Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infrared: Add option to "Load from Library File" for Universal Remotes #255

Merged
merged 25 commits into from
Oct 12, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 53 additions & 13 deletions applications/main/infrared/infrared_brute_force.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include "infrared_signal.h"

#include <furi.h>

typedef struct {
uint32_t index;
uint32_t count;
Expand Down Expand Up @@ -60,32 +62,34 @@ InfraredErrorCode infrared_brute_force_calculate_messages(InfraredBruteForce* br
FuriString* signal_name = furi_string_alloc();
InfraredSignal* signal = infrared_signal_alloc();

do {
if(!flipper_format_buffered_file_open_existing(ff, brute_force->db_filename)) {
error = InfraredErrorCodeFileOperationFailed;
break;
}

bool signals_valid = false;
if(!flipper_format_buffered_file_open_existing(ff, brute_force->db_filename)) {
Willy-JL marked this conversation as resolved.
Show resolved Hide resolved
error = InfraredErrorCodeFileOperationFailed;
} else {
uint32_t total_signals = 0;
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;
if(INFRARED_ERROR_PRESENT(error) || !infrared_signal_is_valid(signal)) {
break;
}

InfraredBruteForceRecord* record =
InfraredBruteForceRecordDict_get(brute_force->records, signal_name);
if(record) { //-V547
++(record->count);

} else {
infrared_brute_force_add_record(
brute_force, total_signals, furi_string_get_cstr(signal_name));
}
total_signals++;
}
if(!signals_valid) break;
} while(false);
}

infrared_signal_free(signal);
furi_string_free(signal_name);

flipper_format_free(ff);
furi_record_close(RECORD_STORAGE);

return error;
}

Expand All @@ -94,10 +98,12 @@ bool infrared_brute_force_start(
uint32_t index,
uint32_t* record_count) {
furi_assert(!brute_force->is_started);

bool success = false;
*record_count = 0;

InfraredBruteForceRecordDict_it_t it;

for(InfraredBruteForceRecordDict_it(it, brute_force->records);
!InfraredBruteForceRecordDict_end_p(it);
InfraredBruteForceRecordDict_next(it)) {
Expand All @@ -114,12 +120,17 @@ bool infrared_brute_force_start(
if(*record_count) {
Storage* storage = furi_record_open(RECORD_STORAGE);
brute_force->ff = flipper_format_buffered_file_alloc(storage);

brute_force->current_signal = infrared_signal_alloc();

brute_force->is_started = true;

success =
flipper_format_buffered_file_open_existing(brute_force->ff, brute_force->db_filename);

if(!success) infrared_brute_force_stop(brute_force);
}

return success;
}

Expand Down Expand Up @@ -151,7 +162,6 @@ bool infrared_brute_force_send_next(InfraredBruteForce* brute_force) {
}
return success;
}

void infrared_brute_force_add_record(
InfraredBruteForce* brute_force,
uint32_t index,
Expand All @@ -160,10 +170,40 @@ void infrared_brute_force_add_record(
FuriString* key;
key = furi_string_alloc_set(name);
InfraredBruteForceRecordDict_set_at(brute_force->records, key, value);

furi_string_free(key);
}

void infrared_brute_force_reset(InfraredBruteForce* brute_force) {
furi_assert(!brute_force->is_started);
InfraredBruteForceRecordDict_reset(brute_force->records);
}

size_t infrared_brute_force_get_db_size(const InfraredBruteForce* brute_force) {
Willy-JL marked this conversation as resolved.
Show resolved Hide resolved
size_t size = InfraredBruteForceRecordDict_size(brute_force->records);
return size;
}

const char*
infrared_brute_force_get_button_name(const InfraredBruteForce* brute_force, size_t index) {
if(index >= infrared_brute_force_get_db_size(brute_force)) {
return NULL;
}

InfraredBruteForceRecordDict_it_t it;
size_t current_index = 0;

for(InfraredBruteForceRecordDict_it(it, brute_force->records);
!InfraredBruteForceRecordDict_end_p(it);
InfraredBruteForceRecordDict_next(it)) {
if(current_index == index) {
const char* button_name =
furi_string_get_cstr(InfraredBruteForceRecordDict_cref(it)->key);

return button_name;
}
current_index++;
}

return NULL; //just as fallback
}
20 changes: 20 additions & 0 deletions applications/main/infrared/infrared_brute_force.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "infrared_error_code.h"

/**
Expand Down Expand Up @@ -109,3 +110,22 @@ void infrared_brute_force_add_record(
* @param[in,out] brute_force pointer to the instance to be reset.
*/
void infrared_brute_force_reset(InfraredBruteForce* brute_force);

/**
* @brief Get the total number of unique button names in the database, for example,
* if a button name is "Power" and it appears 3 times in the db, then the
* db_size is 1, instead of 3.
*
* @param[in] brute_force pointer to the InfraredBruteForce instance.
* @return size_t number of unique button names.
*/
size_t infrared_brute_force_get_db_size(const InfraredBruteForce* brute_force);

/**
* @brief Get the button name at the specified index.
*
* @param[in] brute_force pointer to the InfraredBruteForce instance.
* @param[in] index index of the button name to retrieve.
* @return const char* button name, or NULL if index is out of range.
*/
const char* infrared_brute_force_get_button_name(const InfraredBruteForce* brute_force, size_t index);
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ void infrared_scene_universal_common_on_enter(void* context) {
infrared_blocking_task_start(infrared, infrared_scene_universal_common_task_callback);
}

void infrared_scene_universal_common_on_enter_more_devices(void* context) {
InfraredApp* infrared = context;
view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical);
view_stack_add_view(infrared->view_stack, button_menu_get_view(infrared->button_menu));

// Load universal remote data in background
infrared_blocking_task_start(infrared, infrared_scene_universal_common_task_callback);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack);
}

bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent event) {
InfraredApp* infrared = context;
SceneManager* scene_manager = infrared->scene_manager;
Expand Down Expand Up @@ -114,4 +124,4 @@ void infrared_scene_universal_common_on_exit(void* context) {
view_stack_remove_view(infrared->view_stack, button_panel_get_view(button_panel));
infrared_brute_force_reset(infrared->brute_force);
button_panel_reset(button_panel);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ ADD_SCENE(infrared, universal_audio, UniversalAudio)
ADD_SCENE(infrared, universal_led, UniversalLED)
ADD_SCENE(infrared, universal_ac, UniversalAC)
ADD_SCENE(infrared, universal_fan, UniversalFan)
ADD_SCENE(infrared, universal_more_devices, UniversalMoreDevices)
ADD_SCENE(infrared, gpio_settings, GpioSettings)
ADD_SCENE(infrared, debug, Debug)
ADD_SCENE(infrared, error_databases, ErrorDatabases)
Expand Down
12 changes: 12 additions & 0 deletions applications/main/infrared/scenes/infrared_scene_universal.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ typedef enum {
SubmenuIndexUniversalMonitor,
SubmenuIndexUniversalDigitalSign,
SubmenuIndexUniversalLED,
SubmenuIndexUniversalMoreDevices,
} SubmenuIndex;

static void infrared_scene_universal_submenu_callback(void* context, uint32_t index) {
Expand Down Expand Up @@ -76,6 +77,13 @@ void infrared_scene_universal_on_enter(void* context) {
infrared_scene_universal_submenu_callback,
context);

submenu_add_item(
submenu,
"More Devices",
zxkmm marked this conversation as resolved.
Show resolved Hide resolved
SubmenuIndexUniversalMoreDevices,
infrared_scene_universal_submenu_callback,
context);

submenu_set_selected_item(
submenu, scene_manager_get_scene_state(infrared->scene_manager, InfraredSceneUniversal));

Expand Down Expand Up @@ -112,6 +120,10 @@ bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) {
} else if(event.event == SubmenuIndexUniversalLED) {
scene_manager_next_scene(scene_manager, InfraredSceneUniversalLED);
consumed = true;
} else if(event.event == SubmenuIndexUniversalMoreDevices) {
furi_string_set(infrared->file_path, INFRARED_APP_FOLDER);
scene_manager_next_scene(scene_manager, InfraredSceneUniversalMoreDevices);
consumed = true;
}
scene_manager_set_scene_state(scene_manager, InfraredSceneUniversal, event.event);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ void infrared_scene_universal_led_on_enter(void* context) {
InfraredBruteForce* brute_force = infrared->brute_force;

infrared_brute_force_set_db_filename(brute_force, EXT_PATH("infrared/assets/led.ir"));

button_panel_reserve(button_panel, 2, 2);
uint32_t i = 0;
button_panel_add_item(
Expand Down
Loading