fetch big commit from upstream

This commit is contained in:
r3df0xx
2022-05-27 22:12:40 +03:00
parent 697b016805
commit 6634999113
68 changed files with 655 additions and 475 deletions

View File

@@ -1,4 +1,5 @@
#include "bad_usb_app_i.h"
#include "m-string.h"
#include <furi.h>
#include <furi_hal.h>
#include <storage/storage.h>
@@ -22,33 +23,13 @@ static void bad_usb_app_tick_event_callback(void* context) {
scene_manager_handle_tick_event(app->scene_manager);
}
static bool bad_usb_check_assets() {
Storage* fs_api = furi_record_open("storage");
File* dir = storage_file_alloc(fs_api);
bool ret = false;
if(storage_dir_open(dir, BAD_USB_APP_PATH_FOLDER)) {
ret = true;
}
storage_dir_close(dir);
storage_file_free(dir);
furi_record_close("storage");
return ret;
}
BadUsbApp* bad_usb_app_alloc(char* arg) {
BadUsbApp* app = malloc(sizeof(BadUsbApp));
string_init(app->file_path);
if(arg != NULL) {
string_t filename;
string_init(filename);
path_extract_filename_no_ext(arg, filename);
strncpy(app->file_name, string_get_cstr(filename), BAD_USB_FILE_NAME_LEN);
string_clear(filename);
string_set_str(app->file_path, arg);
}
app->gui = furi_record_open("gui");
@@ -83,13 +64,11 @@ BadUsbApp* bad_usb_app_alloc(char* arg) {
app->error = BadUsbAppErrorCloseRpc;
scene_manager_next_scene(app->scene_manager, BadUsbSceneError);
} else {
if(*app->file_name != '\0') {
if(!string_empty_p(app->file_path)) {
scene_manager_next_scene(app->scene_manager, BadUsbSceneWork);
} else if(bad_usb_check_assets()) {
scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect);
} else {
app->error = BadUsbAppErrorNoFiles;
scene_manager_next_scene(app->scene_manager, BadUsbSceneError);
string_set_str(app->file_path, BAD_USB_APP_PATH_FOLDER);
scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect);
}
}
@@ -117,6 +96,8 @@ void bad_usb_app_free(BadUsbApp* app) {
furi_record_close("notification");
furi_record_close("dialogs");
string_clear(app->file_path);
free(app);
}

View File

@@ -16,7 +16,6 @@
#define BAD_USB_APP_PATH_FOLDER "/any/badusb"
#define BAD_USB_APP_EXTENSION ".txt"
#define BAD_USB_FILE_NAME_LEN 40
typedef enum {
BadUsbAppErrorNoFiles,
@@ -32,7 +31,7 @@ struct BadUsbApp {
Widget* widget;
BadUsbAppError error;
char file_name[BAD_USB_FILE_NAME_LEN + 1];
string_t file_path;
BadUsb* bad_usb_view;
BadUsbScript* bad_usb_script;
};

View File

@@ -5,14 +5,16 @@
static bool bad_usb_file_select(BadUsbApp* bad_usb) {
furi_assert(bad_usb);
// Input events and views are managed by file_select
bool res = dialog_file_select_show(
// Input events and views are managed by file_browser
bool res = dialog_file_browser_show(
bad_usb->dialogs,
BAD_USB_APP_PATH_FOLDER,
bad_usb->file_path,
bad_usb->file_path,
BAD_USB_APP_EXTENSION,
bad_usb->file_name,
sizeof(bad_usb->file_name),
NULL);
true,
&I_badusb_10px,
true);
return res;
}

View File

@@ -2,6 +2,8 @@
#include "../bad_usb_app_i.h"
#include "../views/bad_usb_view.h"
#include "furi_hal.h"
#include "m-string.h"
#include "toolbox/path.h"
void bad_usb_scene_work_ok_callback(InputType type, void* context) {
furi_assert(context);
@@ -28,10 +30,9 @@ void bad_usb_scene_work_on_enter(void* context) {
string_t file_name;
string_init(file_name);
bad_usb_set_file_name(app->bad_usb_view, app->file_name);
string_printf(
file_name, "%s/%s%s", BAD_USB_APP_PATH_FOLDER, app->file_name, BAD_USB_APP_EXTENSION);
app->bad_usb_script = bad_usb_script_open(file_name);
path_extract_filename(app->file_path, file_name, true);
bad_usb_set_file_name(app->bad_usb_view, string_get_cstr(file_name));
app->bad_usb_script = bad_usb_script_open(app->file_path);
string_clear(file_name);

View File

@@ -2,6 +2,8 @@
#include "../bad_usb_script.h"
#include <gui/elements.h>
#define MAX_NAME_LEN 64
struct BadUsb {
View* view;
BadUsbOkCallback callback;
@@ -9,7 +11,7 @@ struct BadUsb {
};
typedef struct {
char* file_name;
char file_name[MAX_NAME_LEN];
BadUsbState state;
uint8_t anim_frame;
} BadUsbModel;
@@ -149,11 +151,11 @@ void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* c
});
}
void bad_usb_set_file_name(BadUsb* bad_usb, char* name) {
void bad_usb_set_file_name(BadUsb* bad_usb, const char* name) {
furi_assert(name);
with_view_model(
bad_usb->view, (BadUsbModel * model) {
model->file_name = name;
strncpy(model->file_name, name, MAX_NAME_LEN);
return true;
});
}

View File

@@ -14,6 +14,6 @@ View* bad_usb_get_view(BadUsb* bad_usb);
void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* context);
void bad_usb_set_file_name(BadUsb* bad_usb, char* name);
void bad_usb_set_file_name(BadUsb* bad_usb, const char* name);
void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st);

View File

@@ -48,7 +48,7 @@ FileBrowserApp* file_browser_app_alloc(char* arg) {
app->widget = widget_alloc();
string_init(app->file_path);
app->file_browser = file_browser_alloc(&(app->file_path));
app->file_browser = file_browser_alloc(app->file_path);
file_browser_configure(app->file_browser, "*", true, &I_badusb_10px, true);
view_dispatcher_add_view(

View File

@@ -20,12 +20,10 @@ bool file_browser_scene_browser_on_event(void* context, SceneManagerEvent event)
return consumed;
}
static void file_browser_callback(void* context, bool state) {
static void file_browser_callback(void* context) {
FileBrowserApp* app = context;
furi_assert(app);
view_dispatcher_send_custom_event(app->view_dispatcher, SceneManagerEventTypeCustom);
UNUSED(state);
}
void file_browser_scene_browser_on_enter(void* context) {

View File

@@ -56,12 +56,7 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) {
return true;
case DesktopGlobalAutoLock:
if(!loader_is_locked(desktop->loader)) {
if(desktop->settings.pin_code.length > 0) {
desktop_pin_lock(&desktop->settings);
desktop_lock(desktop);
} else {
desktop_lock(desktop);
}
desktop_lock(desktop);
}
return true;
}

View File

@@ -1,6 +1,7 @@
#include "dialogs/dialogs_message.h"
#include "dialogs_i.h"
#include "dialogs_api_lock.h"
#include "dialogs_module_file_select.h"
#include "dialogs_module_file_browser.h"
#include "dialogs_module_message.h"
static DialogsApp* dialogs_app_alloc() {
@@ -13,9 +14,9 @@ static DialogsApp* dialogs_app_alloc() {
static void dialogs_app_process_message(DialogsApp* app, DialogsAppMessage* message) {
UNUSED(app);
switch(message->command) {
case DialogsAppCommandFileOpen:
case DialogsAppCommandFileBrowser:
message->return_data->bool_value =
dialogs_app_process_module_file_select(&message->data->file_select);
dialogs_app_process_module_file_browser(&message->data->file_browser);
break;
case DialogsAppCommandDialog:
message->return_data->dialog_value =

View File

@@ -1,6 +1,7 @@
#pragma once
#include <furi.h>
#include <gui/canvas.h>
#include "m-string.h"
#ifdef __cplusplus
extern "C" {
@@ -10,25 +11,27 @@ extern "C" {
typedef struct DialogsApp DialogsApp;
/****************** FILE SELECT ******************/
/****************** FILE BROWSER ******************/
/**
* Shows and processes the file selection dialog
* Shows and processes the file browser dialog
* @param context api pointer
* @param path path to directory
* @param result_path selected file path string pointer
* @param path preselected file path string pointer
* @param extension file extension to be offered for selection
* @param selected_filename buffer where the selected filename will be saved
* @param selected_filename_size and the size of this buffer
* @param preselected_filename filename to be preselected
* @param skip_assets true - do not show assets folders
* @param icon file icon pointer, NULL for default icon
* @param hide_ext true - hide extensions for files
* @return bool whether a file was selected
*/
bool dialog_file_select_show(
bool dialog_file_browser_show(
DialogsApp* context,
const char* path,
string_ptr result_path,
string_ptr path,
const char* extension,
char* result,
uint8_t result_size,
const char* preselected_filename);
bool skip_assets,
const Icon* icon,
bool hide_ext);
/****************** MESSAGE ******************/

View File

@@ -1,31 +1,36 @@
#include "dialogs/dialogs_message.h"
#include "dialogs_i.h"
#include "dialogs_api_lock.h"
#include "m-string.h"
/****************** File select ******************/
/****************** File browser ******************/
bool dialog_file_select_show(
bool dialog_file_browser_show(
DialogsApp* context,
const char* path,
string_ptr result_path,
string_ptr path,
const char* extension,
char* result,
uint8_t result_size,
const char* preselected_filename) {
bool skip_assets,
const Icon* icon,
bool hide_ext) {
FuriApiLock lock = API_LOCK_INIT_LOCKED();
furi_check(lock != NULL);
DialogsAppData data = {
.file_select = {
.path = path,
.file_browser = {
.extension = extension,
.result = result,
.result_size = result_size,
.preselected_filename = preselected_filename,
.result_path = result_path,
.file_icon = icon,
.hide_ext = hide_ext,
.skip_assets = skip_assets,
.preselected_filename = path,
}};
DialogsAppReturn return_data;
DialogsAppMessage message = {
.lock = lock,
.command = DialogsAppCommandFileOpen,
.command = DialogsAppCommandFileBrowser,
.data = &data,
.return_data = &return_data,
};

View File

@@ -2,25 +2,27 @@
#include <furi.h>
#include "dialogs_i.h"
#include "dialogs_api_lock.h"
#include "m-string.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
const char* path;
const char* extension;
char* result;
uint8_t result_size;
const char* preselected_filename;
} DialogsAppMessageDataFileSelect;
bool skip_assets;
bool hide_ext;
const Icon* file_icon;
string_ptr result_path;
string_ptr preselected_filename;
} DialogsAppMessageDataFileBrowser;
typedef struct {
const DialogMessage* message;
} DialogsAppMessageDataDialog;
typedef union {
DialogsAppMessageDataFileSelect file_select;
DialogsAppMessageDataFileBrowser file_browser;
DialogsAppMessageDataDialog dialog;
} DialogsAppData;
@@ -30,7 +32,7 @@ typedef union {
} DialogsAppReturn;
typedef enum {
DialogsAppCommandFileOpen,
DialogsAppCommandFileBrowser,
DialogsAppCommandDialog,
} DialogsAppCommand;

View File

@@ -0,0 +1,59 @@
#include "dialogs_i.h"
#include "dialogs_api_lock.h"
#include "gui/modules/file_browser.h"
typedef struct {
FuriApiLock lock;
bool result;
} DialogsAppFileBrowserContext;
static void dialogs_app_file_browser_back_callback(void* context) {
furi_assert(context);
DialogsAppFileBrowserContext* file_browser_context = context;
file_browser_context->result = false;
API_LOCK_UNLOCK(file_browser_context->lock);
}
static void dialogs_app_file_browser_callback(void* context) {
furi_assert(context);
DialogsAppFileBrowserContext* file_browser_context = context;
file_browser_context->result = true;
API_LOCK_UNLOCK(file_browser_context->lock);
}
bool dialogs_app_process_module_file_browser(const DialogsAppMessageDataFileBrowser* data) {
bool ret = false;
Gui* gui = furi_record_open("gui");
DialogsAppFileBrowserContext* file_browser_context =
malloc(sizeof(DialogsAppFileBrowserContext));
file_browser_context->lock = API_LOCK_INIT_LOCKED();
ViewHolder* view_holder = view_holder_alloc();
view_holder_attach_to_gui(view_holder, gui);
view_holder_set_back_callback(
view_holder, dialogs_app_file_browser_back_callback, file_browser_context);
FileBrowser* file_browser = file_browser_alloc(data->result_path);
file_browser_set_callback(
file_browser, dialogs_app_file_browser_callback, file_browser_context);
file_browser_configure(
file_browser, data->extension, data->skip_assets, data->file_icon, data->hide_ext);
file_browser_start(file_browser, data->preselected_filename);
view_holder_set_view(view_holder, file_browser_get_view(file_browser));
view_holder_start(view_holder);
API_LOCK_WAIT_UNTIL_UNLOCK(file_browser_context->lock);
ret = file_browser_context->result;
view_holder_stop(view_holder);
view_holder_free(view_holder);
file_browser_stop(file_browser);
file_browser_free(file_browser);
API_LOCK_FREE(file_browser_context->lock);
free(file_browser_context);
furi_record_close("gui");
return ret;
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include "dialogs_message.h"
#ifdef __cplusplus
extern "C" {
#endif
bool dialogs_app_process_module_file_browser(const DialogsAppMessageDataFileBrowser* data);
#ifdef __cplusplus
}
#endif

View File

@@ -10,6 +10,7 @@
#include <m-array.h>
#include <gui/elements.h>
#include <furi.h>
#include "toolbox/path.h"
#define LIST_ITEMS 5u
#define MAX_LEN_PX 110
@@ -60,13 +61,13 @@ ARRAY_DEF(
struct FileBrowser {
View* view;
BrowserWorker* worker;
char* ext_filter;
const char* ext_filter;
bool skip_assets;
FileBrowserCallback callback;
void* context;
string_t* result_path;
string_ptr result_path;
};
typedef struct {
@@ -100,7 +101,7 @@ static void browser_list_load_cb(void* context, uint32_t list_load_offset);
static void browser_list_item_cb(void* context, string_t item_path, bool is_folder, bool is_last);
static void browser_long_load_cb(void* context);
FileBrowser* file_browser_alloc(string_t* result_path) {
FileBrowser* file_browser_alloc(string_ptr result_path) {
furi_assert(result_path);
FileBrowser* browser = malloc(sizeof(FileBrowser));
browser->view = view_alloc();
@@ -140,7 +141,7 @@ View* file_browser_get_view(FileBrowser* browser) {
void file_browser_configure(
FileBrowser* browser,
char* extension,
const char* extension,
bool skip_assets,
const Icon* file_icon,
bool hide_ext) {
@@ -250,6 +251,7 @@ static void
with_view_model(
browser->view, (FileBrowserModel * model) {
items_array_reset(model->items);
if(is_root) {
model->item_cnt = item_cnt;
model->item_idx = (file_idx > 0) ? file_idx : 0;
@@ -383,7 +385,7 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) {
BrowserItem_t* item = items_array_get(
model->items, CLAMP(idx - model->array_offset, (int32_t)(array_size - 1), 0));
item_type = item->type;
file_browser_worker_get_filename(
path_extract_filename(
item->path, filename, (model->hide_ext) && (item_type == BrowserItemTypeFile));
} else {
string_set_str(filename, "---");
@@ -505,9 +507,9 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
file_browser_worker_folder_enter(
browser->worker, selected_item->path, select_index);
} else if(selected_item->type == BrowserItemTypeFile) {
string_set(*(browser->result_path), selected_item->path);
string_set(browser->result_path, selected_item->path);
if(browser->callback) {
browser->callback(browser->context, true);
browser->callback(browser->context);
}
}
}

View File

@@ -13,9 +13,9 @@ extern "C" {
#endif
typedef struct FileBrowser FileBrowser;
typedef void (*FileBrowserCallback)(void* context, bool state);
typedef void (*FileBrowserCallback)(void* context);
FileBrowser* file_browser_alloc(string_t* result_path);
FileBrowser* file_browser_alloc(string_ptr result_path);
void file_browser_free(FileBrowser* browser);
@@ -23,7 +23,7 @@ View* file_browser_get_view(FileBrowser* browser);
void file_browser_configure(
FileBrowser* browser,
char* extension,
const char* extension,
bool skip_assets,
const Icon* file_icon,
bool hide_ext);

View File

@@ -8,6 +8,7 @@
#include <storage/storage.h>
#include <furi.h>
#include <stddef.h>
#include "toolbox/path.h"
#define TAG "BrowserWorker"
@@ -149,6 +150,7 @@ static bool browser_folder_init(
(*item_cnt)++;
}
if(total_files_cnt == LONG_LOAD_THRESHOLD) {
// There are too many files in folder and counting them will take some time - send callback to app
if(browser->long_load_cb) {
browser->long_load_cb(browser->cb_ctx);
}
@@ -255,7 +257,7 @@ static int32_t browser_worker(void* context) {
string_t filename;
string_init(filename);
if(browser_path_is_file(browser->path_next)) {
file_browser_worker_get_filename(browser->path_next, filename, false);
path_extract_filename(browser->path_next, filename, false);
}
osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtFolderEnter);
@@ -319,21 +321,7 @@ static int32_t browser_worker(void* context) {
return 0;
}
void file_browser_worker_get_filename(string_t path, string_t name, bool trim_ext) {
size_t filename_start = string_search_rchar(path, '/');
if(filename_start > 0) {
filename_start++;
string_set_n(name, path, filename_start, string_size(path) - filename_start);
}
if(trim_ext) {
size_t dot = string_search_rchar(name, '.');
if(dot > 0) {
string_left(name, dot);
}
}
}
BrowserWorker* file_browser_worker_alloc(string_t path, char* filter_ext, bool skip_assets) {
BrowserWorker* file_browser_worker_alloc(string_t path, const char* filter_ext, bool skip_assets) {
BrowserWorker* browser = malloc(sizeof(BrowserWorker));
idx_last_array_init(browser->idx_last);

View File

@@ -22,9 +22,7 @@ typedef void (*BrowserWorkerListItemCallback)(
bool is_last);
typedef void (*BrowserWorkerLongLoadCallback)(void* context);
void file_browser_worker_get_filename(string_t path, string_t name, bool trim_ext);
BrowserWorker* file_browser_worker_alloc(string_t path, char* filter_ext, bool skip_assets);
BrowserWorker* file_browser_worker_alloc(string_t path, const char* filter_ext, bool skip_assets);
void file_browser_worker_free(BrowserWorker* browser);

View File

@@ -3,7 +3,7 @@
#include "applications/storage/storage.h"
struct ValidatorIsFile {
const char* app_path_folder;
char* app_path_folder;
const char* app_extension;
char* current_name;
};
@@ -40,7 +40,7 @@ ValidatorIsFile* validator_is_file_alloc_init(
const char* current_name) {
ValidatorIsFile* instance = malloc(sizeof(ValidatorIsFile));
instance->app_path_folder = app_path_folder;
instance->app_path_folder = strdup(app_path_folder);
instance->app_extension = app_extension;
instance->current_name = strdup(current_name);
@@ -49,6 +49,7 @@ ValidatorIsFile* validator_is_file_alloc_init(
void validator_is_file_free(ValidatorIsFile* instance) {
furi_assert(instance);
free(instance->app_path_folder);
free(instance->current_name);
free(instance);
}

View File

@@ -1,7 +1,8 @@
#include "ibutton.h"
#include "assets_icons.h"
#include "ibutton_i.h"
#include "ibutton/scenes/ibutton_scene.h"
#include "m-string.h"
#include <toolbox/path.h>
#include <flipper_format/flipper_format.h>
@@ -85,6 +86,8 @@ void ibutton_tick_event_callback(void* context) {
iButton* ibutton_alloc() {
iButton* ibutton = malloc(sizeof(iButton));
string_init(ibutton->file_path);
ibutton->scene_manager = scene_manager_alloc(&ibutton_scene_handlers, ibutton);
ibutton->view_dispatcher = view_dispatcher_alloc();
@@ -176,49 +179,28 @@ void ibutton_free(iButton* ibutton) {
ibutton_worker_free(ibutton->key_worker);
ibutton_key_free(ibutton->key);
string_clear(ibutton->file_path);
free(ibutton);
}
bool ibutton_file_select(iButton* ibutton) {
bool success = dialog_file_select_show(
bool success = dialog_file_browser_show(
ibutton->dialogs,
IBUTTON_APP_FOLDER,
ibutton->file_path,
ibutton->file_path,
IBUTTON_APP_EXTENSION,
ibutton->file_name,
IBUTTON_FILE_NAME_SIZE,
ibutton_key_get_name_p(ibutton->key));
true,
&I_ibutt_10px,
true);
if(success) {
string_t key_str;
string_init_printf(
key_str, "%s/%s%s", IBUTTON_APP_FOLDER, ibutton->file_name, IBUTTON_APP_EXTENSION);
success = ibutton_load_key_data(ibutton, key_str);
if(success) {
ibutton_key_set_name(ibutton->key, ibutton->file_name);
}
string_clear(key_str);
success = ibutton_load_key_data(ibutton, ibutton->file_path);
}
return success;
}
bool ibutton_load_key(iButton* ibutton, const char* key_name) {
string_t key_path;
string_init_set_str(key_path, key_name);
const bool success = ibutton_load_key_data(ibutton, key_path);
if(success) {
path_extract_filename_no_ext(key_name, key_path);
ibutton_key_set_name(ibutton->key, string_get_cstr(key_path));
}
string_clear(key_path);
return success;
}
bool ibutton_save_key(iButton* ibutton, const char* key_name) {
// Create ibutton directory if necessary
ibutton_make_app_folder(ibutton);
@@ -226,27 +208,22 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name) {
FlipperFormat* file = flipper_format_file_alloc(ibutton->storage);
iButtonKey* key = ibutton->key;
string_t key_file_name;
bool result = false;
string_init(key_file_name);
do {
// First remove key if it was saved (we rename the key)
if(!ibutton_delete_key(ibutton)) break;
// Save the key
ibutton_key_set_name(key, key_name);
ibutton_delete_key(ibutton);
// Set full file name, for new key
string_printf(
key_file_name,
"%s/%s%s",
IBUTTON_APP_FOLDER,
ibutton_key_get_name_p(key),
IBUTTON_APP_EXTENSION);
if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
size_t filename_start = string_search_rchar(ibutton->file_path, '/');
string_left(ibutton->file_path, filename_start);
}
string_cat_printf(ibutton->file_path, "/%s%s", key_name, IBUTTON_APP_EXTENSION);
// Open file for write
if(!flipper_format_file_open_always(file, string_get_cstr(key_file_name))) break;
if(!flipper_format_file_open_always(file, string_get_cstr(ibutton->file_path))) break;
// Write header
if(!flipper_format_write_header_cstr(file, IBUTTON_APP_FILE_TYPE, 1)) break;
@@ -271,8 +248,6 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name) {
flipper_format_free(file);
string_clear(key_file_name);
if(!result) {
dialog_message_show_storage_error(ibutton->dialogs, "Cannot save\nkey file");
}
@@ -281,17 +256,8 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name) {
}
bool ibutton_delete_key(iButton* ibutton) {
string_t file_name;
bool result = false;
string_init_printf(
file_name,
"%s/%s%s",
IBUTTON_APP_FOLDER,
ibutton_key_get_name_p(ibutton->key),
IBUTTON_APP_EXTENSION);
result = storage_simply_remove(ibutton->storage, string_get_cstr(file_name));
string_clear(file_name);
result = storage_simply_remove(ibutton->storage, string_get_cstr(ibutton->file_path));
return result;
}
@@ -335,8 +301,17 @@ int32_t ibutton_app(void* p) {
ibutton_make_app_folder(ibutton);
if(p && ibutton_load_key(ibutton, (const char*)p)) {
// TODO: Display an error if the key from p could not be loaded
bool key_loaded = false;
if(p) {
string_set_str(ibutton->file_path, (const char*)p);
if(ibutton_load_key_data(ibutton, ibutton->file_path)) {
key_loaded = true;
// TODO: Display an error if the key from p could not be loaded
}
}
if(key_loaded) {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate);
} else {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneStart);

View File

@@ -41,7 +41,7 @@ struct iButton {
iButtonWorker* key_worker;
iButtonKey* key;
char file_name[IBUTTON_FILE_NAME_SIZE];
string_t file_path;
char text_store[IBUTTON_TEXT_STORE_SIZE + 1];
Submenu* submenu;
@@ -74,7 +74,6 @@ typedef enum {
} iButtonNotificationMessage;
bool ibutton_file_select(iButton* ibutton);
bool ibutton_load_key(iButton* ibutton, const char* key_name);
bool ibutton_save_key(iButton* ibutton, const char* key_name);
bool ibutton_delete_key(iButton* ibutton);
void ibutton_text_store_set(iButton* ibutton, const char* text, ...);

View File

@@ -1,4 +1,5 @@
#include "../ibutton_i.h"
#include "m-string.h"
enum SubmenuIndex {
SubmenuIndexCyfral,
@@ -44,7 +45,7 @@ bool ibutton_scene_add_type_on_event(void* context, SceneManagerEvent event) {
furi_crash("Unknown key type");
}
ibutton_key_set_name(key, "");
string_set_str(ibutton->file_path, IBUTTON_APP_FOLDER);
ibutton_key_clear_data(key);
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddValue);
}

View File

@@ -1,4 +1,5 @@
#include "../ibutton_i.h"
#include <toolbox/path.h>
static void ibutton_scene_delete_confirm_widget_callback(
GuiButtonType result,
@@ -16,7 +17,11 @@ void ibutton_scene_delete_confirm_on_enter(void* context) {
iButtonKey* key = ibutton->key;
const uint8_t* key_data = ibutton_key_get_data_p(key);
ibutton_text_store_set(ibutton, "\e#Delete %s?\e#", ibutton_key_get_name_p(key));
string_t key_name;
string_init(key_name);
path_extract_filename(ibutton->file_path, key_name, true);
ibutton_text_store_set(ibutton, "\e#Delete %s?\e#", string_get_cstr(key_name));
widget_add_text_box_element(
widget, 0, 0, 128, 27, AlignCenter, AlignCenter, ibutton->text_store, false);
widget_add_button_element(
@@ -62,6 +67,8 @@ void ibutton_scene_delete_confirm_on_enter(void* context) {
widget, 64, 33, AlignCenter, AlignBottom, FontSecondary, ibutton->text_store);
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
string_clear(key_name);
}
bool ibutton_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) {

View File

@@ -1,5 +1,6 @@
#include "../ibutton_i.h"
#include <dolphin/dolphin.h>
#include <toolbox/path.h>
static void ibutton_scene_emulate_callback(void* context, bool emulated) {
iButton* ibutton = context;
@@ -15,14 +16,19 @@ void ibutton_scene_emulate_on_enter(void* context) {
iButtonKey* key = ibutton->key;
const uint8_t* key_data = ibutton_key_get_data_p(key);
const char* key_name = ibutton_key_get_name_p(key);
string_t key_name;
string_init(key_name);
if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
path_extract_filename(ibutton->file_path, key_name, true);
}
uint8_t line_count = 2;
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
// check that stored key has name
if(strcmp(key_name, "") != 0) {
ibutton_text_store_set(ibutton, "emulating\n%s", key_name);
if(!string_empty_p(key_name)) {
ibutton_text_store_set(ibutton, "emulating\n%s", string_get_cstr(key_name));
line_count = 2;
} else {
// if not, show key data
@@ -77,6 +83,8 @@ void ibutton_scene_emulate_on_enter(void* context) {
ibutton_worker_emulate_set_callback(
ibutton->key_worker, ibutton_scene_emulate_callback, ibutton);
ibutton_worker_emulate_start(ibutton->key_worker, key);
string_clear(key_name);
}
bool ibutton_scene_emulate_on_event(void* context, SceneManagerEvent event) {

View File

@@ -1,4 +1,5 @@
#include "../ibutton_i.h"
#include <toolbox/path.h>
void ibutton_scene_info_on_enter(void* context) {
iButton* ibutton = context;
@@ -7,7 +8,11 @@ void ibutton_scene_info_on_enter(void* context) {
const uint8_t* key_data = ibutton_key_get_data_p(key);
ibutton_text_store_set(ibutton, "%s", ibutton_key_get_name_p(key));
string_t key_name;
string_init(key_name);
path_extract_filename(ibutton->file_path, key_name, true);
ibutton_text_store_set(ibutton, "%s", string_get_cstr(key_name));
widget_add_text_box_element(
widget, 0, 0, 128, 28, AlignCenter, AlignCenter, ibutton->text_store, false);
@@ -46,6 +51,8 @@ void ibutton_scene_info_on_enter(void* context) {
widget, 64, 35, AlignCenter, AlignBottom, FontPrimary, ibutton->text_store);
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
string_clear(key_name);
}
bool ibutton_scene_info_on_event(void* context, SceneManagerEvent event) {

View File

@@ -18,7 +18,7 @@ void ibutton_scene_read_on_enter(void* context) {
popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59);
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
ibutton_key_set_name(key, "");
string_set_str(ibutton->file_path, IBUTTON_APP_FOLDER);
ibutton_worker_read_set_callback(worker, ibutton_scene_read_callback, ibutton);
ibutton_worker_read_start(worker, key);

View File

@@ -1,5 +1,7 @@
#include "../ibutton_i.h"
#include "m-string.h"
#include <lib/toolbox/random_name.h>
#include <toolbox/path.h>
static void ibutton_scene_save_name_text_input_callback(void* context) {
iButton* ibutton = context;
@@ -10,13 +12,17 @@ void ibutton_scene_save_name_on_enter(void* context) {
iButton* ibutton = context;
TextInput* text_input = ibutton->text_input;
const char* key_name = ibutton_key_get_name_p(ibutton->key);
const bool key_name_is_empty = !strcmp(key_name, "");
string_t key_name;
string_init(key_name);
if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
path_extract_filename(ibutton->file_path, key_name, true);
}
const bool key_name_is_empty = string_empty_p(key_name);
if(key_name_is_empty) {
set_random_name(ibutton->text_store, IBUTTON_TEXT_STORE_SIZE);
} else {
ibutton_text_store_set(ibutton, "%s", key_name);
ibutton_text_store_set(ibutton, "%s", string_get_cstr(key_name));
}
text_input_set_header_text(text_input, "Name the key");
@@ -28,11 +34,19 @@ void ibutton_scene_save_name_on_enter(void* context) {
IBUTTON_KEY_NAME_SIZE,
key_name_is_empty);
ValidatorIsFile* validator_is_file =
validator_is_file_alloc_init(IBUTTON_APP_FOLDER, IBUTTON_APP_EXTENSION, key_name);
string_t folder_path;
string_init(folder_path);
path_extract_dirname(string_get_cstr(ibutton->file_path), folder_path);
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
string_get_cstr(folder_path), IBUTTON_APP_EXTENSION, string_get_cstr(key_name));
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewTextInput);
string_clear(key_name);
string_clear(folder_path);
}
bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) {

View File

@@ -36,6 +36,7 @@ bool ibutton_scene_start_on_event(void* context, SceneManagerEvent event) {
if(event.event == SubmenuIndexRead) {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRead);
} else if(event.event == SubmenuIndexSaved) {
string_set_str(ibutton->file_path, IBUTTON_APP_FOLDER);
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSelectKey);
} else if(event.event == SubmenuIndexAdd) {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddType);

View File

@@ -1,4 +1,6 @@
#include "../ibutton_i.h"
#include "m-string.h"
#include "toolbox/path.h"
typedef enum {
iButtonSceneWriteStateDefault,
@@ -17,13 +19,18 @@ void ibutton_scene_write_on_enter(void* context) {
iButtonWorker* worker = ibutton->key_worker;
const uint8_t* key_data = ibutton_key_get_data_p(key);
const char* key_name = ibutton_key_get_name_p(key);
string_t key_name;
string_init(key_name);
if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
path_extract_filename(ibutton->file_path, key_name, true);
}
uint8_t line_count = 2;
// check that stored key has name
if(strcmp(key_name, "") != 0) {
ibutton_text_store_set(ibutton, "writing\n%s", key_name);
if(!string_empty_p(key_name)) {
ibutton_text_store_set(ibutton, "writing\n%s", string_get_cstr(key_name));
line_count = 2;
} else {
// if not, show key data
@@ -79,6 +86,8 @@ void ibutton_scene_write_on_enter(void* context) {
ibutton_worker_write_set_callback(worker, ibutton_scene_write_callback, ibutton);
ibutton_worker_write_start(worker, key);
string_clear(key_name);
}
bool ibutton_scene_write_on_event(void* context, SceneManagerEvent event) {

View File

@@ -1,4 +1,5 @@
#include "infrared_app.h"
#include "m-string.h"
#include <infrared_worker.h>
#include <furi.h>
#include <gui/gui.h>
@@ -12,20 +13,18 @@ int32_t InfraredApp::run(void* args) {
bool exit = false;
if(args) {
std::string path = static_cast<const char*>(args);
std::string remote_name(path, path.find_last_of('/') + 1, path.size());
auto last_dot = remote_name.find_last_of('.');
if(last_dot != std::string::npos) {
remote_name.erase(last_dot);
path.erase(path.find_last_of('/'));
bool result = remote_manager.load(path, remote_name);
string_t path;
string_init_set_str(path, (char*)args);
if(string_end_with_str_p(path, InfraredApp::infrared_extension)) {
bool result = remote_manager.load(path);
if(result) {
current_scene = InfraredApp::Scene::Remote;
} else {
printf("Failed to load remote \'%s\'\r\n", remote_name.c_str());
printf("Failed to load remote \'%s\'\r\n", string_get_cstr(path));
return -1;
}
}
string_clear(path);
}
scenes[current_scene]->on_enter(this);
@@ -51,6 +50,7 @@ int32_t InfraredApp::run(void* args) {
InfraredApp::InfraredApp() {
furi_check(InfraredAppRemoteManager::max_button_name_length < get_text_store_size());
string_init_set_str(file_path, InfraredApp::infrared_directory);
notification = static_cast<NotificationApp*>(furi_record_open("notification"));
dialogs = static_cast<DialogsApp*>(furi_record_open("dialogs"));
infrared_worker = infrared_worker_alloc();
@@ -60,6 +60,7 @@ InfraredApp::~InfraredApp() {
infrared_worker_free(infrared_worker);
furi_record_close("notification");
furi_record_close("dialogs");
string_clear(file_path);
for(auto& [key, scene] : scenes) delete scene;
}

View File

@@ -251,6 +251,8 @@ public:
/** Main class destructor, deinitializes all critical objects */
~InfraredApp();
string_t file_path;
/** Path to Infrared directory */
static constexpr const char* infrared_directory = "/any/infrared";
/** Infrared files extension (remote files and universal databases) */

View File

@@ -1,3 +1,5 @@
#include "m-string.h"
#include "storage/filesystem_api_defines.h"
#include <flipper_format/flipper_format.h>
#include "infrared_app_remote_manager.h"
#include "infrared/helpers/infrared_parser.h"
@@ -11,44 +13,58 @@
#include <gui/modules/button_menu.h>
#include <storage/storage.h>
#include "infrared_app.h"
#include <toolbox/path.h>
static const char* default_remote_name = "remote";
std::string InfraredAppRemoteManager::make_full_name(
const std::string& path,
const std::string& remote_name) const {
return std::string("") + path + "/" + remote_name + InfraredApp::infrared_extension;
}
std::string InfraredAppRemoteManager::find_vacant_remote_name(const std::string& name) {
std::string result_name;
void InfraredAppRemoteManager::find_vacant_remote_name(string_t name, string_t path) {
Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
FS_Error error = storage_common_stat(
storage, make_full_name(InfraredApp::infrared_directory, name).c_str(), NULL);
string_t base_path;
string_init_set(base_path, path);
if(error == FSE_NOT_EXIST) {
result_name = name;
} else if(error != FSE_OK) {
result_name = std::string();
} else {
if(string_end_with_str_p(base_path, InfraredApp::infrared_extension)) {
size_t filename_start = string_search_rchar(base_path, '/');
string_left(base_path, filename_start);
}
string_printf(
base_path,
"%s/%s%s",
string_get_cstr(path),
string_get_cstr(name),
InfraredApp::infrared_extension);
FS_Error error = storage_common_stat(storage, string_get_cstr(base_path), NULL);
if(error == FSE_OK) {
/* if suggested name is occupied, try another one (name2, name3, etc) */
size_t dot = string_search_rchar(base_path, '.');
string_left(base_path, dot);
string_t path_temp;
string_init(path_temp);
uint32_t i = 1;
std::string new_name;
do {
new_name = make_full_name(InfraredApp::infrared_directory, name + std::to_string(++i));
error = storage_common_stat(storage, new_name.c_str(), NULL);
string_printf(
path_temp,
"%s%u%s",
string_get_cstr(base_path),
++i,
InfraredApp::infrared_extension);
error = storage_common_stat(storage, string_get_cstr(path_temp), NULL);
} while(error == FSE_OK);
string_clear(path_temp);
if(error == FSE_NOT_EXIST) {
result_name = name + std::to_string(i);
} else {
result_name = std::string();
string_cat_printf(name, "%u", i);
}
}
string_clear(base_path);
furi_record_close("storage");
return result_name;
}
bool InfraredAppRemoteManager::add_button(const char* button_name, const InfraredAppSignal& signal) {
@@ -61,12 +77,23 @@ bool InfraredAppRemoteManager::add_remote_with_button(
const InfraredAppSignal& signal) {
furi_check(button_name != nullptr);
auto new_name = find_vacant_remote_name(default_remote_name);
if(new_name.empty()) {
return false;
}
string_t new_name;
string_init_set_str(new_name, default_remote_name);
string_t new_path;
string_init_set_str(new_path, InfraredApp::infrared_directory);
find_vacant_remote_name(new_name, new_path);
string_cat_printf(
new_path, "/%s%s", string_get_cstr(new_name), InfraredApp::infrared_extension);
remote = std::make_unique<InfraredAppRemote>(new_path);
remote->name = std::string(string_get_cstr(new_name));
string_clear(new_path);
string_clear(new_name);
remote = std::make_unique<InfraredAppRemote>(InfraredApp::infrared_directory, new_name);
return add_button(button_name, signal);
}
@@ -93,8 +120,7 @@ const InfraredAppSignal& InfraredAppRemoteManager::get_button_data(size_t index)
bool InfraredAppRemoteManager::delete_remote() {
Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
FS_Error error =
storage_common_remove(storage, make_full_name(remote->path, remote->name).c_str());
FS_Error error = storage_common_remove(storage, string_get_cstr(remote->path));
reset_remote();
furi_record_close("storage");
@@ -128,22 +154,33 @@ std::string InfraredAppRemoteManager::get_remote_name() {
bool InfraredAppRemoteManager::rename_remote(const char* str) {
furi_check(str != nullptr);
furi_check(remote.get() != nullptr);
furi_check(!string_empty_p(remote->path));
if(!remote->name.compare(str)) {
return true;
}
auto new_name = find_vacant_remote_name(str);
if(new_name.empty()) {
return false;
string_t new_name;
string_init_set_str(new_name, str);
find_vacant_remote_name(new_name, remote->path);
string_t new_path;
string_init_set(new_path, remote->path);
if(string_end_with_str_p(new_path, InfraredApp::infrared_extension)) {
size_t filename_start = string_search_rchar(new_path, '/');
string_left(new_path, filename_start);
}
string_cat_printf(
new_path, "/%s%s", string_get_cstr(new_name), InfraredApp::infrared_extension);
Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
std::string old_filename = make_full_name(remote->path, remote->name);
std::string new_filename = make_full_name(remote->path, new_name);
FS_Error error = storage_common_rename(storage, old_filename.c_str(), new_filename.c_str());
remote->name = new_name;
FS_Error error =
storage_common_rename(storage, string_get_cstr(remote->path), string_get_cstr(new_path));
remote->name = std::string(string_get_cstr(new_name));
string_clear(new_name);
string_clear(new_path);
furi_record_close("storage");
return (error == FSE_OK || error == FSE_EXIST);
@@ -171,10 +208,8 @@ bool InfraredAppRemoteManager::store(void) {
FlipperFormat* ff = flipper_format_file_alloc(storage);
FURI_LOG_I(
"RemoteManager", "store file: \'%s\'", make_full_name(remote->path, remote->name).c_str());
result =
flipper_format_file_open_always(ff, make_full_name(remote->path, remote->name).c_str());
FURI_LOG_I("RemoteManager", "store file: \'%s\'", string_get_cstr(remote->path));
result = flipper_format_file_open_always(ff, string_get_cstr(remote->path));
if(result) {
result = flipper_format_write_header_cstr(ff, "IR signals file", 1);
}
@@ -192,13 +227,13 @@ bool InfraredAppRemoteManager::store(void) {
return result;
}
bool InfraredAppRemoteManager::load(const std::string& path, const std::string& remote_name) {
bool InfraredAppRemoteManager::load(string_t path) {
bool result = false;
Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
FlipperFormat* ff = flipper_format_file_alloc(storage);
FURI_LOG_I("RemoteManager", "load file: \'%s\'", make_full_name(path, remote_name).c_str());
result = flipper_format_file_open_existing(ff, make_full_name(path, remote_name).c_str());
FURI_LOG_I("RemoteManager", "load file: \'%s\'", string_get_cstr(path));
result = flipper_format_file_open_existing(ff, string_get_cstr(path));
if(result) {
string_t header;
string_init(header);
@@ -210,7 +245,14 @@ bool InfraredAppRemoteManager::load(const std::string& path, const std::string&
string_clear(header);
}
if(result) {
remote = std::make_unique<InfraredAppRemote>(path, remote_name);
string_t new_name;
string_init(new_name);
remote = std::make_unique<InfraredAppRemote>(path);
path_extract_filename(path, new_name, true);
remote->name = std::string(string_get_cstr(new_name));
string_clear(new_name);
InfraredAppSignal signal;
std::string signal_name;
while(infrared_parser_read_signal(ff, signal, signal_name)) {

View File

@@ -8,6 +8,7 @@
#include "infrared_app_signal.h"
#include "m-string.h"
#include <infrared_worker.h>
#include <infrared.h>
@@ -60,17 +61,19 @@ class InfraredAppRemote {
/** Name of remote */
std::string name;
/** Path to remote file */
std::string path;
string_t path;
public:
/** Initialize new remote
*
* @param path - remote file path
* @param name - new remote name
*/
InfraredAppRemote(const std::string& path, const std::string& name)
: name(name)
, path(path) {
InfraredAppRemote(string_t file_path) {
string_init_set(path, file_path);
}
~InfraredAppRemote() {
string_clear(path);
}
};
@@ -78,12 +81,6 @@ public:
class InfraredAppRemoteManager {
/** Remote instance. There can be 1 remote loaded at a time. */
std::unique_ptr<InfraredAppRemote> remote;
/** Make full name from remote name
*
* @param remote_name name of remote
* @retval full name of remote on disk
*/
std::string make_full_name(const std::string& path, const std::string& remote_name) const;
public:
/** Restriction to button name length. Buttons larger are ignored. */
@@ -125,9 +122,9 @@ public:
* incremented digit(2,3,4,etc) added to name and check repeated.
*
* @param name - suggested remote name
* @retval garanteed free remote name, prefixed with suggested
* @param path - remote file path
*/
std::string find_vacant_remote_name(const std::string& name);
void find_vacant_remote_name(string_t name, string_t path);
/** Get button list
*
@@ -185,8 +182,8 @@ public:
/** Load data from disk into current remote
*
* @param name - name of remote to load
* @param path - path to remote file
* @retval true if success, false otherwise
*/
bool load(const std::string& path, const std::string& name);
bool load(string_t path);
};

View File

@@ -1,4 +1,6 @@
#include "../infrared_app.h"
#include "m-string.h"
#include "toolbox/path.h"
void InfraredAppSceneEditRename::on_enter(InfraredApp* app) {
InfraredAppViewManager* view_manager = app->get_view_manager();
@@ -21,9 +23,18 @@ void InfraredAppSceneEditRename::on_enter(InfraredApp* app) {
enter_name_length = InfraredAppRemoteManager::max_remote_name_length;
text_input_set_header_text(text_input, "Name the remote");
string_t folder_path;
string_init(folder_path);
if(string_end_with_str_p(app->file_path, InfraredApp::infrared_extension)) {
path_extract_dirname(string_get_cstr(app->file_path), folder_path);
}
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
app->infrared_directory, app->infrared_extension, remote_name.c_str());
string_get_cstr(folder_path), app->infrared_extension, remote_name.c_str());
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
string_clear(folder_path);
}
text_input_set_result_callback(

View File

@@ -1,4 +1,5 @@
#include "../infrared_app.h"
#include "assets_icons.h"
#include "infrared/infrared_app_event.h"
#include <text_store.h>
@@ -8,11 +9,6 @@ void InfraredAppSceneRemoteList::on_enter(InfraredApp* app) {
bool result = false;
bool file_select_result;
auto remote_manager = app->get_remote_manager();
auto last_selected_remote = remote_manager->get_remote_name();
const char* last_selected_remote_name =
last_selected_remote.size() ? last_selected_remote.c_str() : nullptr;
auto filename_ts =
std::make_unique<TextStore>(InfraredAppRemoteManager::max_remote_name_length);
DialogsApp* dialogs = app->get_dialogs();
InfraredAppViewManager* view_manager = app->get_view_manager();
@@ -20,16 +16,17 @@ void InfraredAppSceneRemoteList::on_enter(InfraredApp* app) {
button_menu_reset(button_menu);
view_manager->switch_to(InfraredAppViewManager::ViewId::ButtonMenu);
file_select_result = dialog_file_select_show(
file_select_result = dialog_file_browser_show(
dialogs,
InfraredApp::infrared_directory,
app->file_path,
app->file_path,
InfraredApp::infrared_extension,
filename_ts->text,
filename_ts->text_size,
last_selected_remote_name);
true,
&I_ir_10px,
true);
if(file_select_result) {
if(remote_manager->load(InfraredApp::infrared_directory, std::string(filename_ts->text))) {
if(remote_manager->load(app->file_path)) {
app->switch_to_next_scene(InfraredApp::Scene::Remote);
result = true;
}

View File

@@ -26,6 +26,8 @@ void InfraredAppSceneStart::on_enter(InfraredApp* app) {
submenu, "Learn New Remote", SubmenuIndexLearnNewRemote, submenu_callback, app);
submenu_add_item(submenu, "Saved Remotes", SubmenuIndexSavedRemotes, submenu_callback, app);
submenu_set_selected_item(submenu, submenu_item_selected);
string_set_str(app->file_path, InfraredApp::infrared_directory);
submenu_item_selected = 0;
view_manager->switch_to(InfraredAppViewManager::ViewId::Submenu);

View File

@@ -1,4 +1,7 @@
#include "lfrfid_app.h"
#include "assets_icons.h"
#include "furi/common_defines.h"
#include "m-string.h"
#include "scene/lfrfid_app_scene_start.h"
#include "scene/lfrfid_app_scene_read.h"
#include "scene/lfrfid_app_scene_read_success.h"
@@ -31,9 +34,11 @@ LfRfidApp::LfRfidApp()
, storage{"storage"}
, dialogs{"dialogs"}
, text_store(40) {
string_init_set_str(file_path, app_folder);
}
LfRfidApp::~LfRfidApp() {
string_clear(file_path);
}
void LfRfidApp::run(void* _args) {
@@ -42,7 +47,8 @@ void LfRfidApp::run(void* _args) {
make_app_folder();
if(strlen(args)) {
load_key_data(args, &worker.key);
string_set_str(file_path, args);
load_key_data(file_path, &worker.key);
scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());
scene_controller.process(100, SceneType::Emulate);
} else {
@@ -69,65 +75,49 @@ void LfRfidApp::run(void* _args) {
}
bool LfRfidApp::save_key(RfidKey* key) {
string_t file_name;
bool result = false;
make_app_folder();
string_init_printf(file_name, "%s/%s%s", app_folder, key->get_name(), app_extension);
result = save_key_data(string_get_cstr(file_name), key);
string_clear(file_name);
if(string_end_with_str_p(file_path, app_extension)) {
size_t filename_start = string_search_rchar(file_path, '/');
string_left(file_path, filename_start);
}
string_cat_printf(file_path, "/%s%s", key->get_name(), app_extension);
result = save_key_data(file_path, key);
return result;
}
bool LfRfidApp::load_key_from_file_select(bool need_restore) {
TextStore* filename_ts = new TextStore(64);
bool result = false;
if(need_restore) {
result = dialog_file_select_show(
dialogs,
app_folder,
app_extension,
filename_ts->text,
filename_ts->text_size,
worker.key.get_name());
} else {
result = dialog_file_select_show(
dialogs, app_folder, app_extension, filename_ts->text, filename_ts->text_size, NULL);
if(!need_restore) {
string_set_str(file_path, app_folder);
}
bool result = dialog_file_browser_show(
dialogs, file_path, file_path, app_extension, true, &I_125_10px, true);
if(result) {
string_t key_str;
string_init_printf(key_str, "%s/%s%s", app_folder, filename_ts->text, app_extension);
result = load_key_data(string_get_cstr(key_str), &worker.key);
string_clear(key_str);
result = load_key_data(file_path, &worker.key);
}
delete filename_ts;
return result;
}
bool LfRfidApp::delete_key(RfidKey* key) {
string_t file_name;
bool result = false;
string_init_printf(file_name, "%s/%s%s", app_folder, key->get_name(), app_extension);
result = storage_simply_remove(storage, string_get_cstr(file_name));
string_clear(file_name);
return result;
UNUSED(key);
return storage_simply_remove(storage, string_get_cstr(file_path));
}
bool LfRfidApp::load_key_data(const char* path, RfidKey* key) {
bool LfRfidApp::load_key_data(string_t path, RfidKey* key) {
FlipperFormat* file = flipper_format_file_alloc(storage);
bool result = false;
string_t str_result;
string_init(str_result);
do {
if(!flipper_format_file_open_existing(file, path)) break;
if(!flipper_format_file_open_existing(file, string_get_cstr(path))) break;
// header
uint32_t version;
@@ -149,7 +139,7 @@ bool LfRfidApp::load_key_data(const char* path, RfidKey* key) {
break;
loaded_key.set_data(key_data, loaded_key.get_type_data_count());
path_extract_filename_no_ext(path, str_result);
path_extract_filename(path, str_result, true);
loaded_key.set_name(string_get_cstr(str_result));
*key = loaded_key;
@@ -166,12 +156,12 @@ bool LfRfidApp::load_key_data(const char* path, RfidKey* key) {
return result;
}
bool LfRfidApp::save_key_data(const char* path, RfidKey* key) {
bool LfRfidApp::save_key_data(string_t path, RfidKey* key) {
FlipperFormat* file = flipper_format_file_alloc(storage);
bool result = false;
do {
if(!flipper_format_file_open_always(file, path)) break;
if(!flipper_format_file_open_always(file, string_get_cstr(path))) break;
if(!flipper_format_write_header_cstr(file, app_filetype, 1)) break;
if(!flipper_format_write_comment_cstr(file, "Key type can be EM4100, H10301 or I40134"))
break;

View File

@@ -1,4 +1,5 @@
#pragma once
#include "m-string.h"
#include <furi.h>
#include <furi_hal.h>
@@ -76,6 +77,8 @@ public:
TextStore text_store;
string_t file_path;
void run(void* args);
static const char* app_folder;
@@ -86,8 +89,8 @@ public:
bool load_key_from_file_select(bool need_restore);
bool delete_key(RfidKey* key);
bool load_key_data(const char* path, RfidKey* key);
bool save_key_data(const char* path, RfidKey* key);
bool load_key_data(string_t path, RfidKey* key);
bool save_key_data(string_t path, RfidKey* key);
void make_app_folder();
};

View File

@@ -1,11 +1,14 @@
#include "lfrfid_app_scene_save_name.h"
#include "m-string.h"
#include <lib/toolbox/random_name.h>
#include <lib/toolbox/path.h>
void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool /* need_restore */) {
const char* key_name = app->worker.key.get_name();
bool key_name_empty = !strcmp(key_name, "");
if(key_name_empty) {
string_set_str(app->file_path, app->app_folder);
set_random_name(app->text_store.text, app->text_store.text_size);
} else {
app->text_store.set("%s", key_name);
@@ -21,10 +24,17 @@ void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool /* need_restore */) {
app->worker.key.get_name_length(),
key_name_empty);
string_t folder_path;
string_init(folder_path);
path_extract_dirname(string_get_cstr(app->file_path), folder_path);
ValidatorIsFile* validator_is_file =
validator_is_file_alloc_init(app->app_folder, app->app_extension, key_name);
validator_is_file_alloc_init(string_get_cstr(folder_path), app->app_extension, key_name);
text_input->set_validator(validator_is_file_callback, validator_is_file);
string_clear(folder_path);
app->view_controller.switch_to<TextInputVM>();
}

View File

@@ -1,3 +1,5 @@
#include "assets_icons.h"
#include "m-string.h"
#include <furi.h>
#include <furi_hal.h>
@@ -298,23 +300,23 @@ int32_t music_player_app(void* p) {
if(p) {
string_cat_str(file_path, p);
} else {
char file_name[256] = {0};
string_set_str(file_path, MUSIC_PLAYER_APP_PATH_FOLDER);
DialogsApp* dialogs = furi_record_open("dialogs");
bool res = dialog_file_select_show(
bool res = dialog_file_browser_show(
dialogs,
MUSIC_PLAYER_APP_PATH_FOLDER,
file_path,
file_path,
MUSIC_PLAYER_APP_EXTENSION,
file_name,
255,
NULL);
true,
&I_music_10px,
false);
furi_record_close("dialogs");
if(!res) {
FURI_LOG_E(TAG, "No file selected");
break;
}
string_cat_str(file_path, MUSIC_PLAYER_APP_PATH_FOLDER);
string_cat_str(file_path, "/");
string_cat_str(file_path, file_name);
}
if(!music_player_worker_load(music_player->worker, string_get_cstr(file_path))) {

View File

@@ -1,4 +1,6 @@
#include "nfc_device.h"
#include "assets_icons.h"
#include "m-string.h"
#include "nfc_types.h"
#include <toolbox/path.h>
@@ -14,6 +16,7 @@ NfcDevice* nfc_device_alloc() {
NfcDevice* nfc_dev = malloc(sizeof(NfcDevice));
nfc_dev->storage = furi_record_open("storage");
nfc_dev->dialogs = furi_record_open("dialogs");
string_init(nfc_dev->load_path);
return nfc_dev;
}
@@ -22,6 +25,7 @@ void nfc_device_free(NfcDevice* nfc_dev) {
nfc_device_clear(nfc_dev);
furi_record_close("storage");
furi_record_close("dialogs");
string_clear(nfc_dev->load_path);
free(nfc_dev);
}
@@ -730,11 +734,24 @@ void nfc_device_set_name(NfcDevice* dev, const char* name) {
strlcpy(dev->dev_name, name, NFC_DEV_NAME_MAX_LEN);
}
static void nfc_device_get_path_without_ext(string_t orig_path, string_t shadow_path) {
// TODO: this won't work if there is ".nfc" anywhere in the path other than
// at the end
size_t ext_start = string_search_str(orig_path, NFC_APP_EXTENSION);
string_set_n(shadow_path, orig_path, 0, ext_start);
}
static void nfc_device_get_shadow_path(string_t orig_path, string_t shadow_path) {
nfc_device_get_path_without_ext(orig_path, shadow_path);
string_cat_printf(shadow_path, "%s", NFC_APP_SHADOW_EXTENSION);
}
static bool nfc_device_save_file(
NfcDevice* dev,
const char* dev_name,
const char* folder,
const char* extension) {
const char* extension,
bool use_load_path) {
furi_assert(dev);
bool saved = false;
@@ -744,10 +761,19 @@ static bool nfc_device_save_file(
string_init(temp_str);
do {
// Create nfc directory if necessary
if(!storage_simply_mkdir(dev->storage, NFC_APP_FOLDER)) break;
// First remove nfc device file if it was saved
string_printf(temp_str, "%s/%s%s", folder, dev_name, extension);
if(use_load_path && !string_empty_p(dev->load_path)) {
// Get directory name
path_extract_dirname(string_get_cstr(dev->load_path), temp_str);
// Create nfc directory if necessary
if(!storage_simply_mkdir(dev->storage, string_get_cstr(temp_str))) break;
// Make path to file to save
string_cat_printf(temp_str, "/%s%s", dev_name, extension);
} else {
// Create nfc directory if necessary
if(!storage_simply_mkdir(dev->storage, NFC_APP_FOLDER)) break;
// First remove nfc device file if it was saved
string_printf(temp_str, "%s/%s%s", folder, dev_name, extension);
}
// Open file
if(!flipper_format_file_open_always(file, string_get_cstr(temp_str))) break;
// Write header
@@ -786,12 +812,12 @@ static bool nfc_device_save_file(
}
bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_EXTENSION);
return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_EXTENSION, true);
}
bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name) {
dev->shadow_file_exist = true;
return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_SHADOW_EXTENSION);
return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_SHADOW_EXTENSION, true);
}
static bool nfc_device_load_data(NfcDevice* dev, string_t path) {
@@ -805,9 +831,7 @@ static bool nfc_device_load_data(NfcDevice* dev, string_t path) {
do {
// Check existance of shadow file
size_t ext_start = string_search_str(path, NFC_APP_EXTENSION);
string_set_n(temp_str, path, 0, ext_start);
string_cat_printf(temp_str, "%s", NFC_APP_SHADOW_EXTENSION);
nfc_device_get_shadow_path(path, temp_str);
dev->shadow_file_exist =
storage_common_stat(dev->storage, string_get_cstr(temp_str), NULL) == FSE_OK;
// Open shadow file if it exists. If not - open original
@@ -864,15 +888,16 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path) {
furi_assert(file_path);
// Load device data
string_t path;
string_init_set_str(path, file_path);
bool dev_load = nfc_device_load_data(dev, path);
string_set_str(dev->load_path, file_path);
bool dev_load = nfc_device_load_data(dev, dev->load_path);
if(dev_load) {
// Set device name
path_extract_filename_no_ext(file_path, path);
nfc_device_set_name(dev, string_get_cstr(path));
string_t filename;
string_init(filename);
path_extract_filename_no_ext(file_path, filename);
nfc_device_set_name(dev, string_get_cstr(filename));
string_clear(filename);
}
string_clear(path);
return dev_load;
}
@@ -880,23 +905,19 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path) {
bool nfc_file_select(NfcDevice* dev) {
furi_assert(dev);
// Input events and views are managed by file_select
bool res = dialog_file_select_show(
dev->dialogs,
NFC_APP_FOLDER,
NFC_APP_EXTENSION,
dev->file_name,
sizeof(dev->file_name),
dev->dev_name);
// Input events and views are managed by file_browser
bool res = dialog_file_browser_show(
dev->dialogs, dev->load_path, dev->load_path, NFC_APP_EXTENSION, true, &I_Nfc_10px, true);
if(res) {
string_t dev_str;
// Get key file path
string_init_printf(dev_str, "%s/%s%s", NFC_APP_FOLDER, dev->file_name, NFC_APP_EXTENSION);
res = nfc_device_load_data(dev, dev_str);
string_t filename;
string_init(filename);
path_extract_filename(dev->load_path, filename, true);
strncpy(dev->dev_name, string_get_cstr(filename), NFC_DEV_NAME_MAX_LEN);
res = nfc_device_load_data(dev, dev->load_path);
if(res) {
nfc_device_set_name(dev, dev->file_name);
nfc_device_set_name(dev, dev->dev_name);
}
string_clear(dev_str);
string_clear(filename);
}
return res;
@@ -914,9 +935,10 @@ void nfc_device_clear(NfcDevice* dev) {
nfc_device_data_clear(&dev->dev_data);
memset(&dev->dev_data, 0, sizeof(dev->dev_data));
dev->format = NfcDeviceSaveFormatUid;
string_set_str(dev->load_path, NFC_APP_FOLDER);
}
bool nfc_device_delete(NfcDevice* dev) {
bool nfc_device_delete(NfcDevice* dev, bool use_load_path) {
furi_assert(dev);
bool deleted = false;
@@ -925,12 +947,20 @@ bool nfc_device_delete(NfcDevice* dev) {
do {
// Delete original file
string_init_printf(file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION);
if(use_load_path && !string_empty_p(dev->load_path)) {
string_set(file_path, dev->load_path);
} else {
string_printf(file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION);
}
if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break;
// Delete shadow file if it exists
if(dev->shadow_file_exist) {
string_printf(
file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION);
if(use_load_path && !string_empty_p(dev->load_path)) {
nfc_device_get_shadow_path(dev->load_path, file_path);
} else {
string_printf(
file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION);
}
if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break;
}
deleted = true;
@@ -944,19 +974,29 @@ bool nfc_device_delete(NfcDevice* dev) {
return deleted;
}
bool nfc_device_restore(NfcDevice* dev) {
bool nfc_device_restore(NfcDevice* dev, bool use_load_path) {
furi_assert(dev);
furi_assert(dev->shadow_file_exist);
bool restored = false;
string_t path;
string_init(path);
do {
string_init_printf(
path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION);
if(use_load_path && !string_empty_p(dev->load_path)) {
nfc_device_get_shadow_path(dev->load_path, path);
} else {
string_printf(
path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION);
}
if(!storage_simply_remove(dev->storage, string_get_cstr(path))) break;
dev->shadow_file_exist = false;
string_printf(path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION);
if(use_load_path && !string_empty_p(dev->load_path)) {
string_set(path, dev->load_path);
} else {
string_printf(path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION);
}
if(!nfc_device_load_data(dev, path)) break;
restored = true;
} while(0);

View File

@@ -12,7 +12,6 @@
#include <lib/nfc_protocols/mifare_desfire.h>
#define NFC_DEV_NAME_MAX_LEN 22
#define NFC_FILE_NAME_MAX_LEN 120
#define NFC_READER_DATA_MAX_SIZE 64
#define NFC_APP_FOLDER "/any/nfc"
@@ -57,7 +56,7 @@ typedef struct {
DialogsApp* dialogs;
NfcDeviceData dev_data;
char dev_name[NFC_DEV_NAME_MAX_LEN + 1];
char file_name[NFC_FILE_NAME_MAX_LEN];
string_t load_path;
NfcDeviceSaveFormat format;
bool shadow_file_exist;
} NfcDevice;
@@ -80,6 +79,6 @@ void nfc_device_data_clear(NfcDeviceData* dev);
void nfc_device_clear(NfcDevice* dev);
bool nfc_device_delete(NfcDevice* dev);
bool nfc_device_delete(NfcDevice* dev, bool use_load_path);
bool nfc_device_restore(NfcDevice* dev);
bool nfc_device_restore(NfcDevice* dev, bool use_load_path);

View File

@@ -73,7 +73,7 @@ bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) {
if(event.event == GuiButtonTypeLeft) {
return scene_manager_previous_scene(nfc->scene_manager);
} else if(event.event == GuiButtonTypeRight) {
if(nfc_device_delete(nfc->dev)) {
if(nfc_device_delete(nfc->dev, true)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess);
} else {
scene_manager_search_and_switch_to_previous_scene(

View File

@@ -1,6 +1,8 @@
#include "../nfc_i.h"
#include "m-string.h"
#include <lib/toolbox/random_name.h>
#include <gui/modules/validators.h>
#include <toolbox/path.h>
void nfc_scene_save_name_text_input_callback(void* context) {
Nfc* nfc = context;
@@ -29,11 +31,22 @@ void nfc_scene_save_name_on_enter(void* context) {
NFC_DEV_NAME_MAX_LEN,
dev_name_empty);
ValidatorIsFile* validator_is_file =
validator_is_file_alloc_init(NFC_APP_FOLDER, NFC_APP_EXTENSION, nfc->dev->dev_name);
string_t folder_path;
string_init(folder_path);
if(string_end_with_str_p(nfc->dev->load_path, NFC_APP_EXTENSION)) {
path_extract_dirname(string_get_cstr(nfc->dev->load_path), folder_path);
} else {
string_set_str(folder_path, NFC_APP_FOLDER);
}
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
string_get_cstr(folder_path), NFC_APP_EXTENSION, nfc->dev->dev_name);
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput);
string_clear(folder_path);
}
bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) {
@@ -43,7 +56,7 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventTextInputDone) {
if(strcmp(nfc->dev->dev_name, "")) {
nfc_device_delete(nfc->dev);
nfc_device_delete(nfc->dev, true);
}
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetUid)) {
nfc->dev->dev_data.nfc_data = nfc->dev_edit_data;

View File

@@ -30,9 +30,6 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneCardMenu)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneCardMenu);
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) {
consumed = scene_manager_search_and_switch_to_another_scene(
nfc->scene_manager, NfcSceneFileSelect);
} else if(scene_manager_has_previous_scene(
nfc->scene_manager, NfcSceneMifareDesfireMenu)) {
consumed = scene_manager_search_and_switch_to_previous_scene(

View File

@@ -78,7 +78,7 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
consumed = true;
} else if(event.event == SubmenuIndexRestoreOriginal) {
if(!nfc_device_restore(nfc->dev)) {
if(!nfc_device_restore(nfc->dev, true)) {
scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneStart);
} else {

View File

@@ -1,4 +1,5 @@
#include "../nfc_i.h"
#include "m-string.h"
enum SubmenuIndex {
SubmenuIndexNFCA4,
@@ -16,6 +17,7 @@ void nfc_scene_set_type_on_enter(void* context) {
Submenu* submenu = nfc->submenu;
// Clear device name
nfc_device_set_name(nfc->dev, "");
string_set_str(nfc->dev->load_path, "");
submenu_add_item(
submenu, "NFC-A 7-bytes UID", SubmenuIndexNFCA7, nfc_scene_set_type_submenu_callback, nfc);
submenu_add_item(

View File

@@ -46,17 +46,16 @@ const char* const volume_text[VOLUME_COUNT] = {
};
const float volume_value[VOLUME_COUNT] = {0.0f, 0.25f, 0.5f, 0.75f, 1.0f};
#define DELAY_COUNT 7
#define DELAY_COUNT 6
const char* const delay_text[DELAY_COUNT] = {
"1s",
"5s",
"15s",
"30s",
"60s",
"90s",
"120s",
};
const uint32_t delay_value[DELAY_COUNT] = {1000, 5000, 15000, 30000, 60000, 90000, 120000};
const uint32_t delay_value[DELAY_COUNT] = {1000, 5000, 15000, 30000, 60000, 120000};
#define VIBRO_COUNT 2
const char* const vibro_text[VIBRO_COUNT] = {

View File

@@ -2,8 +2,6 @@
#include <gui/gui.h>
#include <input/input.h>
#include <stdlib.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
typedef struct {
// +-----x
@@ -300,11 +298,6 @@ static void snake_game_process_game_step(SnakeState* const snake_state) {
bool eatFruit = (next_step.x == snake_state->fruit.x) && (next_step.y == snake_state->fruit.y);
if(eatFruit) {
NotificationApp* notification = furi_record_open("notification");
notification_message(notification, &sequence_single_vibro);
notification_message(notification, &sequence_blink_white_100);
furi_record_close("notification");
snake_state->len++;
if(snake_state->len >= MAX_SNAKE_LEN) {
snake_state->state = GameStateGameOver;

View File

@@ -49,7 +49,7 @@ bool subghz_scene_delete_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventSceneDelete) {
strncpy(subghz->file_path_tmp, subghz->file_path, SUBGHZ_MAX_LEN_NAME);
string_set(subghz->file_path_tmp, subghz->file_path);
if(subghz_delete_file(subghz)) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess);
} else {

View File

@@ -24,7 +24,7 @@ void subghz_scene_delete_raw_on_enter(void* context) {
char delete_str[SUBGHZ_MAX_LEN_NAME + 16];
string_t file_name;
string_init(file_name);
path_extract_filename_no_ext(subghz->file_path, file_name);
path_extract_filename(subghz->file_path, file_name, true);
snprintf(delete_str, sizeof(delete_str), "\e#Delete %s?\e#", string_get_cstr(file_name));
string_clear(file_name);
@@ -61,7 +61,7 @@ bool subghz_scene_delete_raw_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventSceneDeleteRAW) {
strncpy(subghz->file_path_tmp, subghz->file_path, SUBGHZ_MAX_LEN_NAME);
string_set(subghz->file_path_tmp, subghz->file_path);
if(subghz_delete_file(subghz)) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess);
} else {

View File

@@ -45,7 +45,7 @@ bool subghz_scene_more_raw_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteRAW);
return true;
} else if(event.event == SubmenuIndexEdit) {
memset(subghz->file_path_tmp, 0, sizeof(subghz->file_path_tmp));
string_reset(subghz->file_path_tmp);
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneMoreRAW, SubmenuIndexEdit);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);

View File

@@ -1,4 +1,6 @@
#include "../subghz_i.h"
#include "m-string.h"
#include "subghz/types.h"
#include <lib/toolbox/random_name.h>
#include "../helpers/subghz_custom_event.h"
#include <lib/subghz/protocols/raw.h>
@@ -20,45 +22,49 @@ void subghz_scene_save_name_on_enter(void* context) {
bool dev_name_empty = false;
string_t file_name;
string_t dir_name;
string_init(file_name);
string_init(dir_name);
if(!strcmp(subghz->file_path, "")) {
if(!subghz_path_is_file(subghz->file_path)) {
char file_name_buf[SUBGHZ_MAX_LEN_NAME] = {0};
set_random_name(file_name_buf, SUBGHZ_MAX_LEN_NAME);
string_set(file_name, file_name_buf);
strncpy(subghz->file_dir, SUBGHZ_APP_FOLDER, SUBGHZ_MAX_LEN_NAME);
string_set_str(file_name, file_name_buf);
string_set_str(subghz->file_path, SUBGHZ_APP_FOLDER);
//highlighting the entire filename by default
dev_name_empty = true;
} else {
strncpy(subghz->file_path_tmp, subghz->file_path, SUBGHZ_MAX_LEN_NAME);
path_extract_dirname(subghz->file_path, file_name);
strncpy(subghz->file_dir, string_get_cstr(file_name), SUBGHZ_MAX_LEN_NAME);
path_extract_filename_no_ext(subghz->file_path, file_name);
string_set(subghz->file_path_tmp, subghz->file_path);
path_extract_dirname(string_get_cstr(subghz->file_path), dir_name);
path_extract_filename(subghz->file_path, file_name, true);
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
SubGhzCustomEventManagerNoSet) {
subghz_get_next_name_file(subghz, SUBGHZ_MAX_LEN_NAME);
path_extract_filename_no_ext(subghz->file_path, file_name);
path_extract_filename(subghz->file_path, file_name, true);
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) ==
SubGhzCustomEventManagerSetRAW) {
dev_name_empty = true;
}
}
string_set(subghz->file_path, dir_name);
}
strncpy(subghz->file_path, string_get_cstr(file_name), SUBGHZ_MAX_LEN_NAME);
strncpy(subghz->file_name_tmp, string_get_cstr(file_name), SUBGHZ_MAX_LEN_NAME);
text_input_set_header_text(text_input, "Name signal");
text_input_set_result_callback(
text_input,
subghz_scene_save_name_text_input_callback,
subghz,
subghz->file_path,
subghz->file_name_tmp,
MAX_TEXT_INPUT_LEN, // buffer size
dev_name_empty);
ValidatorIsFile* validator_is_file =
validator_is_file_alloc_init(subghz->file_dir, SUBGHZ_APP_EXTENSION, NULL);
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
string_get_cstr(subghz->file_path), SUBGHZ_APP_EXTENSION, NULL);
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
string_clear(file_name);
string_clear(dir_name);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdTextInput);
}
@@ -66,18 +72,15 @@ void subghz_scene_save_name_on_enter(void* context) {
bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
if(event.type == SceneManagerEventTypeBack) {
strncpy(subghz->file_path, subghz->file_path_tmp, SUBGHZ_MAX_LEN_NAME);
string_set(subghz->file_path, subghz->file_path_tmp);
scene_manager_previous_scene(subghz->scene_manager);
return true;
} else if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventSceneSaveName) {
if(strcmp(subghz->file_path, "")) {
string_t temp_str;
string_init_printf(
temp_str, "%s/%s%s", subghz->file_dir, subghz->file_path, SUBGHZ_APP_EXTENSION);
strncpy(subghz->file_path, string_get_cstr(temp_str), SUBGHZ_MAX_LEN_NAME);
string_clear(temp_str);
if(strcmp(subghz->file_path_tmp, "")) {
if(strcmp(subghz->file_name_tmp, "")) {
string_cat_printf(
subghz->file_path, "/%s%s", subghz->file_name_tmp, SUBGHZ_APP_EXTENSION);
if(subghz_path_is_file(subghz->file_path_tmp)) {
if(!subghz_rename_file(subghz)) {
return false;
}
@@ -85,7 +88,7 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) {
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSetType) !=
SubGhzCustomEventManagerNoSet) {
subghz_save_protocol_to_file(
subghz, subghz->txrx->fff_data, subghz->file_path);
subghz, subghz->txrx->fff_data, string_get_cstr(subghz->file_path));
scene_manager_set_scene_state(
subghz->scene_manager,
SubGhzSceneSetType,
@@ -95,13 +98,14 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) {
subghz,
subghz_history_get_raw_data(
subghz->txrx->history, subghz->txrx->idx_menu_chosen),
subghz->file_path);
string_get_cstr(subghz->file_path));
}
}
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
SubGhzCustomEventManagerNoSet) {
subghz_protocol_raw_gen_fff_data(subghz->txrx->fff_data, subghz->file_path);
subghz_protocol_raw_gen_fff_data(
subghz->txrx->fff_data, string_get_cstr(subghz->file_path));
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerNoSet);
} else {
@@ -111,7 +115,7 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess);
return true;
} else {
string_set(subghz->error_str, "No name file");
string_set_str(subghz->error_str, "No name file");
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub);
return true;
}

View File

@@ -94,7 +94,7 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) {
subghz->scene_manager, SubGhzSceneStart);
return true;
} else if(event.event == SubGhzCustomEventViewTransmitterError) {
string_set(subghz->error_str, "Protocol not found");
string_set_str(subghz->error_str, "Protocol not found");
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub);
}
} else if(event.type == SceneManagerEventTypeTick) {

View File

@@ -303,7 +303,7 @@ void subghz_cli_command_decode_raw(Cli* cli, string_t args, void* context) {
UNUSED(context);
string_t file_name;
string_init(file_name);
string_set(file_name, "/any/subghz/test.sub");
string_set_str(file_name, "/any/subghz/test.sub");
Storage* storage = furi_record_open("storage");
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);

View File

@@ -169,14 +169,14 @@ bool subghz_history_add_to_history(
break;
}
if(!strcmp(string_get_cstr(instance->tmp_string), "KeeLoq")) {
string_set(instance->tmp_string, "KL ");
string_set_str(instance->tmp_string, "KL ");
if(!flipper_format_read_string(item->flipper_string, "Manufacture", text)) {
FURI_LOG_E(TAG, "Missing Protocol");
break;
}
string_cat(instance->tmp_string, text);
} else if(!strcmp(string_get_cstr(instance->tmp_string), "Star Line")) {
string_set(instance->tmp_string, "SL ");
string_set_str(instance->tmp_string, "SL ");
if(!flipper_format_read_string(item->flipper_string, "Manufacture", text)) {
FURI_LOG_E(TAG, "Missing Protocol");
break;

View File

@@ -1,5 +1,8 @@
#include "subghz_i.h"
#include "assets_icons.h"
#include "m-string.h"
#include "subghz/types.h"
#include <math.h>
#include <furi.h>
#include <furi_hal.h>
@@ -45,11 +48,11 @@ void subghz_get_frequency_modulation(SubGhz* subghz, string_t frequency, string_
if(modulation != NULL) {
if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async ||
subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) {
string_set(modulation, "AM");
string_set_str(modulation, "AM");
} else if(
subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async ||
subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) {
string_set(modulation, "FM");
string_set_str(modulation, "FM");
} else {
furi_crash("SugGhz: Modulation is incorrect.");
}
@@ -191,8 +194,9 @@ void subghz_tx_stop(SubGhz* subghz) {
//if protocol dynamic then we save the last upload
if((subghz->txrx->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) &&
(strcmp(subghz->file_path, ""))) {
subghz_save_protocol_to_file(subghz, subghz->txrx->fff_data, subghz->file_path);
(subghz_path_is_file(subghz->file_path))) {
subghz_save_protocol_to_file(
subghz, subghz->txrx->fff_data, string_get_cstr(subghz->file_path));
}
subghz_idle(subghz);
notification_message(subghz->notifications, &sequence_reset_red);
@@ -334,10 +338,10 @@ bool subghz_get_next_name_file(SubGhz* subghz, uint8_t max_len) {
bool res = false;
if(strcmp(subghz->file_path, "")) {
if(subghz_path_is_file(subghz->file_path)) {
//get the name of the next free file
path_extract_filename_no_ext(subghz->file_path, file_name);
path_extract_dirname(subghz->file_path, file_path);
path_extract_filename(subghz->file_path, file_name, true);
path_extract_dirname(string_get_cstr(subghz->file_path), file_path);
storage_get_next_filename(
storage,
@@ -353,7 +357,7 @@ bool subghz_get_next_name_file(SubGhz* subghz, uint8_t max_len) {
string_get_cstr(file_path),
string_get_cstr(file_name),
SUBGHZ_APP_EXTENSION);
strncpy(subghz->file_path, string_get_cstr(temp_str), SUBGHZ_MAX_LEN_NAME);
string_set(subghz->file_path, temp_str);
res = true;
}
@@ -413,19 +417,17 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) {
string_init(file_path);
// Input events and views are managed by file_select
bool res = dialog_file_select_show(
bool res = dialog_file_browser_show(
subghz->dialogs,
SUBGHZ_APP_FOLDER,
SUBGHZ_APP_EXTENSION,
subghz->file_path,
sizeof(subghz->file_path),
NULL);
subghz->file_path,
SUBGHZ_APP_EXTENSION,
true,
&I_sub1_10px,
true);
if(res) {
string_printf(
file_path, "%s/%s%s", SUBGHZ_APP_FOLDER, subghz->file_path, SUBGHZ_APP_EXTENSION);
strncpy(subghz->file_path, string_get_cstr(file_path), SUBGHZ_MAX_LEN_NAME);
res = subghz_key_load(subghz, subghz->file_path);
res = subghz_key_load(subghz, string_get_cstr(subghz->file_path));
}
string_clear(file_path);
@@ -439,9 +441,9 @@ bool subghz_rename_file(SubGhz* subghz) {
Storage* storage = furi_record_open("storage");
if(strcmp(subghz->file_path_tmp, subghz->file_path)) {
FS_Error fs_result =
storage_common_rename(storage, subghz->file_path_tmp, subghz->file_path);
if(string_cmp(subghz->file_path_tmp, subghz->file_path)) {
FS_Error fs_result = storage_common_rename(
storage, string_get_cstr(subghz->file_path_tmp), string_get_cstr(subghz->file_path));
if(fs_result != FSE_OK) {
dialog_message_show_storage_error(subghz->dialogs, "Cannot rename\n file/directory");
@@ -457,7 +459,7 @@ bool subghz_delete_file(SubGhz* subghz) {
furi_assert(subghz);
Storage* storage = furi_record_open("storage");
bool result = storage_simply_remove(storage, subghz->file_path_tmp);
bool result = storage_simply_remove(storage, string_get_cstr(subghz->file_path_tmp));
furi_record_close("storage");
subghz_file_name_clear(subghz);
@@ -467,8 +469,12 @@ bool subghz_delete_file(SubGhz* subghz) {
void subghz_file_name_clear(SubGhz* subghz) {
furi_assert(subghz);
memset(subghz->file_path, 0, sizeof(subghz->file_path));
memset(subghz->file_path_tmp, 0, sizeof(subghz->file_path_tmp));
string_set_str(subghz->file_path, SUBGHZ_APP_FOLDER);
string_reset(subghz->file_path_tmp);
}
bool subghz_path_is_file(string_t path) {
return string_end_with_str_p(path, SUBGHZ_APP_EXTENSION);
}
uint32_t subghz_random_serial(void) {

View File

@@ -111,9 +111,9 @@ void subghz_view_receiver_add_data_statusbar(
furi_assert(subghz_receiver);
with_view_model(
subghz_receiver->view, (SubGhzViewReceiverModel * model) {
string_set(model->frequency_str, frequency_str);
string_set(model->preset_str, preset_str);
string_set(model->history_stat_str, history_stat_str);
string_set_str(model->frequency_str, frequency_str);
string_set_str(model->preset_str, preset_str);
string_set_str(model->history_stat_str, history_stat_str);
return true;
});
}

View File

@@ -46,8 +46,8 @@ void subghz_read_raw_add_data_statusbar(
furi_assert(instance);
with_view_model(
instance->view, (SubGhzReadRAWModel * model) {
string_set(model->frequency_str, frequency_str);
string_set(model->preset_str, preset_str);
string_set_str(model->frequency_str, frequency_str);
string_set_str(model->preset_str, preset_str);
return true;
});
}
@@ -372,7 +372,7 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
model->satus = SubGhzReadRAWStatusStart;
model->rssi_history_end = false;
model->ind_write = 0;
string_set(model->sample_write, "0 spl.");
string_set_str(model->sample_write, "0 spl.");
string_reset(model->file_name);
instance->callback(SubGhzCustomEventViewReadRAWErase, instance->context);
}
@@ -424,7 +424,7 @@ void subghz_read_raw_set_status(
model->rssi_history_end = false;
model->ind_write = 0;
string_reset(model->file_name);
string_set(model->sample_write, "0 spl.");
string_set_str(model->sample_write, "0 spl.");
return true;
});
break;
@@ -441,8 +441,8 @@ void subghz_read_raw_set_status(
model->satus = SubGhzReadRAWStatusLoadKeyIDLE;
model->rssi_history_end = false;
model->ind_write = 0;
string_set(model->file_name, file_name);
string_set(model->sample_write, "RAW");
string_set_str(model->file_name, file_name);
string_set_str(model->sample_write, "RAW");
return true;
});
break;
@@ -451,8 +451,8 @@ void subghz_read_raw_set_status(
instance->view, (SubGhzReadRAWModel * model) {
model->satus = SubGhzReadRAWStatusLoadKeyIDLE;
if(!model->ind_write) {
string_set(model->file_name, file_name);
string_set(model->sample_write, "RAW");
string_set_str(model->file_name, file_name);
string_set_str(model->sample_write, "RAW");
} else {
string_reset(model->file_name);
}

View File

@@ -36,9 +36,9 @@ void subghz_view_transmitter_add_data_to_show(
furi_assert(subghz_transmitter);
with_view_model(
subghz_transmitter->view, (SubGhzViewTransmitterModel * model) {
string_set(model->key_str, key_str);
string_set(model->frequency_str, frequency_str);
string_set(model->preset_str, preset_str);
string_set_str(model->key_str, key_str);
string_set_str(model->frequency_str, frequency_str);
string_set_str(model->preset_str, preset_str);
model->show_button = show_button;
return true;
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

View File

@@ -19,8 +19,9 @@ endif
MCU_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard
# Warnings configuration
CFLAGS += $(MCU_FLAGS) -DSTM32WB55xx -Wall -fdata-sections -ffunction-sections
CFLAGS += -Wall -Wextra -Wredundant-decls -Wdouble-promotion
CFLAGS += $(MCU_FLAGS) -DSTM32WB55xx -fdata-sections -ffunction-sections -fsingle-precision-constant
LDFLAGS += $(MCU_FLAGS) -specs=nosys.specs -specs=nano.specs
CPPFLAGS += -fno-rtti -fno-use-cxa-atexit -fno-exceptions

View File

@@ -4,7 +4,6 @@
struct iButtonKey {
uint8_t data[IBUTTON_KEY_DATA_SIZE];
char name[IBUTTON_KEY_NAME_SIZE];
iButtonKeyType type;
};
@@ -42,14 +41,6 @@ uint8_t ibutton_key_get_data_size(iButtonKey* key) {
return ibutton_key_get_size_by_type(key->type);
}
void ibutton_key_set_name(iButtonKey* key, const char* name) {
strlcpy(key->name, name, IBUTTON_KEY_NAME_SIZE);
}
const char* ibutton_key_get_name_p(iButtonKey* key) {
return key->name;
}
void ibutton_key_set_type(iButtonKey* key, iButtonKeyType key_type) {
key->type = key_type;
}

View File

@@ -68,20 +68,6 @@ const uint8_t* ibutton_key_get_data_p(iButtonKey* key);
*/
uint8_t ibutton_key_get_data_size(iButtonKey* key);
/**
* Set key name
* @param key
* @param name
*/
void ibutton_key_set_name(iButtonKey* key, const char* name);
/**
* Get pointer to key name
* @param key
* @return const char*
*/
const char* ibutton_key_get_name_p(iButtonKey* key);
/**
* Set key type
* @param key

View File

@@ -334,7 +334,6 @@ bool subghz_keystore_save(SubGhzKeystore* instance, const char* file_name, uint8
SubGhzKeyArray_t* subghz_keystore_get_data(SubGhzKeystore* instance) {
furi_assert(instance);
return &instance->data;
FURI_LOG_I(TAG, "array: \n", &instance->data);
}
bool subghz_keystore_raw_encrypted_save(

View File

@@ -19,6 +19,20 @@ void path_extract_filename_no_ext(const char* path, string_t filename) {
string_mid(filename, start_position, end_position - start_position);
}
void path_extract_filename(string_t path, string_t name, bool trim_ext) {
size_t filename_start = string_search_rchar(path, '/');
if(filename_start > 0) {
filename_start++;
string_set_n(name, path, filename_start, string_size(path) - filename_start);
}
if(trim_ext) {
size_t dot = string_search_rchar(name, '.');
if(dot > 0) {
string_left(name, dot);
}
}
}
static inline void path_cleanup(string_t path) {
string_strim(path);
while(string_end_with_str_p(path, "/")) {

View File

@@ -14,6 +14,15 @@ extern "C" {
*/
void path_extract_filename_no_ext(const char* path, string_t filename);
/**
* @brief Extract filename string from path.
*
* @param path path string
* @param filename output filename string. Must be initialized before.
* @param trim_ext true - get filename without extension
*/
void path_extract_filename(string_t path, string_t filename, bool trim_ext);
/**
* @brief Extract last path component
*