[FL-3949] Universal IR signal selection (#4085)

* feat: universal ir signal selection
* fix: f18, format specifiers
* update labels with suggestions from the ui team

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
Anna Antonenko
2025-02-20 03:58:55 +04:00
committed by GitHub
parent 93b0277938
commit 0f240c4dbc
17 changed files with 376 additions and 108 deletions

View File

@@ -2,15 +2,28 @@
#include <dolphin/dolphin.h>
#pragma pack(push, 1)
typedef union {
uint32_t packed_value;
struct {
bool is_paused;
uint8_t padding;
uint16_t signal_index;
};
} InfraredSceneState;
#pragma pack(pop)
void infrared_scene_universal_common_item_callback(void* context, uint32_t index) {
InfraredApp* infrared = context;
uint32_t event = infrared_custom_event_pack(InfraredCustomEventTypeButtonSelected, index);
view_dispatcher_send_custom_event(infrared->view_dispatcher, event);
}
static void infrared_scene_universal_common_progress_back_callback(void* context) {
static void infrared_scene_universal_common_progress_input_callback(
void* context,
InfraredProgressViewInput input) {
InfraredApp* infrared = context;
uint32_t event = infrared_custom_event_pack(InfraredCustomEventTypeBackPressed, -1);
uint32_t event = infrared_custom_event_pack(InfraredCustomEventTypePopupInput, input);
view_dispatcher_send_custom_event(infrared->view_dispatcher, event);
}
@@ -19,8 +32,8 @@ static void
ViewStack* view_stack = infrared->view_stack;
InfraredProgressView* progress = infrared->progress;
infrared_progress_view_set_progress_total(progress, record_count);
infrared_progress_view_set_back_callback(
progress, infrared_scene_universal_common_progress_back_callback, infrared);
infrared_progress_view_set_input_callback(
progress, infrared_scene_universal_common_progress_input_callback, infrared);
view_stack_add_view(view_stack, infrared_progress_view_get_view(progress));
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
}
@@ -51,29 +64,111 @@ void infrared_scene_universal_common_on_enter(void* context) {
infrared_blocking_task_start(infrared, infrared_scene_universal_common_task_callback);
}
static void infrared_scene_universal_common_handle_popup_input(
InfraredApp* infrared,
InfraredProgressViewInput input) {
InfraredBruteForce* brute_force = infrared->brute_force;
SceneManager* scene_manager = infrared->scene_manager;
uint32_t scene_id = scene_manager_get_current_scene(infrared->scene_manager);
switch(input) {
case InfraredProgressViewInputStop: {
infrared_brute_force_stop(brute_force);
infrared_scene_universal_common_hide_popup(infrared);
break;
}
case InfraredProgressViewInputPause: {
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
infrared_progress_view_set_paused(infrared->progress, true);
InfraredSceneState scene_state = {
.packed_value = scene_manager_get_scene_state(scene_manager, scene_id)};
scene_state.is_paused = true;
if(scene_state.signal_index)
scene_state.signal_index--; // when running, the state stores the next index
scene_manager_set_scene_state(scene_manager, scene_id, scene_state.packed_value);
break;
}
case InfraredProgressViewInputResume: {
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
infrared_progress_view_set_paused(infrared->progress, false);
InfraredSceneState scene_state = {
.packed_value = scene_manager_get_scene_state(scene_manager, scene_id)};
scene_state.is_paused = false;
scene_manager_set_scene_state(scene_manager, scene_id, scene_state.packed_value);
break;
}
case InfraredProgressViewInputNextSignal: {
InfraredSceneState scene_state = {
.packed_value = scene_manager_get_scene_state(scene_manager, scene_id)};
scene_state.signal_index++;
if(infrared_progress_view_set_progress(infrared->progress, scene_state.signal_index + 1))
scene_manager_set_scene_state(scene_manager, scene_id, scene_state.packed_value);
break;
}
case InfraredProgressViewInputPreviousSignal: {
InfraredSceneState scene_state = {
.packed_value = scene_manager_get_scene_state(scene_manager, scene_id)};
if(scene_state.signal_index) {
scene_state.signal_index--;
if(infrared_progress_view_set_progress(
infrared->progress, scene_state.signal_index + 1))
scene_manager_set_scene_state(scene_manager, scene_id, scene_state.packed_value);
}
break;
}
case InfraredProgressViewInputSendSingle: {
InfraredSceneState scene_state = {
.packed_value = scene_manager_get_scene_state(scene_manager, scene_id)};
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
infrared_brute_force_send(infrared->brute_force, scene_state.signal_index);
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
break;
}
default:
furi_crash();
}
}
bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent event) {
InfraredApp* infrared = context;
SceneManager* scene_manager = infrared->scene_manager;
InfraredBruteForce* brute_force = infrared->brute_force;
uint32_t scene_id = scene_manager_get_current_scene(infrared->scene_manager);
bool consumed = false;
if(infrared_brute_force_is_started(brute_force)) {
if(event.type == SceneManagerEventTypeTick) {
bool success = infrared_brute_force_send_next(brute_force);
if(success) {
success = infrared_progress_view_increase_progress(infrared->progress);
InfraredSceneState scene_state = {
.packed_value = scene_manager_get_scene_state(scene_manager, scene_id)};
if(!scene_state.is_paused) {
bool success = infrared_brute_force_send(brute_force, scene_state.signal_index);
if(success) {
success = infrared_progress_view_set_progress(
infrared->progress, scene_state.signal_index + 1);
scene_state.signal_index++;
scene_manager_set_scene_state(
scene_manager, scene_id, scene_state.packed_value);
}
if(!success) {
infrared_brute_force_stop(brute_force);
infrared_scene_universal_common_hide_popup(infrared);
}
consumed = true;
}
if(!success) {
infrared_brute_force_stop(brute_force);
infrared_scene_universal_common_hide_popup(infrared);
}
consumed = true;
} else if(event.type == SceneManagerEventTypeCustom) {
if(infrared_custom_event_get_type(event.event) == InfraredCustomEventTypeBackPressed) {
infrared_brute_force_stop(brute_force);
infrared_scene_universal_common_hide_popup(infrared);
uint16_t event_type;
int16_t event_value;
infrared_custom_event_unpack(event.event, &event_type, &event_value);
if(event_type == InfraredCustomEventTypePopupInput) {
infrared_scene_universal_common_handle_popup_input(infrared, event_value);
consumed = true;
}
consumed = true;
}
} else {
if(event.type == SceneManagerEventTypeBack) {
@@ -87,6 +182,7 @@ bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent e
if(event_type == InfraredCustomEventTypeButtonSelected) {
uint32_t record_count;
if(infrared_brute_force_start(brute_force, event_value, &record_count)) {
scene_manager_set_scene_state(infrared->scene_manager, scene_id, 0);
dolphin_deed(DolphinDeedIrSend);
infrared_scene_universal_common_show_popup(infrared, record_count);
} else {

View File

@@ -118,7 +118,7 @@ void infrared_scene_universal_ac_on_enter(void* context) {
button_panel_add_icon(button_panel, 0, 60, &I_cool_30x51);
button_panel_add_icon(button_panel, 34, 60, &I_heat_30x51);
button_panel_add_label(button_panel, 4, 10, FontPrimary, "AC remote");
button_panel_add_label(button_panel, 24, 10, FontPrimary, "AC");
infrared_scene_universal_common_on_enter(context);
}

View File

@@ -114,7 +114,7 @@ void infrared_scene_universal_audio_on_enter(void* context) {
context);
infrared_brute_force_add_record(brute_force, i++, "Vol_up");
button_panel_add_label(button_panel, 1, 10, FontPrimary, "Mus. remote");
button_panel_add_label(button_panel, 1, 10, FontPrimary, "Audio player");
button_panel_add_icon(button_panel, 34, 56, &I_vol_ac_text_30x30);
infrared_scene_universal_common_on_enter(context);

View File

@@ -63,7 +63,7 @@ void infrared_scene_universal_projector_on_enter(void* context) {
context);
infrared_brute_force_add_record(brute_force, i++, "Vol_dn");
button_panel_add_label(button_panel, 3, 11, FontPrimary, "Proj. remote");
button_panel_add_label(button_panel, 10, 11, FontPrimary, "Projector");
button_panel_add_icon(button_panel, 17, 72, &I_vol_ac_text_30x30);
infrared_scene_universal_common_on_enter(context);

View File

@@ -91,7 +91,7 @@ void infrared_scene_universal_tv_on_enter(void* context) {
context);
infrared_brute_force_add_record(brute_force, i++, "Ch_prev");
button_panel_add_label(button_panel, 5, 10, FontPrimary, "TV remote");
button_panel_add_label(button_panel, 25, 10, FontPrimary, "TV");
infrared_scene_universal_common_on_enter(context);
}