Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/flipperzero-firmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert Kharisov <ah@bright-box.com>2021-07-22 03:07:00 +0300
committerGitHub <noreply@github.com>2021-07-22 03:07:00 +0300
commit769ab2aef2f73a1bbbb1d9c8e08e9ae64db71576 (patch)
treefdea5c300c3255bfc3b8317b9f4cbb79f86e806f /applications/irda
parentb886ae17b60fe216f7ae1a355b8d7d531da1113f (diff)
[FL-1489] IRDA: move to FileWorker (#594)
* [FL-1489] IRDA: move to FileWorker, fixes * Use FileWorker * Use file_select to select remotes * Fix some crashes * Add RAW parsing restrictions * Remove excess scene (LearnDoneAfter) * Move all file system logic to standalone object
Diffstat (limited to 'applications/irda')
-rw-r--r--applications/irda/irda-app-brute-force.cpp53
-rw-r--r--applications/irda/irda-app-brute-force.hpp8
-rw-r--r--applications/irda/irda-app-event.hpp1
-rw-r--r--applications/irda/irda-app-file-parser.cpp240
-rw-r--r--applications/irda/irda-app-file-parser.hpp36
-rw-r--r--applications/irda/irda-app-remote-manager.cpp194
-rw-r--r--applications/irda/irda-app-remote-manager.hpp7
-rw-r--r--applications/irda/irda-app-view-manager.cpp7
-rw-r--r--applications/irda/irda-app-view-manager.hpp1
-rw-r--r--applications/irda/irda-app.cpp14
-rw-r--r--applications/irda/irda-app.hpp4
-rw-r--r--applications/irda/scene/irda-app-scene-learn-done-after.cpp32
-rw-r--r--applications/irda/scene/irda-app-scene-learn-done.cpp6
-rw-r--r--applications/irda/scene/irda-app-scene-learn-success.cpp11
-rw-r--r--applications/irda/scene/irda-app-scene-remote-list.cpp71
-rw-r--r--applications/irda/scene/irda-app-scene-start.cpp1
-rw-r--r--applications/irda/scene/irda-app-scene-universal-common.cpp35
-rw-r--r--applications/irda/scene/irda-app-scene.hpp11
18 files changed, 361 insertions, 371 deletions
diff --git a/applications/irda/irda-app-brute-force.cpp b/applications/irda/irda-app-brute-force.cpp
index 21491e76..8709dce6 100644
--- a/applications/irda/irda-app-brute-force.cpp
+++ b/applications/irda/irda-app-brute-force.cpp
@@ -1,4 +1,8 @@
#include "irda-app-brute-force.hpp"
+#include "irda/irda-app-file-parser.hpp"
+#include "m-string.h"
+#include <file-worker-cpp.h>
+#include <memory>
void IrdaAppBruteForce::add_record(int index, const char* name) {
records[name].index = index;
@@ -7,43 +11,51 @@ void IrdaAppBruteForce::add_record(int index, const char* name) {
bool IrdaAppBruteForce::calculate_messages() {
bool fs_res = false;
- fs_res = file_parser.get_fs_api().file.open(
- &file, universal_db_filename, FSAM_READ, FSOM_OPEN_EXISTING);
+ furi_assert(!file_parser);
+
+ file_parser = std::make_unique<IrdaAppFileParser>();
+ fs_res = file_parser->open_irda_file_read(universal_db_filename);
if(!fs_res) {
- file_parser.get_sd_api().show_error(file_parser.get_sd_api().context, "Can't open file");
+ file_parser.reset(nullptr);
return false;
}
- file_parser.reset();
while(1) {
- auto message = file_parser.read_signal(&file);
- if(!message) break;
- auto element = records.find(message->name);
+ auto file_signal = file_parser->read_signal();
+ if(!file_signal) break;
+
+ auto element = records.find(file_signal->name);
if(element != records.cend()) {
++element->second.amount;
}
}
- file_parser.get_fs_api().file.close(&file);
+ file_parser->close();
+ file_parser.reset(nullptr);
return true;
}
void IrdaAppBruteForce::stop_bruteforce() {
+ furi_assert((current_record.size()));
+
if(current_record.size()) {
- file_parser.get_fs_api().file.close(&file);
+ furi_assert(file_parser);
current_record.clear();
+ file_parser->close();
+ file_parser.reset(nullptr);
}
}
// TODO: [FL-1418] replace with timer-chained consequence of messages.
bool IrdaAppBruteForce::send_next_bruteforce(void) {
furi_assert(current_record.size());
+ furi_assert(file_parser);
std::unique_ptr<IrdaAppFileParser::IrdaFileSignal> file_signal;
do {
- file_signal = file_parser.read_signal(&file);
+ file_signal = file_parser->read_signal();
} while(file_signal && current_record.compare(file_signal->name));
if(file_signal) {
@@ -53,25 +65,26 @@ bool IrdaAppBruteForce::send_next_bruteforce(void) {
}
bool IrdaAppBruteForce::start_bruteforce(int index, int& record_amount) {
- file_parser.reset();
+ bool result = false;
+ record_amount = 0;
+
for(const auto& it : records) {
if(it.second.index == index) {
record_amount = it.second.amount;
- current_record = it.first;
+ if(record_amount) {
+ current_record = it.first;
+ }
break;
}
}
if(record_amount) {
- bool fs_res = file_parser.get_fs_api().file.open(
- &file, universal_db_filename, FSAM_READ, FSOM_OPEN_EXISTING);
- if(fs_res) {
- return true;
- } else {
- file_parser.get_sd_api().show_error(
- file_parser.get_sd_api().context, "Can't open file");
+ file_parser = std::make_unique<IrdaAppFileParser>();
+ result = file_parser->open_irda_file_read(universal_db_filename);
+ if(!result) {
+ (void)file_parser.reset(nullptr);
}
}
- return false;
+ return result;
}
diff --git a/applications/irda/irda-app-brute-force.hpp b/applications/irda/irda-app-brute-force.hpp
index 62b8f34e..a7794301 100644
--- a/applications/irda/irda-app-brute-force.hpp
+++ b/applications/irda/irda-app-brute-force.hpp
@@ -2,13 +2,13 @@
#include "furi/check.h"
#include <unordered_map>
#include "irda-app-file-parser.hpp"
-
+#include <memory>
class IrdaAppBruteForce {
const char* universal_db_filename;
- IrdaAppFileParser file_parser;
File file;
std::string current_record;
+ std::unique_ptr<IrdaAppFileParser> file_parser;
typedef struct {
int index;
@@ -30,8 +30,6 @@ public:
void add_record(int index, const char* name);
IrdaAppBruteForce(const char* filename) : universal_db_filename (filename) {}
- ~IrdaAppBruteForce() {
- stop_bruteforce();
- }
+ ~IrdaAppBruteForce() {}
};
diff --git a/applications/irda/irda-app-event.hpp b/applications/irda/irda-app-event.hpp
index fd0df16c..eb4848fa 100644
--- a/applications/irda/irda-app-event.hpp
+++ b/applications/irda/irda-app-event.hpp
@@ -15,7 +15,6 @@ public:
TextEditDone,
PopupTimer,
ButtonPanelPressed,
- ButtonPanelPopupBackPressed,
};
union {
diff --git a/applications/irda/irda-app-file-parser.cpp b/applications/irda/irda-app-file-parser.cpp
index e0e274e5..288100ae 100644
--- a/applications/irda/irda-app-file-parser.cpp
+++ b/applications/irda/irda-app-file-parser.cpp
@@ -1,70 +1,139 @@
#include "irda-app-file-parser.hpp"
+#include "furi/check.h"
#include "irda-app-remote-manager.hpp"
#include "irda-app-signal.h"
+#include "m-string.h"
+#include <text-store.h>
#include <irda.h>
#include <cstdio>
#include <stdint.h>
+#include <string>
#include <string_view>
#include <furi.h>
+#include <file-worker-cpp.h>
uint32_t const IrdaAppFileParser::max_line_length = ((9 + 1) * 512 + 100);
+const char* IrdaAppFileParser::irda_directory = "/irda";
+const char* IrdaAppFileParser::irda_extension = ".ir";
+uint32_t const IrdaAppFileParser::max_raw_timings_in_signal = 512;
-std::unique_ptr<IrdaAppFileParser::IrdaFileSignal> IrdaAppFileParser::read_signal(File* file) {
- while(1) {
- auto str = getline(file);
- if(str.empty()) return nullptr;
+bool IrdaAppFileParser::open_irda_file_read(const char* name) {
+ std::string full_filename;
+ if(name[0] != '/')
+ full_filename = make_full_name(name);
+ else
+ full_filename = name;
- auto message = parse_signal(str);
- if(!message.get()) {
- message = parse_signal_raw(str);
- }
- if(message) return message;
+ return file_worker.open(full_filename.c_str(), FSAM_READ, FSOM_OPEN_EXISTING);
+}
+
+bool IrdaAppFileParser::open_irda_file_write(const char* name) {
+ std::string dirname(irda_directory);
+ auto full_filename = make_full_name(name);
+
+ if(!file_worker.mkdir(dirname.c_str())) return false;
+
+ return file_worker.open(full_filename.c_str(), FSAM_WRITE, FSOM_CREATE_ALWAYS);
+}
+
+size_t IrdaAppFileParser::stringify_message(
+ const IrdaAppSignal& signal,
+ const char* name,
+ char* buf,
+ size_t buf_size) {
+ auto message = signal.get_message();
+ auto protocol = message.protocol;
+ size_t written = 0;
+
+ written += sniprintf(
+ buf,
+ buf_size,
+ "%.31s %.31s A:%0*lX C:%0*lX\n",
+ name,
+ irda_get_protocol_name(protocol),
+ irda_get_protocol_address_length(protocol),
+ message.address,
+ irda_get_protocol_command_length(protocol),
+ message.command);
+
+ furi_assert(written < buf_size);
+ if(written >= buf_size) {
+ written = 0;
}
+
+ return written;
}
-bool IrdaAppFileParser::store_signal(File* file, const IrdaAppSignal& signal, const char* name) {
- char* content = new char[max_line_length];
+size_t IrdaAppFileParser::stringify_raw_signal(
+ const IrdaAppSignal& signal,
+ const char* name,
+ char* buf,
+ size_t buf_size) {
size_t written = 0;
+ int duty_cycle = 100 * IRDA_COMMON_DUTY_CYCLE;
+ written += sniprintf(
+ &buf[written],
+ max_line_length - written,
+ "%.31s RAW F:%d DC:%d",
+ name,
+ IRDA_COMMON_CARRIER_FREQUENCY,
+ duty_cycle);
- if(!signal.is_raw()) {
- auto message = signal.get_message();
- auto protocol = message.protocol;
-
- sniprintf(
- content,
- max_line_length,
- "%.31s %.31s A:%0*lX C:%0*lX\n",
- name,
- irda_get_protocol_name(protocol),
- irda_get_protocol_address_length(protocol),
- message.address,
- irda_get_protocol_command_length(protocol),
- message.command);
- written = strlen(content);
+ auto& raw_signal = signal.get_raw_signal();
+ for(size_t i = 0; i < raw_signal.timings_cnt; ++i) {
+ written += sniprintf(&buf[written], buf_size - written, " %ld", raw_signal.timings[i]);
+ if(written > buf_size) {
+ return false;
+ }
+ }
+ written += snprintf(&buf[written], buf_size - written, "\n");
+
+ furi_assert(written < buf_size);
+ if(written >= buf_size) {
+ written = 0;
+ }
+
+ return written;
+}
+
+bool IrdaAppFileParser::save_signal(const IrdaAppSignal& signal, const char* name) {
+ char* buf = new char[max_line_length];
+ size_t buf_cnt = 0;
+ bool write_result = false;
+
+ if(signal.is_raw()) {
+ buf_cnt = stringify_raw_signal(signal, name, buf, max_line_length);
} else {
- int duty_cycle = 100 * IRDA_COMMON_DUTY_CYCLE;
- written += sniprintf(
- &content[written],
- max_line_length - written,
- "%.31s RAW F:%d DC:%d",
- name,
- IRDA_COMMON_CARRIER_FREQUENCY,
- duty_cycle);
-
- auto& raw_signal = signal.get_raw_signal();
- for(size_t i = 0; i < raw_signal.timings_cnt; ++i) {
- written += sniprintf(
- &content[written], max_line_length - written, " %ld", raw_signal.timings[i]);
- furi_assert(written <= max_line_length);
+ buf_cnt = stringify_message(signal, name, buf, max_line_length);
+ }
+
+ if(buf_cnt) {
+ write_result = file_worker.write(buf, buf_cnt);
+ }
+ delete[] buf;
+ return write_result;
+}
+
+std::unique_ptr<IrdaAppFileParser::IrdaFileSignal> IrdaAppFileParser::read_signal(void) {
+ string_t line;
+ string_init(line);
+ string_reserve(line, max_line_length);
+ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal> file_signal;
+
+ while(!file_signal &&
+ file_worker.read_until_buffered(line, file_buf, &file_buf_cnt, sizeof(file_buf))) {
+ if(string_empty_p(line)) {
+ continue;
+ }
+ auto c_str = string_get_cstr(line);
+ file_signal = parse_signal(c_str);
+ if(!file_signal) {
+ file_signal = parse_signal_raw(c_str);
}
- written += snprintf(&content[written], max_line_length - written, "\n");
}
- furi_assert(written < max_line_length);
+ string_clear(line);
- size_t write_count = 0;
- write_count = get_fs_api().file.write(file, content, written);
- delete[] content;
- return (file->error_id == FSE_OK) && (write_count == written);
+ return file_signal;
}
std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
@@ -128,7 +197,6 @@ const char* find_first_not_of(const char* str, char symbol) {
std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
IrdaAppFileParser::parse_signal_raw(const std::string& string) const {
- char protocol_name[32];
uint32_t frequency;
uint32_t duty_cycle;
int str_len = string.size();
@@ -136,14 +204,10 @@ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
auto irda_file_signal = std::make_unique<IrdaFileSignal>();
int parsed = std::sscanf(
- str.data(),
- "%31s %31s F:%ld DC:%ld",
- irda_file_signal->name,
- protocol_name,
- &frequency,
- &duty_cycle);
+ str.data(), "%31s RAW F:%ld DC:%ld", irda_file_signal->name, &frequency, &duty_cycle);
- if(parsed != 4) {
+ if((parsed != 3) || (frequency > 42000) || (frequency < 32000) || (duty_cycle == 0) ||
+ (duty_cycle >= 100)) {
return nullptr;
}
@@ -152,9 +216,8 @@ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
header_len = sniprintf(
dummy,
sizeof(dummy),
- "%.31s %.31s F:%ld DC:%ld",
+ "%.31s RAW F:%ld DC:%ld",
irda_file_signal->name,
- protocol_name,
frequency,
duty_cycle);
@@ -162,39 +225,94 @@ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
str.remove_prefix(header_len);
/* move allocated timings into raw signal object */
- IrdaAppSignal::RawSignal raw_signal = {.timings_cnt = 0, .timings = new uint32_t[500]};
+ IrdaAppSignal::RawSignal raw_signal = {
+ .timings_cnt = 0, .timings = new uint32_t[max_raw_timings_in_signal]};
bool result = false;
while(!str.empty()) {
char buf[10];
size_t index = str.find_first_not_of(' ', 1);
if(index == std::string_view::npos) {
- result = true;
break;
}
str.remove_prefix(index);
parsed = std::sscanf(str.data(), "%9s", buf);
if(parsed != 1) {
+ result = false;
+ furi_assert(0);
break;
}
str.remove_prefix(strlen(buf));
int value = atoi(buf);
if(value <= 0) {
+ result = false;
+ furi_assert(0);
break;
}
raw_signal.timings[raw_signal.timings_cnt] = value;
++raw_signal.timings_cnt;
- if(raw_signal.timings_cnt >= 500) {
+ result = true;
+ if(raw_signal.timings_cnt >= max_raw_timings_in_signal) {
+ result = false;
+ furi_assert(0);
break;
}
}
if(result) {
- irda_file_signal->signal.set_raw_signal(raw_signal.timings, raw_signal.timings_cnt);
+ /* copy timings instead of moving them to occupy less than max_raw_timings_in_signal */
+ irda_file_signal->signal.copy_raw_signal(raw_signal.timings, raw_signal.timings_cnt);
} else {
(void)irda_file_signal.release();
- delete[] raw_signal.timings;
}
+ delete[] raw_signal.timings;
return irda_file_signal;
}
+
+bool IrdaAppFileParser::is_irda_file_exist(const char* name, bool* exist) {
+ std::string full_path = make_full_name(name);
+ return file_worker.is_file_exist(full_path.c_str(), exist);
+}
+
+std::string IrdaAppFileParser::make_full_name(const std::string& remote_name) const {
+ return std::string("") + irda_directory + "/" + remote_name + irda_extension;
+}
+
+std::string IrdaAppFileParser::make_name(const std::string& full_name) const {
+ std::string str(full_name, full_name.find_last_of('/') + 1, full_name.size());
+ str.erase(str.find_last_of('.'));
+
+ return str;
+}
+
+bool IrdaAppFileParser::remove_irda_file(const char* name) {
+ std::string full_filename = make_full_name(name);
+ return file_worker.remove(full_filename.c_str());
+}
+
+bool IrdaAppFileParser::rename_irda_file(const char* old_name, const char* new_name) {
+ std::string old_filename = make_full_name(old_name);
+ std::string new_filename = make_full_name(new_name);
+ return file_worker.rename(old_filename.c_str(), new_filename.c_str());
+}
+
+bool IrdaAppFileParser::close() {
+ return file_worker.close();
+}
+
+bool IrdaAppFileParser::check_errors() {
+ return file_worker.check_errors();
+}
+
+std::string IrdaAppFileParser::file_select(const char* selected) {
+ TextStore* filename_ts = new TextStore(128);
+ bool result;
+
+ result = file_worker.file_select(
+ irda_directory, irda_extension, filename_ts->text, filename_ts->text_size, selected);
+
+ delete filename_ts;
+
+ return result ? std::string(filename_ts->text) : std::string();
+}
diff --git a/applications/irda/irda-app-file-parser.hpp b/applications/irda/irda-app-file-parser.hpp
index 86a69a72..1195f8c3 100644
--- a/applications/irda/irda-app-file-parser.hpp
+++ b/applications/irda/irda-app-file-parser.hpp
@@ -1,26 +1,44 @@
#pragma once
#include <file_reader/file_reader.h>
#include <irda.h>
-#include "irda-app-remote-manager.hpp"
+#include <file-worker-cpp.h>
+#include "irda-app-signal.h"
-class IrdaAppFileParser : public FileReader {
+class IrdaAppFileParser {
public:
typedef struct {
char name[32];
IrdaAppSignal signal;
} IrdaFileSignal;
- IrdaAppFileParser() {
- /* Assume we can save max 512 samples */
- set_max_line_length(max_line_length);
- }
+ bool open_irda_file_read(const char* filename);
+ bool open_irda_file_write(const char* filename);
+ bool is_irda_file_exist(const char* filename, bool* exist);
+ bool rename_irda_file(const char* filename, const char* newname);
+ bool remove_irda_file(const char* name);
+ bool close();
+ bool check_errors();
- std::unique_ptr<IrdaAppFileParser::IrdaFileSignal> read_signal(File* file);
- bool store_signal(File* file, const IrdaAppSignal& signal, const char* name);
+ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal> read_signal();
+ bool save_signal(const IrdaAppSignal& signal, const char* name);
+ std::string file_select(const char* selected);
+
+ std::string make_name(const std::string& full_name) const;
private:
- static const uint32_t max_line_length;
+ size_t stringify_message(const IrdaAppSignal& signal, const char* name, char* content, size_t content_len);
+ size_t stringify_raw_signal(const IrdaAppSignal& signal, const char* name, char* content, size_t content_len);
std::unique_ptr<IrdaFileSignal> parse_signal(const std::string& str) const;
std::unique_ptr<IrdaFileSignal> parse_signal_raw(const std::string& str) const;
+ std::string make_full_name(const std::string& name) const;
+
+ static const char* irda_directory;
+ static const char* irda_extension;
+ static const uint32_t max_line_length;
+ static uint32_t const max_raw_timings_in_signal;
+
+ FileWorkerCpp file_worker;
+ char file_buf[128];
+ size_t file_buf_cnt = 0;
};
diff --git a/applications/irda/irda-app-remote-manager.cpp b/applications/irda/irda-app-remote-manager.cpp
index aedd39ef..3536b074 100644
--- a/applications/irda/irda-app-remote-manager.cpp
+++ b/applications/irda/irda-app-remote-manager.cpp
@@ -5,32 +5,29 @@
#include "gui/modules/button_menu.h"
#include "irda.h"
#include <cstdio>
+#include <stdint.h>
#include <string>
#include <utility>
#include "irda-app-file-parser.hpp"
-const char* IrdaAppRemoteManager::irda_directory = "irda";
-const char* IrdaAppRemoteManager::irda_extension = ".ir";
static const std::string default_remote_name = "remote";
-static bool find_string(const std::vector<std::string>& strings, const std::string& match_string) {
- for(const auto& string : strings) {
- if(!string.compare(match_string)) return true;
- }
- return false;
-}
+std::string IrdaAppRemoteManager::find_vacant_remote_name(const std::string& name) {
+ IrdaAppFileParser file_parser;
+ bool exist = true;
-static std::string
- find_vacant_name(const std::vector<std::string>& strings, const std::string& name) {
- // if suggested name is occupied, try another one (name2, name3, etc)
- if(find_string(strings, name)) {
- int i = 1;
- while(find_string(strings, name + std::to_string(++i)))
- ;
- return name + std::to_string(i);
- } else {
+ if(!file_parser.is_irda_file_exist(name.c_str(), &exist)) {
+ return std::string();
+ } else if(!exist) {
return name;
}
+
+ uint32_t i = 1;
+ /* if suggested name is occupied, try another one (name2, name3, etc) */
+ while(file_parser.is_irda_file_exist((name + std::to_string(++i)).c_str(), &exist) && exist)
+ ;
+
+ return !exist ? name + std::to_string(i) : std::string();
}
bool IrdaAppRemoteManager::add_button(const char* button_name, const IrdaAppSignal& signal) {
@@ -43,11 +40,10 @@ bool IrdaAppRemoteManager::add_remote_with_button(
const IrdaAppSignal& signal) {
furi_check(button_name != nullptr);
- std::vector<std::string> remote_list;
- bool result = get_remote_list(remote_list);
- if(!result) return false;
-
- auto new_name = find_vacant_name(remote_list, default_remote_name);
+ auto new_name = find_vacant_remote_name(default_remote_name);
+ if(new_name.empty()) {
+ return false;
+ }
remote = std::make_unique<IrdaAppRemote>(new_name);
return add_button(button_name, signal);
@@ -73,29 +69,17 @@ const IrdaAppSignal& IrdaAppRemoteManager::get_button_data(size_t index) const {
return buttons.at(index).signal;
}
-std::string IrdaAppRemoteManager::make_full_name(const std::string& remote_name) const {
- return std::string("/") + irda_directory + "/" + remote_name + irda_extension;
-}
-
-std::string IrdaAppRemoteManager::make_remote_name(const std::string& full_name) const {
- std::string str(full_name, full_name.find_last_of('/') + 1, full_name.size());
- str.erase(str.find_last_of('.'));
-
- return str;
-}
-
bool IrdaAppRemoteManager::delete_remote() {
- FS_Error fs_res;
+ bool result;
IrdaAppFileParser file_parser;
- fs_res = file_parser.get_fs_api().common.remove(make_full_name(remote->name).c_str());
- if(fs_res != FSE_OK) {
- file_parser.get_sd_api().show_error(
- file_parser.get_sd_api().context, "Error deleting file");
- return false;
- }
+ result = file_parser.remove_irda_file(remote->name.c_str());
+ reset_remote();
+ return result;
+}
+
+void IrdaAppRemoteManager::reset_remote() {
remote.reset();
- return true;
}
bool IrdaAppRemoteManager::delete_button(uint32_t index) {
@@ -111,12 +95,11 @@ std::string IrdaAppRemoteManager::get_button_name(uint32_t index) {
furi_check(remote.get() != nullptr);
auto& buttons = remote->buttons;
furi_check(index < buttons.size());
- return buttons[index].name;
+ return buttons[index].name.c_str();
}
std::string IrdaAppRemoteManager::get_remote_name() {
- furi_check(remote.get() != nullptr);
- return remote->name;
+ return remote ? remote->name : std::string();
}
int IrdaAppRemoteManager::find_remote_name(const std::vector<std::string>& strings) {
@@ -134,22 +117,21 @@ bool IrdaAppRemoteManager::rename_remote(const char* str) {
furi_check(str != nullptr);
furi_check(remote.get() != nullptr);
- if(!remote->name.compare(str)) return true;
+ if(!remote->name.compare(str)) {
+ return true;
+ }
- std::vector<std::string> remote_list;
- bool result = get_remote_list(remote_list);
- if(!result) return false;
+ auto new_name = find_vacant_remote_name(str);
+ if(new_name.empty()) {
+ return false;
+ }
- auto new_name = find_vacant_name(remote_list, str);
IrdaAppFileParser file_parser;
- FS_Error fs_err = file_parser.get_fs_api().common.rename(
- make_full_name(remote->name).c_str(), make_full_name(new_name).c_str());
+ bool result = file_parser.rename_irda_file(remote->name.c_str(), new_name.c_str());
+
remote->name = new_name;
- if(fs_err != FSE_OK) {
- file_parser.get_sd_api().show_error(
- file_parser.get_sd_api().context, "Error renaming\nremote file");
- }
- return fs_err == FSE_OK;
+
+ return result;
}
bool IrdaAppRemoteManager::rename_button(uint32_t index, const char* str) {
@@ -167,115 +149,45 @@ size_t IrdaAppRemoteManager::get_number_of_buttons() {
}
bool IrdaAppRemoteManager::store(void) {
- File file;
- std::string dirname(std::string("/") + irda_directory);
-
IrdaAppFileParser file_parser;
- FS_Error fs_err = file_parser.get_fs_api().common.mkdir(dirname.c_str());
- if((fs_err != FSE_OK) && (fs_err != FSE_EXIST)) {
- file_parser.get_sd_api().show_error(
- file_parser.get_sd_api().context, "Can't create directory");
- return false;
- }
-
- bool res = file_parser.get_fs_api().file.open(
- &file, make_full_name(remote->name).c_str(), FSAM_WRITE, FSOM_CREATE_ALWAYS);
+ bool result = true;
- if(!res) {
- file_parser.get_sd_api().show_error(
- file_parser.get_sd_api().context, "Cannot create\nnew remote file");
+ if(!file_parser.open_irda_file_write(remote->name.c_str())) {
return false;
}
for(const auto& button : remote->buttons) {
- bool result = file_parser.store_signal(&file, button.signal, button.name.c_str());
+ bool result = file_parser.save_signal(button.signal, button.name.c_str());
if(!result) {
- file_parser.get_sd_api().show_error(
- file_parser.get_sd_api().context, "Cannot write\nto key file");
- file_parser.get_fs_api().file.close(&file);
- return false;
- }
- }
-
- file_parser.get_fs_api().file.close(&file);
- file_parser.get_sd_api().check_error(file_parser.get_sd_api().context);
-
- return true;
-}
-
-bool IrdaAppRemoteManager::get_remote_list(std::vector<std::string>& remote_names) const {
- bool fs_res = false;
- char name[128];
- File dir;
- std::string dirname(std::string("/") + irda_directory);
- remote_names.clear();
-
- IrdaAppFileParser file_parser;
- fs_res = file_parser.get_fs_api().dir.open(&dir, dirname.c_str());
- if(!fs_res) {
- if(!check_fs()) {
- file_parser.get_sd_api().show_error(
- file_parser.get_sd_api().context, "Cannot open\napplication directory");
- return false;
- } else {
- return true; // SD ok, but no files written yet
+ result = false;
+ break;
}
}
- while(file_parser.get_fs_api().dir.read(&dir, nullptr, name, sizeof(name)) && strlen(name)) {
- std::string filename(name);
- auto extension_index = filename.rfind(irda_extension);
- if((extension_index == std::string::npos) ||
- (extension_index + strlen(irda_extension) != filename.size())) {
- continue;
- }
- remote_names.push_back(filename.erase(extension_index));
- }
- file_parser.get_fs_api().dir.close(&dir);
+ file_parser.close();
- return true;
+ return result;
}
-bool IrdaAppRemoteManager::load(const std::string& name_arg, bool fullpath) {
+bool IrdaAppRemoteManager::load(const std::string& name) {
bool fs_res = false;
IrdaAppFileParser file_parser;
- File file;
- std::string full_filename;
- std::string remote_name;
-
- if(fullpath) {
- full_filename = name_arg;
- remote_name = make_remote_name(name_arg);
- } else {
- full_filename = make_full_name(name_arg);
- remote_name = name_arg;
- }
- fs_res = file_parser.get_fs_api().file.open(
- &file, full_filename.c_str(), FSAM_READ, FSOM_OPEN_EXISTING);
+ fs_res = file_parser.open_irda_file_read(name.c_str());
if(!fs_res) {
- file_parser.get_sd_api().show_error(
- file_parser.get_sd_api().context, "Error opening file");
return false;
}
- remote = std::make_unique<IrdaAppRemote>(remote_name);
+ remote = std::make_unique<IrdaAppRemote>(name);
while(1) {
- auto file_signal = file_parser.read_signal(&file);
- if(!file_signal.get()) break;
+ auto file_signal = file_parser.read_signal();
+ if(!file_signal) {
+ break;
+ }
remote->buttons.emplace_back(file_signal->name, file_signal->signal);
}
- file_parser.get_fs_api().file.close(&file);
+ file_parser.close();
return true;
}
-
-bool IrdaAppRemoteManager::check_fs() const {
- // TODO: [FL-1431] Add return value to file_parser.get_sd_api().check_error() and replace get_fs_info().
- IrdaAppFileParser file_parser;
- auto fs_err = file_parser.get_fs_api().common.get_fs_info(nullptr, nullptr);
- if(fs_err != FSE_OK)
- file_parser.get_sd_api().show_error(file_parser.get_sd_api().context, "SD card not found");
- return fs_err == FSE_OK;
-}
diff --git a/applications/irda/irda-app-remote-manager.hpp b/applications/irda/irda-app-remote-manager.hpp
index dd193074..1d835ca7 100644
--- a/applications/irda/irda-app-remote-manager.hpp
+++ b/applications/irda/irda-app-remote-manager.hpp
@@ -9,7 +9,6 @@
#include <filesystem-api.h>
#include "irda-app-signal.h"
-
class IrdaAppRemoteButton {
friend class IrdaAppRemoteManager;
std::string name;
@@ -49,8 +48,8 @@ public:
int find_remote_name(const std::vector<std::string>& strings);
bool rename_button(uint32_t index, const char* str);
bool rename_remote(const char* str);
+ std::string find_vacant_remote_name(const std::string& name);
- bool get_remote_list(std::vector<std::string>& remote_names) const;
std::vector<std::string> get_button_list() const;
std::string get_button_name(uint32_t index);
std::string get_remote_name();
@@ -58,9 +57,9 @@ public:
const IrdaAppSignal& get_button_data(size_t index) const;
bool delete_button(uint32_t index);
bool delete_remote();
+ void reset_remote();
bool store();
- bool load(const std::string& name, bool fullpath = false);
- bool check_fs() const;
+ bool load(const std::string& name);
};
diff --git a/applications/irda/irda-app-view-manager.cpp b/applications/irda/irda-app-view-manager.cpp
index 822b66ab..cc2371f7 100644
--- a/applications/irda/irda-app-view-manager.cpp
+++ b/applications/irda/irda-app-view-manager.cpp
@@ -1,6 +1,7 @@
#include "furi.h"
#include "gui/modules/button_panel.h"
#include "irda-app.hpp"
+#include "irda/irda-app-event.hpp"
#include <callback-connector.h>
IrdaAppViewManager::IrdaAppViewManager() {
@@ -98,6 +99,12 @@ osMessageQueueId_t IrdaAppViewManager::get_event_queue() {
return event_queue;
}
+void IrdaAppViewManager::clear_events() {
+ IrdaAppEvent event;
+ while(osMessageQueueGet(event_queue, &event, NULL, 0) == osOK)
+ ;
+}
+
void IrdaAppViewManager::receive_event(IrdaAppEvent* event) {
if(osMessageQueueGet(event_queue, event, NULL, 100) != osOK) {
event->type = IrdaAppEvent::Type::Tick;
diff --git a/applications/irda/irda-app-view-manager.hpp b/applications/irda/irda-app-view-manager.hpp
index 90511acd..4569a104 100644
--- a/applications/irda/irda-app-view-manager.hpp
+++ b/applications/irda/irda-app-view-manager.hpp
@@ -28,6 +28,7 @@ public:
void receive_event(IrdaAppEvent* event);
void send_event(IrdaAppEvent* event);
+ void clear_events();
DialogEx* get_dialog_ex();
Submenu* get_submenu();
diff --git a/applications/irda/irda-app.cpp b/applications/irda/irda-app.cpp
index 29e1d281..1e2de687 100644
--- a/applications/irda/irda-app.cpp
+++ b/applications/irda/irda-app.cpp
@@ -1,4 +1,5 @@
#include "irda-app.hpp"
+#include "irda/irda-app-file-parser.hpp"
#include <irda_worker.h>
#include <furi.h>
#include <gui/gui.h>
@@ -12,12 +13,16 @@ int32_t IrdaApp::run(void* args) {
bool exit = false;
if(args) {
- const char* remote_name = static_cast<const char*>(args);
- bool result = remote_manager.load(std::string(remote_name), true);
+ std::string remote_name;
+ {
+ IrdaAppFileParser file_parser;
+ remote_name = file_parser.make_name(static_cast<const char*>(args));
+ }
+ bool result = remote_manager.load(remote_name);
if(result) {
current_scene = IrdaApp::Scene::Remote;
} else {
- printf("Failed to load remote \'%s\'\r\n", remote_name);
+ printf("Failed to load remote \'%s\'\r\n", remote_name.c_str());
return -1;
}
}
@@ -65,6 +70,7 @@ void IrdaApp::switch_to_next_scene_without_saving(Scene next_scene) {
scenes[current_scene]->on_exit(this);
current_scene = next_scene;
scenes[current_scene]->on_enter(this);
+ view_manager.clear_events();
}
}
@@ -93,6 +99,7 @@ void IrdaApp::search_and_switch_to_previous_scene(const std::initializer_list<Sc
scenes[current_scene]->on_exit(this);
current_scene = previous_scene;
scenes[current_scene]->on_enter(this);
+ view_manager.clear_events();
}
}
@@ -106,6 +113,7 @@ bool IrdaApp::switch_to_previous_scene(uint8_t count) {
scenes[current_scene]->on_exit(this);
current_scene = previous_scene;
scenes[current_scene]->on_enter(this);
+ view_manager.clear_events();
return false;
}
diff --git a/applications/irda/irda-app.hpp b/applications/irda/irda-app.hpp
index 31637e7a..0562aefb 100644
--- a/applications/irda/irda-app.hpp
+++ b/applications/irda/irda-app.hpp
@@ -2,7 +2,7 @@
#include <map>
#include <irda.h>
#include <furi.h>
-#include "irda/scene/irda-app-scene.hpp"
+#include "scene/irda-app-scene.hpp"
#include "irda-app-event.hpp"
#include "scene/irda-app-scene.hpp"
#include "irda-app-view-manager.hpp"
@@ -34,7 +34,6 @@ public:
LearnSuccess,
LearnEnterName,
LearnDone,
- LearnDoneAfter,
Remote,
RemoteList,
Edit,
@@ -126,7 +125,6 @@ private:
{Scene::LearnSuccess, new IrdaAppSceneLearnSuccess()},
{Scene::LearnEnterName, new IrdaAppSceneLearnEnterName()},
{Scene::LearnDone, new IrdaAppSceneLearnDone()},
- {Scene::LearnDoneAfter, new IrdaAppSceneLearnDoneAfter()},
{Scene::Remote, new IrdaAppSceneRemote()},
{Scene::RemoteList, new IrdaAppSceneRemoteList()},
{Scene::Edit, new IrdaAppSceneEdit()},
diff --git a/applications/irda/scene/irda-app-scene-learn-done-after.cpp b/applications/irda/scene/irda-app-scene-learn-done-after.cpp
deleted file mode 100644
index b7ff57d6..00000000
--- a/applications/irda/scene/irda-app-scene-learn-done-after.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "../irda-app.hpp"
-#include <gui/modules/popup.h>
-
-void IrdaAppSceneLearnDoneAfter::on_enter(IrdaApp* app) {
- auto view_manager = app->get_view_manager();
- auto popup = view_manager->get_popup();
-
- popup_set_icon(popup, 0, 30, &I_IrdaSendShort_128x34);
- popup_set_text(
- popup, "Get ready!\nPoint flipper at target.", 64, 16, AlignCenter, AlignCenter);
-
- popup_set_callback(popup, IrdaApp::popup_callback);
- popup_set_context(popup, app);
- popup_set_timeout(popup, 1500);
- popup_enable_timeout(popup);
-
- view_manager->switch_to(IrdaAppViewManager::ViewType::Popup);
-}
-
-bool IrdaAppSceneLearnDoneAfter::on_event(IrdaApp* app, IrdaAppEvent* event) {
- bool consumed = false;
-
- if(event->type == IrdaAppEvent::Type::PopupTimer) {
- app->switch_to_next_scene(IrdaApp::Scene::Remote);
- consumed = true;
- }
-
- return consumed;
-}
-
-void IrdaAppSceneLearnDoneAfter::on_exit(IrdaApp* app) {
-}
diff --git a/applications/irda/scene/irda-app-scene-learn-done.cpp b/applications/irda/scene/irda-app-scene-learn-done.cpp
index f411af5d..a9bd2049 100644
--- a/applications/irda/scene/irda-app-scene-learn-done.cpp
+++ b/applications/irda/scene/irda-app-scene-learn-done.cpp
@@ -24,11 +24,7 @@ bool IrdaAppSceneLearnDone::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
if(event->type == IrdaAppEvent::Type::PopupTimer) {
- if(app->get_learn_new_remote()) {
- app->switch_to_next_scene(IrdaApp::Scene::LearnDoneAfter);
- } else {
- app->switch_to_next_scene(IrdaApp::Scene::Remote);
- }
+ app->switch_to_next_scene(IrdaApp::Scene::Remote);
consumed = true;
}
diff --git a/applications/irda/scene/irda-app-scene-learn-success.cpp b/applications/irda/scene/irda-app-scene-learn-success.cpp
index 74e8db74..4ade76df 100644
--- a/applications/irda/scene/irda-app-scene-learn-success.cpp
+++ b/applications/irda/scene/irda-app-scene-learn-success.cpp
@@ -1,5 +1,7 @@
#include "../irda-app.hpp"
#include "irda.h"
+#include "../irda-app-file-parser.hpp"
+#include <memory>
static void dialog_result_callback(DialogExResult result, void* context) {
auto app = static_cast<IrdaApp*>(context);
@@ -61,15 +63,18 @@ bool IrdaAppSceneLearnSuccess::on_event(IrdaApp* app, IrdaAppEvent* event) {
signal.transmit();
break;
}
- case DialogExResultRight:
- auto remote_manager = app->get_remote_manager();
- if(remote_manager->check_fs()) {
+ case DialogExResultRight: {
+ IrdaAppFileParser file_parser;
+ if(file_parser.check_errors()) {
app->switch_to_next_scene(IrdaApp::Scene::LearnEnterName);
} else {
app->switch_to_previous_scene();
}
break;
}
+ default:
+ break;
+ }
}
return consumed;
diff --git a/applications/irda/scene/irda-app-scene-remote-list.cpp b/applications/irda/scene/irda-app-scene-remote-list.cpp
index aacc537f..d2b56e48 100644
--- a/applications/irda/scene/irda-app-scene-remote-list.cpp
+++ b/applications/irda/scene/irda-app-scene-remote-list.cpp
@@ -1,75 +1,30 @@
#include "../irda-app.hpp"
-
-typedef enum {
- SubmenuIndexPlus = -1,
-} SubmenuIndex;
-
-static void submenu_callback(void* context, uint32_t index) {
- IrdaApp* app = static_cast<IrdaApp*>(context);
- IrdaAppEvent event;
-
- event.type = IrdaAppEvent::Type::MenuSelected;
- event.payload.menu_index = index;
-
- app->get_view_manager()->send_event(&event);
-}
+#include "irda/irda-app-event.hpp"
void IrdaAppSceneRemoteList::on_enter(IrdaApp* app) {
- IrdaAppViewManager* view_manager = app->get_view_manager();
- Submenu* submenu = view_manager->get_submenu();
+ IrdaAppFileParser file_parser;
+ bool success = false;
auto remote_manager = app->get_remote_manager();
- int i = 0;
-
- bool result = remote_manager->get_remote_list(remote_names);
- if(!result) {
- app->switch_to_previous_scene();
- return;
- }
-
- for(auto& name : remote_names) {
- submenu_add_item(submenu, name.c_str(), i++, submenu_callback, app);
+ auto last_selected_remote = remote_manager->get_remote_name();
+ auto selected_file = file_parser.file_select(
+ last_selected_remote.size() ? last_selected_remote.c_str() : nullptr);
+ if(!selected_file.empty()) {
+ if(remote_manager->load(selected_file)) {
+ app->switch_to_next_scene(IrdaApp::Scene::Remote);
+ success = true;
+ }
}
- submenu_add_item(
- submenu, " +", SubmenuIndexPlus, submenu_callback, app);
- if((SubmenuIndex)submenu_item_selected == SubmenuIndexPlus) {
- submenu_set_selected_item(submenu, submenu_item_selected);
- } else {
- int remote_index = remote_manager->find_remote_name(remote_names);
- submenu_set_selected_item(submenu, (remote_index >= 0) ? remote_index : 0);
+ if(!success) {
+ app->switch_to_previous_scene();
}
-
- submenu_item_selected = 0;
- view_manager->switch_to(IrdaAppViewManager::ViewType::Submenu);
}
bool IrdaAppSceneRemoteList::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
- if(event->type == IrdaAppEvent::Type::MenuSelected) {
- switch(event->payload.menu_index) {
- case SubmenuIndexPlus:
- app->set_learn_new_remote(true);
- app->switch_to_next_scene(IrdaApp::Scene::Learn);
- submenu_item_selected = event->payload.menu_index;
- break;
- default:
- auto remote_manager = app->get_remote_manager();
- bool result = remote_manager->load(remote_names.at(event->payload.menu_index));
- if(result) {
- app->switch_to_next_scene(IrdaApp::Scene::Remote);
- }
- consumed = true;
- break;
- }
- }
-
return consumed;
}
void IrdaAppSceneRemoteList::on_exit(IrdaApp* app) {
- IrdaAppViewManager* view_manager = app->get_view_manager();
- Submenu* submenu = view_manager->get_submenu();
-
- submenu_clean(submenu);
}
diff --git a/applications/irda/scene/irda-app-scene-start.cpp b/applications/irda/scene/irda-app-scene-start.cpp
index 27f40ad3..6d9e77f8 100644
--- a/applications/irda/scene/irda-app-scene-start.cpp
+++ b/applications/irda/scene/irda-app-scene-start.cpp
@@ -61,5 +61,6 @@ void IrdaAppSceneStart::on_exit(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
Submenu* submenu = view_manager->get_submenu();
+ app->get_remote_manager()->reset_remote();
submenu_clean(submenu);
}
diff --git a/applications/irda/scene/irda-app-scene-universal-common.cpp b/applications/irda/scene/irda-app-scene-universal-common.cpp
index 53c8a246..88e7cf34 100644
--- a/applications/irda/scene/irda-app-scene-universal-common.cpp
+++ b/applications/irda/scene/irda-app-scene-universal-common.cpp
@@ -28,7 +28,7 @@ static bool irda_popup_brut_input_callback(InputEvent* event, void* context) {
consumed = true;
IrdaAppEvent irda_event;
- irda_event.type = IrdaAppEvent::Type::ButtonPanelPopupBackPressed;
+ irda_event.type = IrdaAppEvent::Type::Back;
app->get_view_manager()->send_event(&irda_event);
}
@@ -58,8 +58,8 @@ void IrdaAppSceneUniversalCommon::progress_popup(IrdaApp* app) {
bool IrdaAppSceneUniversalCommon::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
- if(event->type == IrdaAppEvent::Type::Tick) {
- if(brute_force_started) {
+ if(brute_force_started) {
+ if(event->type == IrdaAppEvent::Type::Tick) {
auto view_manager = app->get_view_manager();
IrdaAppEvent tick_event = {.type = IrdaAppEvent::Type::Tick};
view_manager->send_event(&tick_event);
@@ -70,26 +70,27 @@ bool IrdaAppSceneUniversalCommon::on_event(IrdaApp* app, IrdaAppEvent* event) {
brute_force_started = false;
remove_popup(app);
}
+ consumed = true;
+ } else if(event->type == IrdaAppEvent::Type::Back) {
+ brute_force_started = false;
+ brute_force.stop_bruteforce();
+ remove_popup(app);
+ consumed = true;
}
- consumed = true;
- }
-
- if(event->type == IrdaAppEvent::Type::ButtonPanelPopupBackPressed) {
- consumed = true;
- brute_force_started = false;
- brute_force.stop_bruteforce();
- remove_popup(app);
- } else if(event->type == IrdaAppEvent::Type::ButtonPanelPressed) {
- int record_amount = 0;
- if(brute_force.start_bruteforce(event->payload.menu_index, record_amount)) {
- if(record_amount > 0) {
+ } else {
+ if(event->type == IrdaAppEvent::Type::ButtonPanelPressed) {
+ int record_amount = 0;
+ if(brute_force.start_bruteforce(event->payload.menu_index, record_amount)) {
brute_force_started = true;
show_popup(app, record_amount);
+ } else {
+ app->switch_to_previous_scene();
}
- } else {
+ consumed = true;
+ } else if(event->type == IrdaAppEvent::Type::Back) {
app->switch_to_previous_scene();
+ consumed = true;
}
- consumed = true;
}
return consumed;
diff --git a/applications/irda/scene/irda-app-scene.hpp b/applications/irda/scene/irda-app-scene.hpp
index 524c0671..a90f5f49 100644
--- a/applications/irda/scene/irda-app-scene.hpp
+++ b/applications/irda/scene/irda-app-scene.hpp
@@ -65,13 +65,6 @@ public:
void on_exit(IrdaApp* app) final;
};
-class IrdaAppSceneLearnDoneAfter : public IrdaAppScene {
-public:
- void on_enter(IrdaApp* app) final;
- bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
- void on_exit(IrdaApp* app) final;
-};
-
class IrdaAppSceneRemote : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
@@ -155,14 +148,14 @@ protected:
class IrdaAppSceneUniversalTV : public IrdaAppSceneUniversalCommon {
public:
void on_enter(IrdaApp* app) final;
- IrdaAppSceneUniversalTV() : IrdaAppSceneUniversalCommon("/irda/universal/tv.ir") {}
+ IrdaAppSceneUniversalTV() : IrdaAppSceneUniversalCommon("/assets/ext/irda/tv.ir") {}
~IrdaAppSceneUniversalTV() {}
};
class IrdaAppSceneUniversalAudio : public IrdaAppSceneUniversalCommon {
public:
void on_enter(IrdaApp* app) final;
- IrdaAppSceneUniversalAudio() : IrdaAppSceneUniversalCommon("/irda/universal/audio.ir") {}
+ IrdaAppSceneUniversalAudio() : IrdaAppSceneUniversalCommon("/assets/ext/irda/audio.ir") {}
~IrdaAppSceneUniversalAudio() {}
};