mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2024-11-23 10:01:58 +03:00
[FL-3890] Infrared button operation fails now shows more informative messages (#3859)
* Error codes enum added * Adjusted signal api to return error codes instead of bool * Remote api adjusted to work with error codes * Brute force logic adjusted to work with error codes * Other application functions adjust to work with error codes * All task callbacks now return ErrorCode through int32t, which belongs to thread * All scenes now work with error codes * More api functions now return error code * Now signal names are buffered and restored in case of error. * New error code enumeration added. Now least significant byte is left for the button index * Some macro to simplify error setup and error check * Error code checks replaced by macro * Different message is now shown when move failed * Comments updated * Fixed error check * Fixed navigation issue while openning broken files from Favorites * Now search by index also returns index in addition to error code * Remote loading logic adjusted * New error codes added and numbers adjusted * New error message when loading library file instead of signal one * Some more remote loading logic adjusted * New error message on rename fail * Grammar mistake fix * Function signature changed * Function usage adjusted according to new signature Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
parent
6a1c27ef93
commit
e0654fe409
@ -297,7 +297,7 @@ static void infrared_free(InfraredApp* infrared) {
|
||||
free(infrared);
|
||||
}
|
||||
|
||||
bool infrared_add_remote_with_button(
|
||||
InfraredErrorCode infrared_add_remote_with_button(
|
||||
const InfraredApp* infrared,
|
||||
const char* button_name,
|
||||
const InfraredSignal* signal) {
|
||||
@ -310,21 +310,23 @@ bool infrared_add_remote_with_button(
|
||||
furi_string_cat_printf(
|
||||
new_path, "/%s%s", furi_string_get_cstr(new_name), INFRARED_APP_EXTENSION);
|
||||
|
||||
bool success = false;
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
|
||||
do {
|
||||
if(!infrared_remote_create(remote, furi_string_get_cstr(new_path))) break;
|
||||
if(!infrared_remote_append_signal(remote, signal, button_name)) break;
|
||||
success = true;
|
||||
error = infrared_remote_create(remote, furi_string_get_cstr(new_path));
|
||||
if(INFRARED_ERROR_PRESENT(error)) break;
|
||||
|
||||
error = infrared_remote_append_signal(remote, signal, button_name);
|
||||
} while(false);
|
||||
|
||||
furi_string_free(new_name);
|
||||
furi_string_free(new_path);
|
||||
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
bool infrared_rename_current_remote(const InfraredApp* infrared, const char* new_name) {
|
||||
InfraredErrorCode
|
||||
infrared_rename_current_remote(const InfraredApp* infrared, const char* new_name) {
|
||||
InfraredRemote* remote = infrared->remote;
|
||||
const char* old_path = infrared_remote_get_path(remote);
|
||||
|
||||
@ -344,12 +346,13 @@ bool infrared_rename_current_remote(const InfraredApp* infrared, const char* new
|
||||
path_append(new_path_fstr, furi_string_get_cstr(new_name_fstr));
|
||||
furi_string_cat(new_path_fstr, INFRARED_APP_EXTENSION);
|
||||
|
||||
const bool success = infrared_remote_rename(remote, furi_string_get_cstr(new_path_fstr));
|
||||
const InfraredErrorCode error =
|
||||
infrared_remote_rename(remote, furi_string_get_cstr(new_path_fstr));
|
||||
|
||||
furi_string_free(new_name_fstr);
|
||||
furi_string_free(new_path_fstr);
|
||||
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
void infrared_tx_start(InfraredApp* infrared) {
|
||||
@ -382,15 +385,16 @@ void infrared_tx_start(InfraredApp* infrared) {
|
||||
infrared->app_state.is_transmitting = true;
|
||||
}
|
||||
|
||||
bool infrared_tx_start_button_index(InfraredApp* infrared, size_t button_index) {
|
||||
InfraredErrorCode infrared_tx_start_button_index(InfraredApp* infrared, size_t button_index) {
|
||||
furi_assert(button_index < infrared_remote_get_signal_count(infrared->remote));
|
||||
|
||||
bool result =
|
||||
InfraredErrorCode error =
|
||||
infrared_remote_load_signal(infrared->remote, infrared->current_signal, button_index);
|
||||
if(result) {
|
||||
|
||||
if(!INFRARED_ERROR_PRESENT(error)) {
|
||||
infrared_tx_start(infrared);
|
||||
}
|
||||
return result;
|
||||
return error;
|
||||
}
|
||||
|
||||
void infrared_tx_stop(InfraredApp* infrared) {
|
||||
@ -413,7 +417,7 @@ void infrared_blocking_task_start(InfraredApp* infrared, FuriThreadCallback call
|
||||
furi_thread_start(infrared->task_thread);
|
||||
}
|
||||
|
||||
bool infrared_blocking_task_finalize(InfraredApp* infrared) {
|
||||
InfraredErrorCode infrared_blocking_task_finalize(InfraredApp* infrared) {
|
||||
furi_thread_join(infrared->task_thread);
|
||||
return furi_thread_get_return_code(infrared->task_thread);
|
||||
}
|
||||
@ -563,10 +567,18 @@ int32_t infrared_app(void* p) {
|
||||
is_rpc_mode = true;
|
||||
} else {
|
||||
const char* file_path = (const char*)p;
|
||||
is_remote_loaded = infrared_remote_load(infrared->remote, file_path);
|
||||
InfraredErrorCode error = infrared_remote_load(infrared->remote, file_path);
|
||||
|
||||
if(!is_remote_loaded) {
|
||||
infrared_show_error_message(infrared, "Failed to load\n\"%s\"", file_path);
|
||||
if(!INFRARED_ERROR_PRESENT(error)) {
|
||||
is_remote_loaded = true;
|
||||
} else {
|
||||
is_remote_loaded = false;
|
||||
bool wrong_file_type = INFRARED_ERROR_CHECK(error, InfraredErrorCodeWrongFileType);
|
||||
const char* format = wrong_file_type ?
|
||||
"Library file\n\"%s\" can't be openned as a remote" :
|
||||
"Failed to load\n\"%s\"";
|
||||
|
||||
infrared_show_error_message(infrared, format, file_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -174,9 +174,9 @@ typedef enum {
|
||||
* @param[in] infrared pointer to the application instance.
|
||||
* @param[in] name pointer to a zero-terminated string containing the signal name.
|
||||
* @param[in] signal pointer to the signal to be added.
|
||||
* @return true if the remote was successfully created, false otherwise.
|
||||
* @return InfraredErrorCodeNone if the remote was successfully created, otherwise error code.
|
||||
*/
|
||||
bool infrared_add_remote_with_button(
|
||||
InfraredErrorCode infrared_add_remote_with_button(
|
||||
const InfraredApp* infrared,
|
||||
const char* name,
|
||||
const InfraredSignal* signal);
|
||||
@ -186,9 +186,10 @@ bool infrared_add_remote_with_button(
|
||||
*
|
||||
* @param[in] infrared pointer to the application instance.
|
||||
* @param[in] new_name pointer to a zero-terminated string containing the new remote name.
|
||||
* @return true if the remote was successfully renamed, false otherwise.
|
||||
* @return InfraredErrorCodeNone if the remote was successfully renamed, otherwise error code.
|
||||
*/
|
||||
bool infrared_rename_current_remote(const InfraredApp* infrared, const char* new_name);
|
||||
InfraredErrorCode
|
||||
infrared_rename_current_remote(const InfraredApp* infrared, const char* new_name);
|
||||
|
||||
/**
|
||||
* @brief Begin transmission of the currently loaded signal.
|
||||
@ -206,9 +207,9 @@ void infrared_tx_start(InfraredApp* infrared);
|
||||
*
|
||||
* @param[in,out] infrared pointer to the application instance.
|
||||
* @param[in] button_index index of the signal to be loaded.
|
||||
* @returns true if the signal could be loaded, false otherwise.
|
||||
* @returns InfraredErrorCodeNone if the signal could be loaded, otherwise error code.
|
||||
*/
|
||||
bool infrared_tx_start_button_index(InfraredApp* infrared, size_t button_index);
|
||||
InfraredErrorCode infrared_tx_start_button_index(InfraredApp* infrared, size_t button_index);
|
||||
|
||||
/**
|
||||
* @brief Stop transmission of the currently loaded signal.
|
||||
@ -236,9 +237,9 @@ void infrared_blocking_task_start(InfraredApp* infrared, FuriThreadCallback call
|
||||
* (e.g. to display the results), the caller code MUST set it explicitly.
|
||||
*
|
||||
* @param[in,out] infrared pointer to the application instance.
|
||||
* @return true if the blocking task finished successfully, false otherwise.
|
||||
* @return InfraredErrorCodeNone if the blocking task finished successfully, otherwise error code.
|
||||
*/
|
||||
bool infrared_blocking_task_finalize(InfraredApp* infrared);
|
||||
InfraredErrorCode infrared_blocking_task_finalize(InfraredApp* infrared);
|
||||
|
||||
/**
|
||||
* @brief Set the internal text store with formatted text.
|
||||
|
@ -50,10 +50,10 @@ void infrared_brute_force_set_db_filename(InfraredBruteForce* brute_force, const
|
||||
brute_force->db_filename = db_filename;
|
||||
}
|
||||
|
||||
bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) {
|
||||
InfraredErrorCode infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) {
|
||||
furi_assert(!brute_force->is_started);
|
||||
furi_assert(brute_force->db_filename);
|
||||
bool success = false;
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* ff = flipper_format_buffered_file_alloc(storage);
|
||||
@ -61,12 +61,15 @@ bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) {
|
||||
InfraredSignal* signal = infrared_signal_alloc();
|
||||
|
||||
do {
|
||||
if(!flipper_format_buffered_file_open_existing(ff, brute_force->db_filename)) break;
|
||||
if(!flipper_format_buffered_file_open_existing(ff, brute_force->db_filename)) {
|
||||
error = InfraredErrorCodeFileOperationFailed;
|
||||
break;
|
||||
}
|
||||
|
||||
bool signals_valid = false;
|
||||
while(infrared_signal_read_name(ff, signal_name)) {
|
||||
signals_valid = infrared_signal_read_body(signal, ff) &&
|
||||
infrared_signal_is_valid(signal);
|
||||
while(infrared_signal_read_name(ff, signal_name) == InfraredErrorCodeNone) {
|
||||
error = infrared_signal_read_body(signal, ff);
|
||||
signals_valid = (!INFRARED_ERROR_PRESENT(error)) && infrared_signal_is_valid(signal);
|
||||
if(!signals_valid) break;
|
||||
|
||||
InfraredBruteForceRecord* record =
|
||||
@ -75,9 +78,7 @@ bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) {
|
||||
++(record->count);
|
||||
}
|
||||
}
|
||||
|
||||
if(!signals_valid) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
infrared_signal_free(signal);
|
||||
@ -85,7 +86,7 @@ bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) {
|
||||
|
||||
flipper_format_free(ff);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
bool infrared_brute_force_start(
|
||||
@ -139,10 +140,12 @@ void infrared_brute_force_stop(InfraredBruteForce* brute_force) {
|
||||
|
||||
bool infrared_brute_force_send_next(InfraredBruteForce* brute_force) {
|
||||
furi_assert(brute_force->is_started);
|
||||
|
||||
const bool success = infrared_signal_search_by_name_and_read(
|
||||
brute_force->current_signal,
|
||||
brute_force->ff,
|
||||
furi_string_get_cstr(brute_force->current_record_name));
|
||||
brute_force->current_signal,
|
||||
brute_force->ff,
|
||||
furi_string_get_cstr(brute_force->current_record_name)) ==
|
||||
InfraredErrorCodeNone;
|
||||
if(success) {
|
||||
infrared_signal_transmit(brute_force->current_signal);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "infrared_error_code.h"
|
||||
|
||||
/**
|
||||
* @brief InfraredBruteForce opaque type declaration.
|
||||
@ -45,9 +46,9 @@ void infrared_brute_force_set_db_filename(InfraredBruteForce* brute_force, const
|
||||
* a infrared_brute_force_set_db_filename() call.
|
||||
*
|
||||
* @param[in,out] brute_force pointer to the instance to be updated.
|
||||
* @returns true on success, false otherwise.
|
||||
* @returns InfraredErrorCodeNone on success, otherwise error code.
|
||||
*/
|
||||
bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force);
|
||||
InfraredErrorCode infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force);
|
||||
|
||||
/**
|
||||
* @brief Start transmitting signals from a category stored in an InfraredBruteForce's instance dictionary.
|
||||
|
@ -232,9 +232,15 @@ static void infrared_cli_start_ir_tx(Cli* cli, FuriString* args) {
|
||||
|
||||
static bool
|
||||
infrared_cli_save_signal(InfraredSignal* signal, FlipperFormat* file, const char* name) {
|
||||
bool ret = infrared_signal_save(signal, file, name);
|
||||
if(!ret) {
|
||||
printf("Failed to save signal: \"%s\"\r\n", name);
|
||||
bool ret = true;
|
||||
InfraredErrorCode error = infrared_signal_save(signal, file, name);
|
||||
if(INFRARED_ERROR_PRESENT(error)) {
|
||||
printf(
|
||||
"Failed to save signal: \"%s\" code: 0x%X index: 0x%02X\r\n",
|
||||
name,
|
||||
INFRARED_ERROR_GET_CODE(error),
|
||||
INFRARED_ERROR_GET_INDEX(error));
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -296,7 +302,7 @@ static bool infrared_cli_decode_file(FlipperFormat* input_file, FlipperFormat* o
|
||||
FuriString* tmp;
|
||||
tmp = furi_string_alloc();
|
||||
|
||||
while(infrared_signal_read(signal, input_file, tmp)) {
|
||||
while(infrared_signal_read(signal, input_file, tmp) == InfraredErrorCodeNone) {
|
||||
ret = false;
|
||||
if(!infrared_signal_is_valid(signal)) {
|
||||
printf("Invalid signal\r\n");
|
||||
@ -464,7 +470,7 @@ static void
|
||||
printf("Missing signal name.\r\n");
|
||||
break;
|
||||
}
|
||||
if(!infrared_brute_force_calculate_messages(brute_force)) {
|
||||
if(infrared_brute_force_calculate_messages(brute_force) != InfraredErrorCodeNone) {
|
||||
printf("Invalid remote name.\r\n");
|
||||
break;
|
||||
}
|
||||
|
45
applications/main/infrared/infrared_error_code.h
Normal file
45
applications/main/infrared/infrared_error_code.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
InfraredErrorCodeNone = 0,
|
||||
InfraredErrorCodeFileOperationFailed = 0x800000,
|
||||
InfraredErrorCodeWrongFileType = 0x80000100,
|
||||
InfraredErrorCodeWrongFileVersion = 0x80000200,
|
||||
|
||||
//Common signal errors
|
||||
InfraredErrorCodeSignalTypeUnknown = 0x80000300,
|
||||
InfraredErrorCodeSignalNameNotFound = 0x80000400,
|
||||
InfraredErrorCodeSignalUnableToReadType = 0x80000500,
|
||||
InfraredErrorCodeSignalUnableToWriteType = 0x80000600,
|
||||
|
||||
//Raw signal errors
|
||||
InfraredErrorCodeSignalRawUnableToReadFrequency = 0x80000700,
|
||||
InfraredErrorCodeSignalRawUnableToReadDutyCycle = 0x80000800,
|
||||
InfraredErrorCodeSignalRawUnableToReadTimingsSize = 0x80000900,
|
||||
InfraredErrorCodeSignalRawUnableToReadTooLongData = 0x80000A00,
|
||||
InfraredErrorCodeSignalRawUnableToReadData = 0x80000B00,
|
||||
|
||||
InfraredErrorCodeSignalRawUnableToWriteFrequency = 0x80000C00,
|
||||
InfraredErrorCodeSignalRawUnableToWriteDutyCycle = 0x80000D00,
|
||||
InfraredErrorCodeSignalRawUnableToWriteData = 0x80000E00,
|
||||
|
||||
//Message signal errors
|
||||
InfraredErrorCodeSignalMessageUnableToReadProtocol = 0x80000F00,
|
||||
InfraredErrorCodeSignalMessageUnableToReadAddress = 0x80001000,
|
||||
InfraredErrorCodeSignalMessageUnableToReadCommand = 0x80001100,
|
||||
InfraredErrorCodeSignalMessageIsInvalid = 0x80001200,
|
||||
|
||||
InfraredErrorCodeSignalMessageUnableToWriteProtocol = 0x80001300,
|
||||
InfraredErrorCodeSignalMessageUnableToWriteAddress = 0x80001400,
|
||||
InfraredErrorCodeSignalMessageUnableToWriteCommand = 0x80001500,
|
||||
} InfraredErrorCode;
|
||||
|
||||
#define INFRARED_ERROR_CODE_MASK (0xFFFFFF00)
|
||||
#define INFRARED_ERROR_INDEX_MASK (0x000000FF)
|
||||
|
||||
#define INFRARED_ERROR_GET_CODE(error) (error & INFRARED_ERROR_CODE_MASK)
|
||||
#define INFRARED_ERROR_GET_INDEX(error) (error & INFRARED_ERROR_INDEX_MASK)
|
||||
#define INFRARED_ERROR_SET_INDEX(code, index) (code |= (index & INFRARED_ERROR_INDEX_MASK))
|
||||
|
||||
#define INFRARED_ERROR_PRESENT(error) (INFRARED_ERROR_GET_CODE(error) != InfraredErrorCodeNone)
|
||||
#define INFRARED_ERROR_CHECK(error, test_code) (INFRARED_ERROR_GET_CODE(error) == test_code)
|
@ -8,8 +8,9 @@
|
||||
|
||||
#define TAG "InfraredRemote"
|
||||
|
||||
#define INFRARED_FILE_HEADER "IR signals file"
|
||||
#define INFRARED_FILE_VERSION (1)
|
||||
#define INFRARED_FILE_HEADER "IR signals file"
|
||||
#define INFRARED_LIBRARY_HEADER "IR library file"
|
||||
#define INFRARED_FILE_VERSION (1)
|
||||
|
||||
ARRAY_DEF(StringArray, const char*, M_CSTR_DUP_OPLIST); //-V575
|
||||
|
||||
@ -34,7 +35,7 @@ typedef struct {
|
||||
const InfraredSignal* signal;
|
||||
} InfraredBatchTarget;
|
||||
|
||||
typedef bool (
|
||||
typedef InfraredErrorCode (
|
||||
*InfraredBatchCallback)(const InfraredBatch* batch, const InfraredBatchTarget* target);
|
||||
|
||||
InfraredRemote* infrared_remote_alloc(void) {
|
||||
@ -80,7 +81,7 @@ const char* infrared_remote_get_signal_name(const InfraredRemote* remote, size_t
|
||||
return *StringArray_cget(remote->signal_names, index);
|
||||
}
|
||||
|
||||
bool infrared_remote_load_signal(
|
||||
InfraredErrorCode infrared_remote_load_signal(
|
||||
const InfraredRemote* remote,
|
||||
InfraredSignal* signal,
|
||||
size_t index) {
|
||||
@ -89,25 +90,27 @@ bool infrared_remote_load_signal(
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* ff = flipper_format_buffered_file_alloc(storage);
|
||||
|
||||
bool success = false;
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
|
||||
do {
|
||||
const char* path = furi_string_get_cstr(remote->path);
|
||||
if(!flipper_format_buffered_file_open_existing(ff, path)) break;
|
||||
if(!flipper_format_buffered_file_open_existing(ff, path)) {
|
||||
error = InfraredErrorCodeFileOperationFailed;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!infrared_signal_search_by_index_and_read(signal, ff, index)) {
|
||||
error = infrared_signal_search_by_index_and_read(signal, ff, index);
|
||||
if(INFRARED_ERROR_PRESENT(error)) {
|
||||
const char* signal_name = infrared_remote_get_signal_name(remote, index);
|
||||
FURI_LOG_E(TAG, "Failed to load signal '%s' from file '%s'", signal_name, path);
|
||||
break;
|
||||
}
|
||||
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
flipper_format_free(ff);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
bool infrared_remote_get_signal_index(
|
||||
@ -128,31 +131,35 @@ bool infrared_remote_get_signal_index(
|
||||
return false;
|
||||
}
|
||||
|
||||
bool infrared_remote_append_signal(
|
||||
InfraredErrorCode infrared_remote_append_signal(
|
||||
InfraredRemote* remote,
|
||||
const InfraredSignal* signal,
|
||||
const char* name) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* ff = flipper_format_file_alloc(storage);
|
||||
|
||||
bool success = false;
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
const char* path = furi_string_get_cstr(remote->path);
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_append(ff, path)) break;
|
||||
if(!infrared_signal_save(signal, ff, name)) break;
|
||||
if(!flipper_format_file_open_append(ff, path)) {
|
||||
error = InfraredErrorCodeFileOperationFailed;
|
||||
break;
|
||||
}
|
||||
|
||||
error = infrared_signal_save(signal, ff, name);
|
||||
if(INFRARED_ERROR_PRESENT(error)) break;
|
||||
|
||||
StringArray_push_back(remote->signal_names, name);
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
flipper_format_free(ff);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
static bool infrared_remote_batch_start(
|
||||
static InfraredErrorCode infrared_remote_batch_start(
|
||||
InfraredRemote* remote,
|
||||
InfraredBatchCallback batch_callback,
|
||||
const InfraredBatchTarget* target) {
|
||||
@ -179,33 +186,59 @@ static bool infrared_remote_batch_start(
|
||||
status = storage_common_stat(storage, path_out, NULL);
|
||||
} while(status == FSE_OK || status == FSE_EXIST);
|
||||
|
||||
bool success = false;
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
|
||||
StringArray_t buf_names;
|
||||
StringArray_init_set(buf_names, remote->signal_names);
|
||||
do {
|
||||
if(!flipper_format_buffered_file_open_existing(batch_context.ff_in, path_in)) break;
|
||||
if(!flipper_format_buffered_file_open_always(batch_context.ff_out, path_out)) break;
|
||||
if(!flipper_format_write_header_cstr(
|
||||
batch_context.ff_out, INFRARED_FILE_HEADER, INFRARED_FILE_VERSION))
|
||||
if(!flipper_format_buffered_file_open_existing(batch_context.ff_in, path_in) ||
|
||||
!flipper_format_buffered_file_open_always(batch_context.ff_out, path_out) ||
|
||||
!flipper_format_write_header_cstr(
|
||||
batch_context.ff_out, INFRARED_FILE_HEADER, INFRARED_FILE_VERSION)) {
|
||||
error = InfraredErrorCodeFileOperationFailed;
|
||||
break;
|
||||
|
||||
}
|
||||
const size_t signal_count = infrared_remote_get_signal_count(remote);
|
||||
|
||||
for(; batch_context.signal_index < signal_count; ++batch_context.signal_index) {
|
||||
if(!infrared_signal_read(
|
||||
batch_context.signal, batch_context.ff_in, batch_context.signal_name))
|
||||
error = infrared_signal_read(
|
||||
batch_context.signal, batch_context.ff_in, batch_context.signal_name);
|
||||
if(INFRARED_ERROR_PRESENT(error)) {
|
||||
INFRARED_ERROR_SET_INDEX(error, batch_context.signal_index);
|
||||
break;
|
||||
if(!batch_callback(&batch_context, target)) break;
|
||||
}
|
||||
|
||||
error = batch_callback(&batch_context, target);
|
||||
if(INFRARED_ERROR_PRESENT(error)) {
|
||||
INFRARED_ERROR_SET_INDEX(error, batch_context.signal_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(INFRARED_ERROR_PRESENT(error)) break;
|
||||
|
||||
if(!flipper_format_buffered_file_close(batch_context.ff_out) ||
|
||||
!flipper_format_buffered_file_close(batch_context.ff_in)) {
|
||||
error = InfraredErrorCodeFileOperationFailed;
|
||||
break;
|
||||
}
|
||||
|
||||
if(batch_context.signal_index != signal_count) break;
|
||||
|
||||
if(!flipper_format_buffered_file_close(batch_context.ff_out)) break;
|
||||
if(!flipper_format_buffered_file_close(batch_context.ff_in)) break;
|
||||
|
||||
const FS_Error status = storage_common_rename(storage, path_out, path_in);
|
||||
success = (status == FSE_OK || status == FSE_EXIST);
|
||||
error = (status == FSE_OK || status == FSE_EXIST) ? InfraredErrorCodeNone :
|
||||
InfraredErrorCodeFileOperationFailed;
|
||||
} while(false);
|
||||
|
||||
if(INFRARED_ERROR_PRESENT(error)) {
|
||||
//Remove all temp data and rollback signal names
|
||||
flipper_format_buffered_file_close(batch_context.ff_out);
|
||||
flipper_format_buffered_file_close(batch_context.ff_in);
|
||||
status = storage_common_stat(storage, path_out, NULL);
|
||||
if(status == FSE_OK || status == FSE_EXIST) storage_common_remove(storage, path_out);
|
||||
|
||||
StringArray_reset(remote->signal_names);
|
||||
StringArray_set(remote->signal_names, buf_names);
|
||||
}
|
||||
|
||||
StringArray_clear(buf_names);
|
||||
infrared_signal_free(batch_context.signal);
|
||||
furi_string_free(batch_context.signal_name);
|
||||
flipper_format_free(batch_context.ff_out);
|
||||
@ -214,15 +247,18 @@ static bool infrared_remote_batch_start(
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
static bool infrared_remote_insert_signal_callback(
|
||||
static InfraredErrorCode infrared_remote_insert_signal_callback(
|
||||
const InfraredBatch* batch,
|
||||
const InfraredBatchTarget* target) {
|
||||
// Insert a signal under the specified index
|
||||
if(batch->signal_index == target->signal_index) {
|
||||
if(!infrared_signal_save(target->signal, batch->ff_out, target->signal_name)) return false;
|
||||
InfraredErrorCode error =
|
||||
infrared_signal_save(target->signal, batch->ff_out, target->signal_name);
|
||||
if(INFRARED_ERROR_PRESENT(error)) return error;
|
||||
|
||||
StringArray_push_at(
|
||||
batch->remote->signal_names, target->signal_index, target->signal_name);
|
||||
}
|
||||
@ -232,7 +268,7 @@ static bool infrared_remote_insert_signal_callback(
|
||||
batch->signal, batch->ff_out, furi_string_get_cstr(batch->signal_name));
|
||||
}
|
||||
|
||||
bool infrared_remote_insert_signal(
|
||||
InfraredErrorCode infrared_remote_insert_signal(
|
||||
InfraredRemote* remote,
|
||||
const InfraredSignal* signal,
|
||||
const char* name,
|
||||
@ -251,7 +287,7 @@ bool infrared_remote_insert_signal(
|
||||
remote, infrared_remote_insert_signal_callback, &insert_target);
|
||||
}
|
||||
|
||||
static bool infrared_remote_rename_signal_callback(
|
||||
static InfraredErrorCode infrared_remote_rename_signal_callback(
|
||||
const InfraredBatch* batch,
|
||||
const InfraredBatchTarget* target) {
|
||||
const char* signal_name;
|
||||
@ -268,7 +304,8 @@ static bool infrared_remote_rename_signal_callback(
|
||||
return infrared_signal_save(batch->signal, batch->ff_out, signal_name);
|
||||
}
|
||||
|
||||
bool infrared_remote_rename_signal(InfraredRemote* remote, size_t index, const char* new_name) {
|
||||
InfraredErrorCode
|
||||
infrared_remote_rename_signal(InfraredRemote* remote, size_t index, const char* new_name) {
|
||||
furi_assert(index < infrared_remote_get_signal_count(remote));
|
||||
|
||||
const InfraredBatchTarget rename_target = {
|
||||
@ -281,7 +318,7 @@ bool infrared_remote_rename_signal(InfraredRemote* remote, size_t index, const c
|
||||
remote, infrared_remote_rename_signal_callback, &rename_target);
|
||||
}
|
||||
|
||||
static bool infrared_remote_delete_signal_callback(
|
||||
static InfraredErrorCode infrared_remote_delete_signal_callback(
|
||||
const InfraredBatch* batch,
|
||||
const InfraredBatchTarget* target) {
|
||||
if(batch->signal_index == target->signal_index) {
|
||||
@ -294,10 +331,10 @@ static bool infrared_remote_delete_signal_callback(
|
||||
batch->signal, batch->ff_out, furi_string_get_cstr(batch->signal_name));
|
||||
}
|
||||
|
||||
return true;
|
||||
return InfraredErrorCodeNone;
|
||||
}
|
||||
|
||||
bool infrared_remote_delete_signal(InfraredRemote* remote, size_t index) {
|
||||
InfraredErrorCode infrared_remote_delete_signal(InfraredRemote* remote, size_t index) {
|
||||
furi_assert(index < infrared_remote_get_signal_count(remote));
|
||||
|
||||
const InfraredBatchTarget delete_target = {
|
||||
@ -310,33 +347,35 @@ bool infrared_remote_delete_signal(InfraredRemote* remote, size_t index) {
|
||||
remote, infrared_remote_delete_signal_callback, &delete_target);
|
||||
}
|
||||
|
||||
bool infrared_remote_move_signal(InfraredRemote* remote, size_t index, size_t new_index) {
|
||||
InfraredErrorCode
|
||||
infrared_remote_move_signal(InfraredRemote* remote, size_t index, size_t new_index) {
|
||||
const size_t signal_count = infrared_remote_get_signal_count(remote);
|
||||
furi_assert(index < signal_count);
|
||||
furi_assert(new_index < signal_count);
|
||||
|
||||
if(index == new_index) return true;
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
if(index == new_index) return error;
|
||||
|
||||
InfraredSignal* signal = infrared_signal_alloc();
|
||||
char* signal_name = strdup(infrared_remote_get_signal_name(remote, index));
|
||||
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
if(!infrared_remote_load_signal(remote, signal, index)) break;
|
||||
if(!infrared_remote_delete_signal(remote, index)) break;
|
||||
if(!infrared_remote_insert_signal(remote, signal, signal_name, new_index)) break;
|
||||
error = infrared_remote_load_signal(remote, signal, index);
|
||||
if(INFRARED_ERROR_PRESENT(error)) break;
|
||||
|
||||
success = true;
|
||||
error = infrared_remote_delete_signal(remote, index);
|
||||
if(INFRARED_ERROR_PRESENT(error)) break;
|
||||
|
||||
error = infrared_remote_insert_signal(remote, signal, signal_name, new_index);
|
||||
} while(false);
|
||||
|
||||
free(signal_name);
|
||||
infrared_signal_free(signal);
|
||||
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
bool infrared_remote_create(InfraredRemote* remote, const char* path) {
|
||||
InfraredErrorCode infrared_remote_create(InfraredRemote* remote, const char* path) {
|
||||
FURI_LOG_I(TAG, "Creating new file: '%s'", path);
|
||||
|
||||
infrared_remote_reset(remote);
|
||||
@ -358,45 +397,64 @@ bool infrared_remote_create(InfraredRemote* remote, const char* path) {
|
||||
flipper_format_free(ff);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return success;
|
||||
return success ? InfraredErrorCodeNone : InfraredErrorCodeFileOperationFailed;
|
||||
}
|
||||
|
||||
bool infrared_remote_load(InfraredRemote* remote, const char* path) {
|
||||
InfraredErrorCode infrared_remote_load(InfraredRemote* remote, const char* path) {
|
||||
FURI_LOG_I(TAG, "Loading file: '%s'", path);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* ff = flipper_format_buffered_file_alloc(storage);
|
||||
|
||||
FuriString* tmp = furi_string_alloc();
|
||||
bool success = false;
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
|
||||
do {
|
||||
if(!flipper_format_buffered_file_open_existing(ff, path)) break;
|
||||
if(!flipper_format_buffered_file_open_existing(ff, path)) {
|
||||
error = InfraredErrorCodeFileOperationFailed;
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t version;
|
||||
if(!flipper_format_read_header(ff, tmp, &version)) break;
|
||||
|
||||
if(!furi_string_equal(tmp, INFRARED_FILE_HEADER) || (version != INFRARED_FILE_VERSION))
|
||||
if(!flipper_format_read_header(ff, tmp, &version)) {
|
||||
error = InfraredErrorCodeFileOperationFailed;
|
||||
break;
|
||||
}
|
||||
|
||||
if(furi_string_equal(tmp, INFRARED_LIBRARY_HEADER)) {
|
||||
FURI_LOG_E(TAG, "Library file can't be loaded in this context");
|
||||
error = InfraredErrorCodeWrongFileType;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!furi_string_equal(tmp, INFRARED_FILE_HEADER)) {
|
||||
error = InfraredErrorCodeWrongFileType;
|
||||
FURI_LOG_E(TAG, "Filetype unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
if(version != INFRARED_FILE_VERSION) {
|
||||
error = InfraredErrorCodeWrongFileVersion;
|
||||
FURI_LOG_E(TAG, "Wrong file version");
|
||||
break;
|
||||
}
|
||||
|
||||
infrared_remote_set_path(remote, path);
|
||||
StringArray_reset(remote->signal_names);
|
||||
|
||||
while(infrared_signal_read_name(ff, tmp)) {
|
||||
while(infrared_signal_read_name(ff, tmp) == InfraredErrorCodeNone) {
|
||||
StringArray_push_back(remote->signal_names, furi_string_get_cstr(tmp));
|
||||
}
|
||||
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
furi_string_free(tmp);
|
||||
flipper_format_free(ff);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
bool infrared_remote_rename(InfraredRemote* remote, const char* new_path) {
|
||||
InfraredErrorCode infrared_remote_rename(InfraredRemote* remote, const char* new_path) {
|
||||
const char* old_path = infrared_remote_get_path(remote);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
@ -409,10 +467,10 @@ bool infrared_remote_rename(InfraredRemote* remote, const char* new_path) {
|
||||
infrared_remote_set_path(remote, new_path);
|
||||
}
|
||||
|
||||
return success;
|
||||
return success ? InfraredErrorCodeNone : InfraredErrorCodeFileOperationFailed;
|
||||
}
|
||||
|
||||
bool infrared_remote_remove(InfraredRemote* remote) {
|
||||
InfraredErrorCode infrared_remote_remove(InfraredRemote* remote) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
const FS_Error status = storage_common_remove(storage, infrared_remote_get_path(remote));
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
@ -423,5 +481,5 @@ bool infrared_remote_remove(InfraredRemote* remote) {
|
||||
infrared_remote_reset(remote);
|
||||
}
|
||||
|
||||
return success;
|
||||
return success ? InfraredErrorCodeNone : InfraredErrorCodeFileOperationFailed;
|
||||
}
|
||||
|
@ -105,12 +105,10 @@ bool infrared_remote_get_signal_index(
|
||||
* @param[in] remote pointer to the instance to load from.
|
||||
* @param[out] signal pointer to the signal to load into. Must be allocated.
|
||||
* @param[in] index index of the signal to be loaded. Must be less than the total signal count.
|
||||
* @return true if the signal was successfully loaded, false otherwise.
|
||||
* @return InfraredErrorCodeNone if the signal was successfully loaded, otherwise error code.
|
||||
*/
|
||||
bool infrared_remote_load_signal(
|
||||
const InfraredRemote* remote,
|
||||
InfraredSignal* signal,
|
||||
size_t index);
|
||||
InfraredErrorCode
|
||||
infrared_remote_load_signal(const InfraredRemote* remote, InfraredSignal* signal, size_t index);
|
||||
|
||||
/**
|
||||
* @brief Append a signal to the file associated with an InfraredRemote instance.
|
||||
@ -121,9 +119,9 @@ bool infrared_remote_load_signal(
|
||||
* @param[in,out] remote pointer to the instance to append to.
|
||||
* @param[in] signal pointer to the signal to be appended.
|
||||
* @param[in] name pointer to a zero-terminated string containing the name of the signal.
|
||||
* @returns true if the signal was successfully appended, false otherwise.
|
||||
* @returns InfraredErrorCodeNone if the signal was successfully appended, otherwise error code.
|
||||
*/
|
||||
bool infrared_remote_append_signal(
|
||||
InfraredErrorCode infrared_remote_append_signal(
|
||||
InfraredRemote* remote,
|
||||
const InfraredSignal* signal,
|
||||
const char* name);
|
||||
@ -141,9 +139,10 @@ bool infrared_remote_append_signal(
|
||||
* @param[in] signal pointer to the signal to be inserted.
|
||||
* @param[in] name pointer to a zero-terminated string containing the name of the signal.
|
||||
* @param[in] index the index under which the signal shall be inserted.
|
||||
* @returns true if the signal was successfully inserted, false otherwise.
|
||||
* @returns InfraredErrorCodeNone if the signal was successfully inserted, otherwise error
|
||||
* code describing what error happened ORed with index pointing which signal caused an error.
|
||||
*/
|
||||
bool infrared_remote_insert_signal(
|
||||
InfraredErrorCode infrared_remote_insert_signal(
|
||||
InfraredRemote* remote,
|
||||
const InfraredSignal* signal,
|
||||
const char* name,
|
||||
@ -157,9 +156,10 @@ bool infrared_remote_insert_signal(
|
||||
* @param[in,out] remote pointer to the instance to be modified.
|
||||
* @param[in] index index of the signal to be renamed. Must be less than the total signal count.
|
||||
* @param[in] new_name pointer to a zero-terminated string containig the signal's new name.
|
||||
* @returns true if the signal was successfully renamed, false otherwise.
|
||||
* @returns InfraredErrorCodeNone if the signal was successfully renamed, otherwise error code.
|
||||
*/
|
||||
bool infrared_remote_rename_signal(InfraredRemote* remote, size_t index, const char* new_name);
|
||||
InfraredErrorCode
|
||||
infrared_remote_rename_signal(InfraredRemote* remote, size_t index, const char* new_name);
|
||||
|
||||
/**
|
||||
* @brief Change a signal's position in the file associated with an InfraredRemote instance.
|
||||
@ -169,17 +169,21 @@ bool infrared_remote_rename_signal(InfraredRemote* remote, size_t index, const c
|
||||
* @param[in,out] remote pointer to the instance to be modified.
|
||||
* @param[in] index index of the signal to be moved. Must be less than the total signal count.
|
||||
* @param[in] new_index index of the signal to be moved. Must be less than the total signal count.
|
||||
* @returns InfraredErrorCodeNone if the signal was moved successfully, otherwise error
|
||||
* code describing what error happened ORed with index pointing which signal caused an error.
|
||||
*/
|
||||
bool infrared_remote_move_signal(InfraredRemote* remote, size_t index, size_t new_index);
|
||||
InfraredErrorCode
|
||||
infrared_remote_move_signal(InfraredRemote* remote, size_t index, size_t new_index);
|
||||
|
||||
/**
|
||||
* @brief Delete a signal in the file associated with an InfraredRemote instance.
|
||||
*
|
||||
* @param[in,out] remote pointer to the instance to be modified.
|
||||
* @param[in] index index of the signal to be deleted. Must be less than the total signal count.
|
||||
* @returns true if the signal was successfully deleted, false otherwise.
|
||||
* @returns InfraredErrorCodeNone if the signal was successfully deleted, otherwise error
|
||||
* code describing what error happened ORed with index pointing which signal caused an error.
|
||||
*/
|
||||
bool infrared_remote_delete_signal(InfraredRemote* remote, size_t index);
|
||||
InfraredErrorCode infrared_remote_delete_signal(InfraredRemote* remote, size_t index);
|
||||
|
||||
/**
|
||||
* @brief Create a new file and associate it with an InfraredRemote instance.
|
||||
@ -188,9 +192,9 @@ bool infrared_remote_delete_signal(InfraredRemote* remote, size_t index);
|
||||
*
|
||||
* @param[in,out] remote pointer to the instance to be assigned with a new file.
|
||||
* @param[in] path pointer to a zero-terminated string containing the full file path.
|
||||
* @returns true if the file was successfully created, false otherwise.
|
||||
* @returns InfraredErrorCodeNone if the file was successfully created, otherwise error code.
|
||||
*/
|
||||
bool infrared_remote_create(InfraredRemote* remote, const char* path);
|
||||
InfraredErrorCode infrared_remote_create(InfraredRemote* remote, const char* path);
|
||||
|
||||
/**
|
||||
* @brief Associate an InfraredRemote instance with a file and load the signal names from it.
|
||||
@ -200,9 +204,9 @@ bool infrared_remote_create(InfraredRemote* remote, const char* path);
|
||||
*
|
||||
* @param[in,out] remote pointer to the instance to be assigned with an existing file.
|
||||
* @param[in] path pointer to a zero-terminated string containing the full file path.
|
||||
* @returns true if the file was successfully loaded, false otherwise.
|
||||
* @returns InfraredErrorCodeNone if the file was successfully loaded, otherwise error code.
|
||||
*/
|
||||
bool infrared_remote_load(InfraredRemote* remote, const char* path);
|
||||
InfraredErrorCode infrared_remote_load(InfraredRemote* remote, const char* path);
|
||||
|
||||
/**
|
||||
* @brief Rename the file associated with an InfraredRemote instance.
|
||||
@ -211,9 +215,9 @@ bool infrared_remote_load(InfraredRemote* remote, const char* path);
|
||||
*
|
||||
* @param[in,out] remote pointer to the instance to be modified.
|
||||
* @param[in] new_path pointer to a zero-terminated string containing the new full file path.
|
||||
* @returns true if the file was successfully renamed, false otherwise.
|
||||
* @returns InfraredErrorCodeNone if the file was successfully renamed, otherwise error code.
|
||||
*/
|
||||
bool infrared_remote_rename(InfraredRemote* remote, const char* new_path);
|
||||
InfraredErrorCode infrared_remote_rename(InfraredRemote* remote, const char* new_path);
|
||||
|
||||
/**
|
||||
* @brief Remove the file associated with an InfraredRemote instance.
|
||||
@ -224,6 +228,6 @@ bool infrared_remote_rename(InfraredRemote* remote, const char* new_path);
|
||||
* infrared_remote_create() or infrared_remote_load() are successfully executed.
|
||||
*
|
||||
* @param[in,out] remote pointer to the instance to be modified.
|
||||
* @returns true if the file was successfully removed, false otherwise.
|
||||
* @returns InfraredErrorCodeNone if the file was successfully removed, otherwise error code.
|
||||
*/
|
||||
bool infrared_remote_remove(InfraredRemote* remote);
|
||||
InfraredErrorCode infrared_remote_remove(InfraredRemote* remote);
|
||||
|
@ -101,104 +101,177 @@ static bool infrared_signal_is_raw_valid(const InfraredRawSignal* raw) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static inline InfraredErrorCode
|
||||
infrared_signal_save_message(const InfraredMessage* message, FlipperFormat* ff) {
|
||||
const char* protocol_name = infrared_get_protocol_name(message->protocol);
|
||||
return flipper_format_write_string_cstr(
|
||||
ff, INFRARED_SIGNAL_TYPE_KEY, INFRARED_SIGNAL_TYPE_PARSED) &&
|
||||
flipper_format_write_string_cstr(ff, INFRARED_SIGNAL_PROTOCOL_KEY, protocol_name) &&
|
||||
flipper_format_write_hex(
|
||||
ff, INFRARED_SIGNAL_ADDRESS_KEY, (uint8_t*)&message->address, 4) &&
|
||||
flipper_format_write_hex(
|
||||
ff, INFRARED_SIGNAL_COMMAND_KEY, (uint8_t*)&message->command, 4);
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
do {
|
||||
if(!flipper_format_write_string_cstr(
|
||||
ff, INFRARED_SIGNAL_TYPE_KEY, INFRARED_SIGNAL_TYPE_PARSED)) {
|
||||
error = InfraredErrorCodeSignalUnableToWriteType;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_write_string_cstr(ff, INFRARED_SIGNAL_PROTOCOL_KEY, protocol_name)) {
|
||||
error = InfraredErrorCodeSignalMessageUnableToWriteProtocol;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_write_hex(
|
||||
ff, INFRARED_SIGNAL_ADDRESS_KEY, (uint8_t*)&message->address, 4)) {
|
||||
error = InfraredErrorCodeSignalMessageUnableToWriteAddress;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_write_hex(
|
||||
ff, INFRARED_SIGNAL_COMMAND_KEY, (uint8_t*)&message->command, 4)) {
|
||||
error = InfraredErrorCodeSignalMessageUnableToWriteCommand;
|
||||
break;
|
||||
}
|
||||
|
||||
} while(false);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static inline bool infrared_signal_save_raw(const InfraredRawSignal* raw, FlipperFormat* ff) {
|
||||
static inline InfraredErrorCode
|
||||
infrared_signal_save_raw(const InfraredRawSignal* raw, FlipperFormat* ff) {
|
||||
furi_assert(raw->timings_size <= MAX_TIMINGS_AMOUNT);
|
||||
return flipper_format_write_string_cstr(
|
||||
ff, INFRARED_SIGNAL_TYPE_KEY, INFRARED_SIGNAL_TYPE_RAW) &&
|
||||
flipper_format_write_uint32(ff, INFRARED_SIGNAL_FREQUENCY_KEY, &raw->frequency, 1) &&
|
||||
flipper_format_write_float(ff, INFRARED_SIGNAL_DUTY_CYCLE_KEY, &raw->duty_cycle, 1) &&
|
||||
flipper_format_write_uint32(
|
||||
ff, INFRARED_SIGNAL_DATA_KEY, raw->timings, raw->timings_size);
|
||||
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
do {
|
||||
if(!flipper_format_write_string_cstr(
|
||||
ff, INFRARED_SIGNAL_TYPE_KEY, INFRARED_SIGNAL_TYPE_RAW)) {
|
||||
error = InfraredErrorCodeSignalUnableToWriteType;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_write_uint32(ff, INFRARED_SIGNAL_FREQUENCY_KEY, &raw->frequency, 1)) {
|
||||
error = InfraredErrorCodeSignalRawUnableToWriteFrequency;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_write_float(ff, INFRARED_SIGNAL_DUTY_CYCLE_KEY, &raw->duty_cycle, 1)) {
|
||||
error = InfraredErrorCodeSignalRawUnableToWriteDutyCycle;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_write_uint32(
|
||||
ff, INFRARED_SIGNAL_DATA_KEY, raw->timings, raw->timings_size)) {
|
||||
error = InfraredErrorCodeSignalRawUnableToWriteData;
|
||||
break;
|
||||
}
|
||||
} while(false);
|
||||
return error;
|
||||
}
|
||||
|
||||
static inline bool infrared_signal_read_message(InfraredSignal* signal, FlipperFormat* ff) {
|
||||
static inline InfraredErrorCode
|
||||
infrared_signal_read_message(InfraredSignal* signal, FlipperFormat* ff) {
|
||||
FuriString* buf;
|
||||
buf = furi_string_alloc();
|
||||
bool success = false;
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
|
||||
do {
|
||||
if(!flipper_format_read_string(ff, INFRARED_SIGNAL_PROTOCOL_KEY, buf)) break;
|
||||
if(!flipper_format_read_string(ff, INFRARED_SIGNAL_PROTOCOL_KEY, buf)) {
|
||||
error = InfraredErrorCodeSignalMessageUnableToReadProtocol;
|
||||
break;
|
||||
}
|
||||
|
||||
InfraredMessage message;
|
||||
message.protocol = infrared_get_protocol_by_name(furi_string_get_cstr(buf));
|
||||
|
||||
if(!flipper_format_read_hex(ff, INFRARED_SIGNAL_ADDRESS_KEY, (uint8_t*)&message.address, 4))
|
||||
if(!flipper_format_read_hex(
|
||||
ff, INFRARED_SIGNAL_ADDRESS_KEY, (uint8_t*)&message.address, 4)) {
|
||||
error = InfraredErrorCodeSignalMessageUnableToReadAddress;
|
||||
break;
|
||||
if(!flipper_format_read_hex(ff, INFRARED_SIGNAL_COMMAND_KEY, (uint8_t*)&message.command, 4))
|
||||
}
|
||||
if(!flipper_format_read_hex(
|
||||
ff, INFRARED_SIGNAL_COMMAND_KEY, (uint8_t*)&message.command, 4)) {
|
||||
error = InfraredErrorCodeSignalMessageUnableToReadCommand;
|
||||
break;
|
||||
if(!infrared_signal_is_message_valid(&message)) break;
|
||||
}
|
||||
|
||||
if(!infrared_signal_is_message_valid(&message)) {
|
||||
error = InfraredErrorCodeSignalMessageIsInvalid;
|
||||
break;
|
||||
}
|
||||
|
||||
infrared_signal_set_message(signal, &message);
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
furi_string_free(buf);
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
static inline bool infrared_signal_read_raw(InfraredSignal* signal, FlipperFormat* ff) {
|
||||
bool success = false;
|
||||
static inline InfraredErrorCode
|
||||
infrared_signal_read_raw(InfraredSignal* signal, FlipperFormat* ff) {
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
|
||||
do {
|
||||
uint32_t frequency;
|
||||
if(!flipper_format_read_uint32(ff, INFRARED_SIGNAL_FREQUENCY_KEY, &frequency, 1)) break;
|
||||
if(!flipper_format_read_uint32(ff, INFRARED_SIGNAL_FREQUENCY_KEY, &frequency, 1)) {
|
||||
error = InfraredErrorCodeSignalRawUnableToReadFrequency;
|
||||
break;
|
||||
}
|
||||
|
||||
float duty_cycle;
|
||||
if(!flipper_format_read_float(ff, INFRARED_SIGNAL_DUTY_CYCLE_KEY, &duty_cycle, 1)) break;
|
||||
if(!flipper_format_read_float(ff, INFRARED_SIGNAL_DUTY_CYCLE_KEY, &duty_cycle, 1)) {
|
||||
error = InfraredErrorCodeSignalRawUnableToReadDutyCycle;
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t timings_size;
|
||||
if(!flipper_format_get_value_count(ff, INFRARED_SIGNAL_DATA_KEY, &timings_size)) break;
|
||||
if(!flipper_format_get_value_count(ff, INFRARED_SIGNAL_DATA_KEY, &timings_size)) {
|
||||
error = InfraredErrorCodeSignalRawUnableToReadTimingsSize;
|
||||
break;
|
||||
}
|
||||
|
||||
if(timings_size > MAX_TIMINGS_AMOUNT) break;
|
||||
if(timings_size > MAX_TIMINGS_AMOUNT) {
|
||||
error = InfraredErrorCodeSignalRawUnableToReadTooLongData;
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t* timings = malloc(sizeof(uint32_t) * timings_size);
|
||||
if(!flipper_format_read_uint32(ff, INFRARED_SIGNAL_DATA_KEY, timings, timings_size)) {
|
||||
error = InfraredErrorCodeSignalRawUnableToReadData;
|
||||
free(timings);
|
||||
break;
|
||||
}
|
||||
|
||||
infrared_signal_set_raw_signal(signal, timings, timings_size, frequency, duty_cycle);
|
||||
free(timings);
|
||||
|
||||
success = true;
|
||||
error = InfraredErrorCodeNone;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
bool infrared_signal_read_body(InfraredSignal* signal, FlipperFormat* ff) {
|
||||
InfraredErrorCode infrared_signal_read_body(InfraredSignal* signal, FlipperFormat* ff) {
|
||||
FuriString* tmp = furi_string_alloc();
|
||||
|
||||
bool success = false;
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
|
||||
do {
|
||||
if(!flipper_format_read_string(ff, INFRARED_SIGNAL_TYPE_KEY, tmp)) break;
|
||||
|
||||
if(furi_string_equal(tmp, INFRARED_SIGNAL_TYPE_RAW)) {
|
||||
if(!infrared_signal_read_raw(signal, ff)) break;
|
||||
} else if(furi_string_equal(tmp, INFRARED_SIGNAL_TYPE_PARSED)) {
|
||||
if(!infrared_signal_read_message(signal, ff)) break;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Unknown signal type: %s", furi_string_get_cstr(tmp));
|
||||
if(!flipper_format_read_string(ff, INFRARED_SIGNAL_TYPE_KEY, tmp)) {
|
||||
error = InfraredErrorCodeSignalUnableToReadType;
|
||||
break;
|
||||
}
|
||||
|
||||
success = true;
|
||||
if(furi_string_equal(tmp, INFRARED_SIGNAL_TYPE_RAW)) {
|
||||
error = infrared_signal_read_raw(signal, ff);
|
||||
} else if(furi_string_equal(tmp, INFRARED_SIGNAL_TYPE_PARSED)) {
|
||||
error = infrared_signal_read_message(signal, ff);
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Unknown signal type: %s", furi_string_get_cstr(tmp));
|
||||
error = InfraredErrorCodeSignalTypeUnknown;
|
||||
break;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
furi_string_free(tmp);
|
||||
return success;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
InfraredSignal* infrared_signal_alloc(void) {
|
||||
@ -270,68 +343,88 @@ const InfraredMessage* infrared_signal_get_message(const InfraredSignal* signal)
|
||||
return &signal->payload.message;
|
||||
}
|
||||
|
||||
bool infrared_signal_save(const InfraredSignal* signal, FlipperFormat* ff, const char* name) {
|
||||
InfraredErrorCode
|
||||
infrared_signal_save(const InfraredSignal* signal, FlipperFormat* ff, const char* name) {
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
|
||||
if(!flipper_format_write_comment_cstr(ff, "") ||
|
||||
!flipper_format_write_string_cstr(ff, INFRARED_SIGNAL_NAME_KEY, name)) {
|
||||
return false;
|
||||
error = InfraredErrorCodeFileOperationFailed;
|
||||
} else if(signal->is_raw) {
|
||||
return infrared_signal_save_raw(&signal->payload.raw, ff);
|
||||
error = infrared_signal_save_raw(&signal->payload.raw, ff);
|
||||
} else {
|
||||
return infrared_signal_save_message(&signal->payload.message, ff);
|
||||
error = infrared_signal_save_message(&signal->payload.message, ff);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* name) {
|
||||
bool success = false;
|
||||
InfraredErrorCode
|
||||
infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* name) {
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
|
||||
do {
|
||||
if(!infrared_signal_read_name(ff, name)) break;
|
||||
if(!infrared_signal_read_body(signal, ff)) break;
|
||||
error = infrared_signal_read_name(ff, name);
|
||||
if(INFRARED_ERROR_PRESENT(error)) break;
|
||||
|
||||
success = true; //-V779
|
||||
error = infrared_signal_read_body(signal, ff);
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
bool infrared_signal_read_name(FlipperFormat* ff, FuriString* name) {
|
||||
return flipper_format_read_string(ff, INFRARED_SIGNAL_NAME_KEY, name);
|
||||
InfraredErrorCode infrared_signal_read_name(FlipperFormat* ff, FuriString* name) {
|
||||
return flipper_format_read_string(ff, INFRARED_SIGNAL_NAME_KEY, name) ?
|
||||
InfraredErrorCodeNone :
|
||||
InfraredErrorCodeSignalNameNotFound;
|
||||
}
|
||||
|
||||
bool infrared_signal_search_by_name_and_read(
|
||||
InfraredErrorCode infrared_signal_search_by_name_and_read(
|
||||
InfraredSignal* signal,
|
||||
FlipperFormat* ff,
|
||||
const char* name) {
|
||||
bool success = false;
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
FuriString* tmp = furi_string_alloc();
|
||||
|
||||
while(infrared_signal_read_name(ff, tmp)) {
|
||||
do {
|
||||
error = infrared_signal_read_name(ff, tmp);
|
||||
if(INFRARED_ERROR_PRESENT(error)) break;
|
||||
|
||||
if(furi_string_equal(tmp, name)) {
|
||||
success = infrared_signal_read_body(signal, ff);
|
||||
error = infrared_signal_read_body(signal, ff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(true);
|
||||
|
||||
furi_string_free(tmp);
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
bool infrared_signal_search_by_index_and_read(
|
||||
InfraredErrorCode infrared_signal_search_by_index_and_read(
|
||||
InfraredSignal* signal,
|
||||
FlipperFormat* ff,
|
||||
size_t index) {
|
||||
bool success = false;
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
FuriString* tmp = furi_string_alloc();
|
||||
|
||||
for(uint32_t i = 0; infrared_signal_read_name(ff, tmp); ++i) {
|
||||
for(uint32_t i = 0;; ++i) {
|
||||
error = infrared_signal_read_name(ff, tmp);
|
||||
if(INFRARED_ERROR_PRESENT(error)) {
|
||||
INFRARED_ERROR_SET_INDEX(error, i);
|
||||
break;
|
||||
}
|
||||
|
||||
if(i == index) {
|
||||
success = infrared_signal_read_body(signal, ff);
|
||||
error = infrared_signal_read_body(signal, ff);
|
||||
if(INFRARED_ERROR_PRESENT(error)) {
|
||||
INFRARED_ERROR_SET_INDEX(error, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
furi_string_free(tmp);
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
void infrared_signal_transmit(const InfraredSignal* signal) {
|
||||
|
@ -8,6 +8,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "infrared_error_code.h"
|
||||
#include <flipper_format/flipper_format.h>
|
||||
#include <infrared/encoder_decoder/infrared.h>
|
||||
|
||||
@ -136,9 +137,10 @@ const InfraredMessage* infrared_signal_get_message(const InfraredSignal* signal)
|
||||
* @param[in,out] signal pointer to the instance to be read into.
|
||||
* @param[in,out] ff pointer to the FlipperFormat file instance to read from.
|
||||
* @param[out] name pointer to the string to hold the signal name. Must be properly allocated.
|
||||
* @returns true if a signal was successfully read, false otherwise (e.g. no more signals to read).
|
||||
* @returns InfraredErrorCodeNone if a signal was successfully read, otherwise error code
|
||||
*/
|
||||
bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* name);
|
||||
InfraredErrorCode
|
||||
infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* name);
|
||||
|
||||
/**
|
||||
* @brief Read a signal name from a FlipperFormat file.
|
||||
@ -147,9 +149,9 @@ bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString*
|
||||
*
|
||||
* @param[in,out] ff pointer to the FlipperFormat file instance to read from.
|
||||
* @param[out] name pointer to the string to hold the signal name. Must be properly allocated.
|
||||
* @returns true if a signal name was successfully read, false otherwise (e.g. no more signals to read).
|
||||
* @returns InfraredErrorCodeNone if a signal name was successfully read, otherwise error code
|
||||
*/
|
||||
bool infrared_signal_read_name(FlipperFormat* ff, FuriString* name);
|
||||
InfraredErrorCode infrared_signal_read_name(FlipperFormat* ff, FuriString* name);
|
||||
|
||||
/**
|
||||
* @brief Read a signal from a FlipperFormat file.
|
||||
@ -158,9 +160,9 @@ bool infrared_signal_read_name(FlipperFormat* ff, FuriString* name);
|
||||
*
|
||||
* @param[in,out] ff pointer to the FlipperFormat file instance to read from.
|
||||
* @param[out] body pointer to the InfraredSignal instance to hold the signal body. Must be properly allocated.
|
||||
* @returns true if a signal body was successfully read, false otherwise (e.g. syntax error).
|
||||
* @returns InfraredErrorCodeNone if a signal body was successfully read, otherwise error code.
|
||||
*/
|
||||
bool infrared_signal_read_body(InfraredSignal* signal, FlipperFormat* ff);
|
||||
InfraredErrorCode infrared_signal_read_body(InfraredSignal* signal, FlipperFormat* ff);
|
||||
|
||||
/**
|
||||
* @brief Read a signal with a particular name from a FlipperFormat file into an InfraredSignal instance.
|
||||
@ -171,9 +173,9 @@ bool infrared_signal_read_body(InfraredSignal* signal, FlipperFormat* ff);
|
||||
* @param[in,out] signal pointer to the instance to be read into.
|
||||
* @param[in,out] ff pointer to the FlipperFormat file instance to read from.
|
||||
* @param[in] name pointer to a zero-terminated string containing the requested signal name.
|
||||
* @returns true if a signal was found and successfully read, false otherwise (e.g. the signal was not found).
|
||||
* @returns InfraredErrorCodeNone if a signal was found and successfully read, otherwise error code.
|
||||
*/
|
||||
bool infrared_signal_search_by_name_and_read(
|
||||
InfraredErrorCode infrared_signal_search_by_name_and_read(
|
||||
InfraredSignal* signal,
|
||||
FlipperFormat* ff,
|
||||
const char* name);
|
||||
@ -187,9 +189,9 @@ bool infrared_signal_search_by_name_and_read(
|
||||
* @param[in,out] signal pointer to the instance to be read into.
|
||||
* @param[in,out] ff pointer to the FlipperFormat file instance to read from.
|
||||
* @param[in] index the requested signal index.
|
||||
* @returns true if a signal was found and successfully read, false otherwise (e.g. the signal was not found).
|
||||
* @returns InfraredErrorCodeNone if a signal was found and successfully read, otherwise error code.
|
||||
*/
|
||||
bool infrared_signal_search_by_index_and_read(
|
||||
InfraredErrorCode infrared_signal_search_by_index_and_read(
|
||||
InfraredSignal* signal,
|
||||
FlipperFormat* ff,
|
||||
size_t index);
|
||||
@ -203,8 +205,10 @@ bool infrared_signal_search_by_index_and_read(
|
||||
* @param[in] signal pointer to the instance holding the signal to be saved.
|
||||
* @param[in,out] ff pointer to the FlipperFormat file instance to write to.
|
||||
* @param[in] name pointer to a zero-terminated string contating the name of the signal.
|
||||
* @returns InfraredErrorCodeNone if a signal was successfully saved, otherwise error code
|
||||
*/
|
||||
bool infrared_signal_save(const InfraredSignal* signal, FlipperFormat* ff, const char* name);
|
||||
InfraredErrorCode
|
||||
infrared_signal_save(const InfraredSignal* signal, FlipperFormat* ff, const char* name);
|
||||
|
||||
/**
|
||||
* @brief Transmit a signal contained in an InfraredSignal instance.
|
||||
|
@ -34,12 +34,12 @@ static void infrared_scene_universal_common_hide_popup(InfraredApp* infrared) {
|
||||
|
||||
static int32_t infrared_scene_universal_common_task_callback(void* context) {
|
||||
InfraredApp* infrared = context;
|
||||
const bool success = infrared_brute_force_calculate_messages(infrared->brute_force);
|
||||
const InfraredErrorCode error = infrared_brute_force_calculate_messages(infrared->brute_force);
|
||||
view_dispatcher_send_custom_event(
|
||||
infrared->view_dispatcher,
|
||||
infrared_custom_event_pack(InfraredCustomEventTypeTaskFinished, 0));
|
||||
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
void infrared_scene_universal_common_on_enter(void* context) {
|
||||
@ -93,9 +93,9 @@ bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent e
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneErrorDatabases);
|
||||
}
|
||||
} else if(event_type == InfraredCustomEventTypeTaskFinished) {
|
||||
const bool task_success = infrared_blocking_task_finalize(infrared);
|
||||
const InfraredErrorCode task_error = infrared_blocking_task_finalize(infrared);
|
||||
|
||||
if(!task_success) {
|
||||
if(INFRARED_ERROR_PRESENT(task_error)) {
|
||||
scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases);
|
||||
} else {
|
||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack);
|
||||
|
@ -11,12 +11,12 @@ static int32_t infrared_scene_edit_delete_task_callback(void* context) {
|
||||
InfraredAppState* app_state = &infrared->app_state;
|
||||
const InfraredEditTarget edit_target = app_state->edit_target;
|
||||
|
||||
bool success;
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
if(edit_target == InfraredEditTargetButton) {
|
||||
furi_assert(app_state->current_button_index != InfraredButtonIndexNone);
|
||||
success = infrared_remote_delete_signal(infrared->remote, app_state->current_button_index);
|
||||
error = infrared_remote_delete_signal(infrared->remote, app_state->current_button_index);
|
||||
} else if(edit_target == InfraredEditTargetRemote) {
|
||||
success = infrared_remote_remove(infrared->remote);
|
||||
error = infrared_remote_remove(infrared->remote);
|
||||
} else {
|
||||
furi_crash();
|
||||
}
|
||||
@ -24,7 +24,7 @@ static int32_t infrared_scene_edit_delete_task_callback(void* context) {
|
||||
view_dispatcher_send_custom_event(
|
||||
infrared->view_dispatcher, InfraredCustomEventTypeTaskFinished);
|
||||
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
void infrared_scene_edit_delete_on_enter(void* context) {
|
||||
@ -39,11 +39,15 @@ void infrared_scene_edit_delete_on_enter(void* context) {
|
||||
const int32_t current_button_index = infrared->app_state.current_button_index;
|
||||
furi_check(current_button_index != InfraredButtonIndexNone);
|
||||
|
||||
if(!infrared_remote_load_signal(remote, infrared->current_signal, current_button_index)) {
|
||||
InfraredErrorCode error =
|
||||
infrared_remote_load_signal(remote, infrared->current_signal, current_button_index);
|
||||
if(INFRARED_ERROR_PRESENT(error)) {
|
||||
const char* format =
|
||||
(INFRARED_ERROR_CHECK(error, InfraredErrorCodeSignalRawUnableToReadTooLongData)) ?
|
||||
"Failed to delete\n\"%s\" is too long.\nTry to edit file from pc" :
|
||||
"Failed to load\n\"%s\"";
|
||||
infrared_show_error_message(
|
||||
infrared,
|
||||
"Failed to load\n\"%s\"",
|
||||
infrared_remote_get_signal_name(remote, current_button_index));
|
||||
infrared, format, infrared_remote_get_signal_name(remote, current_button_index));
|
||||
scene_manager_previous_scene(infrared->scene_manager);
|
||||
return;
|
||||
}
|
||||
@ -107,18 +111,30 @@ bool infrared_scene_edit_delete_on_event(void* context, SceneManagerEvent event)
|
||||
infrared_blocking_task_start(infrared, infrared_scene_edit_delete_task_callback);
|
||||
|
||||
} else if(event.event == InfraredCustomEventTypeTaskFinished) {
|
||||
const bool task_success = infrared_blocking_task_finalize(infrared);
|
||||
const InfraredErrorCode task_error = infrared_blocking_task_finalize(infrared);
|
||||
|
||||
InfraredAppState* app_state = &infrared->app_state;
|
||||
|
||||
if(task_success) {
|
||||
if(!INFRARED_ERROR_PRESENT(task_error)) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditDeleteDone);
|
||||
} else {
|
||||
const char* edit_target_text =
|
||||
app_state->edit_target == InfraredEditTargetButton ? "button" : "file";
|
||||
infrared_show_error_message(infrared, "Failed to\ndelete %s", edit_target_text);
|
||||
if(INFRARED_ERROR_CHECK(
|
||||
task_error, InfraredErrorCodeSignalRawUnableToReadTooLongData)) {
|
||||
const uint8_t index = INFRARED_ERROR_GET_INDEX(task_error);
|
||||
const char* format =
|
||||
"Failed to delete\n\"%s\" is too long.\nTry to edit file from pc";
|
||||
infrared_show_error_message(
|
||||
infrared,
|
||||
format,
|
||||
infrared_remote_get_signal_name(infrared->remote, index));
|
||||
} else {
|
||||
const char* edit_target_text =
|
||||
app_state->edit_target == InfraredEditTargetButton ? "button" : "file";
|
||||
infrared_show_error_message(
|
||||
infrared, "Failed to\ndelete %s", edit_target_text);
|
||||
}
|
||||
|
||||
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};
|
||||
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneRemote};
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
||||
}
|
||||
|
@ -2,14 +2,14 @@
|
||||
|
||||
static int32_t infrared_scene_edit_move_task_callback(void* context) {
|
||||
InfraredApp* infrared = context;
|
||||
const bool success = infrared_remote_move_signal(
|
||||
const InfraredErrorCode error = infrared_remote_move_signal(
|
||||
infrared->remote,
|
||||
infrared->app_state.prev_button_index,
|
||||
infrared->app_state.current_button_index);
|
||||
view_dispatcher_send_custom_event(
|
||||
infrared->view_dispatcher, InfraredCustomEventTypeTaskFinished);
|
||||
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
static void infrared_scene_edit_move_button_callback(
|
||||
@ -51,14 +51,26 @@ bool infrared_scene_edit_move_on_event(void* context, SceneManagerEvent event) {
|
||||
infrared_blocking_task_start(infrared, infrared_scene_edit_move_task_callback);
|
||||
|
||||
} else if(event.event == InfraredCustomEventTypeTaskFinished) {
|
||||
const bool task_success = infrared_blocking_task_finalize(infrared);
|
||||
const InfraredErrorCode task_error = infrared_blocking_task_finalize(infrared);
|
||||
|
||||
if(!task_success) {
|
||||
const char* signal_name = infrared_remote_get_signal_name(
|
||||
infrared->remote, infrared->app_state.current_button_index);
|
||||
infrared_show_error_message(infrared, "Failed to move\n\"%s\"", signal_name);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
infrared->scene_manager, InfraredSceneRemoteList);
|
||||
if(INFRARED_ERROR_PRESENT(task_error)) {
|
||||
const char* format = "Failed to move\n\"%s\"";
|
||||
uint8_t signal_index = infrared->app_state.prev_button_index;
|
||||
|
||||
if(INFRARED_ERROR_CHECK(
|
||||
task_error, InfraredErrorCodeSignalRawUnableToReadTooLongData)) {
|
||||
signal_index = INFRARED_ERROR_GET_INDEX(task_error);
|
||||
format = "Failed to move\n\"%s\" is too long.\nTry to edit file from pc";
|
||||
}
|
||||
furi_assert(format);
|
||||
|
||||
const char* signal_name =
|
||||
infrared_remote_get_signal_name(infrared->remote, signal_index);
|
||||
infrared_show_error_message(infrared, format, signal_name);
|
||||
|
||||
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneRemote};
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
infrared->scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
||||
} else {
|
||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewMove);
|
||||
}
|
||||
|
@ -8,13 +8,13 @@ static int32_t infrared_scene_edit_rename_task_callback(void* context) {
|
||||
InfraredAppState* app_state = &infrared->app_state;
|
||||
const InfraredEditTarget edit_target = app_state->edit_target;
|
||||
|
||||
bool success;
|
||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||
if(edit_target == InfraredEditTargetButton) {
|
||||
furi_assert(app_state->current_button_index != InfraredButtonIndexNone);
|
||||
success = infrared_remote_rename_signal(
|
||||
error = infrared_remote_rename_signal(
|
||||
infrared->remote, app_state->current_button_index, infrared->text_store[0]);
|
||||
} else if(edit_target == InfraredEditTargetRemote) {
|
||||
success = infrared_rename_current_remote(infrared, infrared->text_store[0]);
|
||||
error = infrared_rename_current_remote(infrared, infrared->text_store[0]);
|
||||
} else {
|
||||
furi_crash();
|
||||
}
|
||||
@ -22,7 +22,7 @@ static int32_t infrared_scene_edit_rename_task_callback(void* context) {
|
||||
view_dispatcher_send_custom_event(
|
||||
infrared->view_dispatcher, InfraredCustomEventTypeTaskFinished);
|
||||
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
void infrared_scene_edit_rename_on_enter(void* context) {
|
||||
@ -89,17 +89,30 @@ bool infrared_scene_edit_rename_on_event(void* context, SceneManagerEvent event)
|
||||
infrared_blocking_task_start(infrared, infrared_scene_edit_rename_task_callback);
|
||||
|
||||
} else if(event.event == InfraredCustomEventTypeTaskFinished) {
|
||||
const bool task_success = infrared_blocking_task_finalize(infrared);
|
||||
const InfraredErrorCode task_error = infrared_blocking_task_finalize(infrared);
|
||||
InfraredAppState* app_state = &infrared->app_state;
|
||||
|
||||
if(task_success) {
|
||||
if(!INFRARED_ERROR_PRESENT(task_error)) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditRenameDone);
|
||||
} else {
|
||||
const char* edit_target_text =
|
||||
app_state->edit_target == InfraredEditTargetButton ? "button" : "file";
|
||||
infrared_show_error_message(infrared, "Failed to\nrename %s", edit_target_text);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
scene_manager, InfraredSceneRemoteList);
|
||||
bool long_signal = INFRARED_ERROR_CHECK(
|
||||
task_error, InfraredErrorCodeSignalRawUnableToReadTooLongData);
|
||||
|
||||
const char* format = "Failed to rename\n%s";
|
||||
const char* target = infrared->app_state.edit_target == InfraredEditTargetButton ?
|
||||
"button" :
|
||||
"file";
|
||||
if(long_signal) {
|
||||
format = "Failed to rename\n\"%s\" is too long.\nTry to edit file from pc";
|
||||
target = infrared_remote_get_signal_name(
|
||||
infrared->remote, INFRARED_ERROR_GET_INDEX(task_error));
|
||||
}
|
||||
|
||||
infrared_show_error_message(infrared, format, target);
|
||||
|
||||
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneRemote};
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
||||
}
|
||||
|
||||
app_state->current_button_index = InfraredButtonIndexNone;
|
||||
|
@ -41,12 +41,12 @@ bool infrared_scene_learn_enter_name_on_event(void* context, SceneManagerEvent e
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == InfraredCustomEventTypeTextEditDone) {
|
||||
const char* signal_name = infrared->text_store[0];
|
||||
const bool success =
|
||||
const InfraredErrorCode error =
|
||||
infrared->app_state.is_learning_new_remote ?
|
||||
infrared_add_remote_with_button(infrared, signal_name, signal) :
|
||||
infrared_remote_append_signal(infrared->remote, signal, signal_name);
|
||||
|
||||
if(success) {
|
||||
if(!INFRARED_ERROR_PRESENT(error)) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneLearnDone);
|
||||
dolphin_deed(DolphinDeedIrSave);
|
||||
} else {
|
||||
|
@ -85,7 +85,8 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(custom_type == InfraredCustomEventTypeTransmitStarted) {
|
||||
furi_assert(button_index >= 0);
|
||||
if(!infrared_tx_start_button_index(infrared, button_index)) {
|
||||
InfraredErrorCode error = infrared_tx_start_button_index(infrared, button_index);
|
||||
if(INFRARED_ERROR_PRESENT(error)) {
|
||||
infrared_show_error_message(
|
||||
infrared,
|
||||
"Failed to load\n\"%s\"",
|
||||
|
@ -2,11 +2,11 @@
|
||||
|
||||
static int32_t infrared_scene_remote_list_task_callback(void* context) {
|
||||
InfraredApp* infrared = context;
|
||||
const bool success =
|
||||
const InfraredErrorCode error =
|
||||
infrared_remote_load(infrared->remote, furi_string_get_cstr(infrared->file_path));
|
||||
view_dispatcher_send_custom_event(
|
||||
infrared->view_dispatcher, InfraredCustomEventTypeTaskFinished);
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
static void infrared_scene_remote_list_select_and_load(InfraredApp* infrared) {
|
||||
@ -38,13 +38,19 @@ bool infrared_scene_remote_list_on_event(void* context, SceneManagerEvent event)
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == InfraredCustomEventTypeTaskFinished) {
|
||||
const bool task_success = infrared_blocking_task_finalize(infrared);
|
||||
const InfraredErrorCode task_error = infrared_blocking_task_finalize(infrared);
|
||||
|
||||
if(task_success) {
|
||||
if(!INFRARED_ERROR_PRESENT(task_error)) {
|
||||
scene_manager_next_scene(infrared->scene_manager, InfraredSceneRemote);
|
||||
} else {
|
||||
bool wrong_file_type =
|
||||
INFRARED_ERROR_CHECK(task_error, InfraredErrorCodeWrongFileType);
|
||||
const char* format = wrong_file_type ?
|
||||
"Library file\n\"%s\" can't be openned as a remote" :
|
||||
"Failed to load\n\"%s\"";
|
||||
|
||||
infrared_show_error_message(
|
||||
infrared, "Failed to load\n\"%s\"", furi_string_get_cstr(infrared->file_path));
|
||||
infrared, format, furi_string_get_cstr(infrared->file_path));
|
||||
infrared_scene_remote_list_select_and_load(infrared);
|
||||
}
|
||||
}
|
||||
|
@ -11,11 +11,11 @@ typedef enum {
|
||||
|
||||
static int32_t infrared_scene_rpc_task_callback(void* context) {
|
||||
InfraredApp* infrared = context;
|
||||
const bool success =
|
||||
const InfraredErrorCode error =
|
||||
infrared_remote_load(infrared->remote, furi_string_get_cstr(infrared->file_path));
|
||||
view_dispatcher_send_custom_event(
|
||||
infrared->view_dispatcher, InfraredCustomEventTypeTaskFinished);
|
||||
return success;
|
||||
return error;
|
||||
}
|
||||
|
||||
void infrared_scene_rpc_on_enter(void* context) {
|
||||
@ -57,8 +57,11 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
||||
}
|
||||
|
||||
} else if(event.event == InfraredCustomEventTypeTaskFinished) {
|
||||
const bool task_success = infrared_blocking_task_finalize(infrared);
|
||||
if(task_success) {
|
||||
const InfraredErrorCode task_error = infrared_blocking_task_finalize(infrared);
|
||||
|
||||
if(!INFRARED_ERROR_PRESENT(task_error)) {
|
||||
const char* remote_name = infrared_remote_get_name(infrared->remote);
|
||||
infrared_text_store_set(infrared, 0, "loaded\n%s", remote_name);
|
||||
scene_manager_set_scene_state(
|
||||
infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded);
|
||||
} else {
|
||||
@ -71,7 +74,7 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
furi_string_free(str);
|
||||
}
|
||||
rpc_system_app_confirm(infrared->rpc_ctx, task_success);
|
||||
rpc_system_app_confirm(infrared->rpc_ctx, !INFRARED_ERROR_PRESENT(task_error));
|
||||
} else if(
|
||||
event.event == InfraredCustomEventTypeRpcButtonPressName ||
|
||||
event.event == InfraredCustomEventTypeRpcButtonPressIndex) {
|
||||
@ -90,7 +93,9 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
||||
TAG, "Sending signal with index \"%ld\"", app_state->current_button_index);
|
||||
}
|
||||
if(infrared->app_state.current_button_index != InfraredButtonIndexNone) {
|
||||
if(infrared_tx_start_button_index(infrared, app_state->current_button_index)) {
|
||||
InfraredErrorCode error =
|
||||
infrared_tx_start_button_index(infrared, app_state->current_button_index);
|
||||
if(!INFRARED_ERROR_PRESENT(error)) {
|
||||
const char* remote_name = infrared_remote_get_name(infrared->remote);
|
||||
infrared_text_store_set(infrared, 0, "emulating\n%s", remote_name);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user