From be86b0f38ad7245749ac8bcafa12bf55f142f76b Mon Sep 17 00:00:00 2001 From: plgcoder <112718803+plgcoder@users.noreply.github.com> Date: Wed, 2 Aug 2023 05:43:36 +0200 Subject: [PATCH 1/2] Overly missed feature: Infrared: move button (change button order in a remote) (#2894) * Feature: Infrared: move button (change button order in a remote) * little fix in furi_assert (case Move button to the end) --- applications/main/infrared/infrared_i.h | 3 + applications/main/infrared/infrared_remote.c | 15 +++ applications/main/infrared/infrared_remote.h | 1 + .../infrared/scenes/infrared_scene_config.h | 2 + .../infrared/scenes/infrared_scene_edit.c | 12 ++ .../infrared_scene_edit_button_select.c | 35 +++++- .../scenes/infrared_scene_edit_move.c | 103 ++++++++++++++++++ .../scenes/infrared_scene_edit_move_done.c | 48 ++++++++ 8 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 applications/main/infrared/scenes/infrared_scene_edit_move.c create mode 100644 applications/main/infrared/scenes/infrared_scene_edit_move_done.c diff --git a/applications/main/infrared/infrared_i.h b/applications/main/infrared/infrared_i.h index 9e65c2b1c9d..96932d9bc5c 100644 --- a/applications/main/infrared/infrared_i.h +++ b/applications/main/infrared/infrared_i.h @@ -60,6 +60,8 @@ typedef enum { InfraredEditModeNone, InfraredEditModeRename, InfraredEditModeDelete, + InfraredEditModeMove, + InfraredEditModeMoveSelectDest } InfraredEditMode; typedef struct { @@ -69,6 +71,7 @@ typedef struct { InfraredEditTarget edit_target : 8; InfraredEditMode edit_mode : 8; int32_t current_button_index; + int32_t current_button_index_move_orig; uint32_t last_transmit_time; } InfraredAppState; diff --git a/applications/main/infrared/infrared_remote.c b/applications/main/infrared/infrared_remote.c index d3dfc2cce91..a04a338baa0 100644 --- a/applications/main/infrared/infrared_remote.c +++ b/applications/main/infrared/infrared_remote.c @@ -108,6 +108,21 @@ bool infrared_remote_delete_button(InfraredRemote* remote, size_t index) { return infrared_remote_store(remote); } +bool infrared_remote_move_button(InfraredRemote* remote, size_t index_orig, size_t index_dest) { + furi_assert(index_orig < InfraredButtonArray_size(remote->buttons)); + furi_assert(index_dest <= InfraredButtonArray_size(remote->buttons)); + if(index_orig == index_dest) { + return true; + } + InfraredRemoteButton* button; + InfraredButtonArray_pop_at(&button, remote->buttons, index_orig); + if(index_orig > index_dest) + InfraredButtonArray_push_at(remote->buttons, index_dest, button); + else + InfraredButtonArray_push_at(remote->buttons, index_dest - 1, button); + return infrared_remote_store(remote); +} + bool infrared_remote_store(InfraredRemote* remote) { Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* ff = flipper_format_file_alloc(storage); diff --git a/applications/main/infrared/infrared_remote.h b/applications/main/infrared/infrared_remote.h index 6eac193d3a0..2640149a482 100644 --- a/applications/main/infrared/infrared_remote.h +++ b/applications/main/infrared/infrared_remote.h @@ -23,6 +23,7 @@ bool infrared_remote_find_button_by_name(InfraredRemote* remote, const char* nam bool infrared_remote_add_button(InfraredRemote* remote, const char* name, InfraredSignal* signal); bool infrared_remote_rename_button(InfraredRemote* remote, const char* new_name, size_t index); bool infrared_remote_delete_button(InfraredRemote* remote, size_t index); +bool infrared_remote_move_button(InfraredRemote* remote, size_t index_orig, size_t index_dest); bool infrared_remote_store(InfraredRemote* remote); bool infrared_remote_load(InfraredRemote* remote, FuriString* path); diff --git a/applications/main/infrared/scenes/infrared_scene_config.h b/applications/main/infrared/scenes/infrared_scene_config.h index 27eabe225f5..36e6ae252f4 100644 --- a/applications/main/infrared/scenes/infrared_scene_config.h +++ b/applications/main/infrared/scenes/infrared_scene_config.h @@ -7,6 +7,8 @@ ADD_SCENE(infrared, edit_delete_done, EditDeleteDone) ADD_SCENE(infrared, edit_button_select, EditButtonSelect) ADD_SCENE(infrared, edit_rename, EditRename) ADD_SCENE(infrared, edit_rename_done, EditRenameDone) +ADD_SCENE(infrared, edit_move, EditMove) +ADD_SCENE(infrared, edit_move_done, EditMoveDone) ADD_SCENE(infrared, learn, Learn) ADD_SCENE(infrared, learn_done, LearnDone) ADD_SCENE(infrared, learn_enter_name, LearnEnterName) diff --git a/applications/main/infrared/scenes/infrared_scene_edit.c b/applications/main/infrared/scenes/infrared_scene_edit.c index 360ed49b351..79de04bda60 100644 --- a/applications/main/infrared/scenes/infrared_scene_edit.c +++ b/applications/main/infrared/scenes/infrared_scene_edit.c @@ -3,6 +3,7 @@ typedef enum { SubmenuIndexAddButton, SubmenuIndexRenameButton, + SubmenuIndexMoveButton, SubmenuIndexDeleteButton, SubmenuIndexRenameRemote, SubmenuIndexDeleteRemote, @@ -30,6 +31,12 @@ void infrared_scene_edit_on_enter(void* context) { SubmenuIndexRenameButton, infrared_scene_edit_submenu_callback, context); + submenu_add_item( + submenu, + "Move Button", + SubmenuIndexMoveButton, + infrared_scene_edit_submenu_callback, + context); submenu_add_item( submenu, "Delete Button", @@ -74,6 +81,11 @@ bool infrared_scene_edit_on_event(void* context, SceneManagerEvent event) { infrared->app_state.edit_mode = InfraredEditModeRename; scene_manager_next_scene(scene_manager, InfraredSceneEditButtonSelect); consumed = true; + } else if(submenu_index == SubmenuIndexMoveButton) { + infrared->app_state.edit_target = InfraredEditTargetButton; + infrared->app_state.edit_mode = InfraredEditModeMove; + scene_manager_next_scene(scene_manager, InfraredSceneEditButtonSelect); + consumed = true; } else if(submenu_index == SubmenuIndexDeleteButton) { infrared->app_state.edit_target = InfraredEditTargetButton; infrared->app_state.edit_mode = InfraredEditModeDelete; diff --git a/applications/main/infrared/scenes/infrared_scene_edit_button_select.c b/applications/main/infrared/scenes/infrared_scene_edit_button_select.c index a7f8a2bf7aa..7056a205396 100644 --- a/applications/main/infrared/scenes/infrared_scene_edit_button_select.c +++ b/applications/main/infrared/scenes/infrared_scene_edit_button_select.c @@ -11,9 +11,23 @@ void infrared_scene_edit_button_select_on_enter(void* context) { InfraredRemote* remote = infrared->remote; InfraredAppState* app_state = &infrared->app_state; - const char* header = infrared->app_state.edit_mode == InfraredEditModeRename ? - "Rename Button:" : - "Delete Button:"; + const char* header = NULL; + switch(infrared->app_state.edit_mode) { + case InfraredEditModeRename: + header = "Rename Button:"; + break; + case InfraredEditModeDelete: + header = "Delete Button:"; + break; + case InfraredEditModeMove: + header = "Select Button to Move:"; + break; + case InfraredEditModeMoveSelectDest: + case InfraredEditModeNone: + default: + header = "Move Button Before:"; + break; + } submenu_set_header(submenu, header); const size_t button_count = infrared_remote_get_button_count(remote); @@ -26,7 +40,14 @@ void infrared_scene_edit_button_select_on_enter(void* context) { infrared_scene_edit_button_select_submenu_callback, context); } - + if(infrared->app_state.edit_mode == InfraredEditModeMoveSelectDest) { + submenu_add_item( + submenu, + "-- Move to the end --", + button_count, + infrared_scene_edit_button_select_submenu_callback, + context); + } if(button_count && app_state->current_button_index != InfraredButtonIndexNone) { submenu_set_selected_item(submenu, app_state->current_button_index); app_state->current_button_index = InfraredButtonIndexNone; @@ -48,6 +69,12 @@ bool infrared_scene_edit_button_select_on_event(void* context, SceneManagerEvent scene_manager_next_scene(scene_manager, InfraredSceneEditRename); } else if(edit_mode == InfraredEditModeDelete) { scene_manager_next_scene(scene_manager, InfraredSceneEditDelete); + } else if(edit_mode == InfraredEditModeMove) { + app_state->current_button_index_move_orig = event.event; + app_state->edit_mode = InfraredEditModeMoveSelectDest; + scene_manager_next_scene(scene_manager, InfraredSceneEditButtonSelect); + } else if(edit_mode == InfraredEditModeMoveSelectDest) { + scene_manager_next_scene(scene_manager, InfraredSceneEditMove); } else { furi_assert(0); } diff --git a/applications/main/infrared/scenes/infrared_scene_edit_move.c b/applications/main/infrared/scenes/infrared_scene_edit_move.c new file mode 100644 index 00000000000..69c7ec41dea --- /dev/null +++ b/applications/main/infrared/scenes/infrared_scene_edit_move.c @@ -0,0 +1,103 @@ +#include "../infrared_i.h" + +static void infrared_scene_edit_move_dialog_result_callback(DialogExResult result, void* context) { + Infrared* infrared = context; + view_dispatcher_send_custom_event(infrared->view_dispatcher, result); +} + +void infrared_scene_edit_move_on_enter(void* context) { + Infrared* infrared = context; + DialogEx* dialog_ex = infrared->dialog_ex; + InfraredRemote* remote = infrared->remote; + + const InfraredEditTarget edit_target = infrared->app_state.edit_target; + if(edit_target == InfraredEditTargetButton) { + int32_t current_button_index = infrared->app_state.current_button_index_move_orig; + furi_assert(current_button_index != InfraredButtonIndexNone); + + dialog_ex_set_header(dialog_ex, "Move Button?", 64, 0, AlignCenter, AlignTop); + InfraredRemoteButton* current_button = + infrared_remote_get_button(remote, current_button_index); + InfraredSignal* signal = infrared_remote_button_get_signal(current_button); + + if(infrared_signal_is_raw(signal)) { + const InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); + infrared_text_store_set( + infrared, + 0, + "%s\nRAW\n%ld samples", + infrared_remote_button_get_name(current_button), + raw->timings_size); + + } else { + const InfraredMessage* message = infrared_signal_get_message(signal); + infrared_text_store_set( + infrared, + 0, + "%s\n%s\nA=0x%0*lX C=0x%0*lX", + infrared_remote_button_get_name(current_button), + infrared_get_protocol_name(message->protocol), + ROUND_UP_TO(infrared_get_protocol_address_length(message->protocol), 4), + message->address, + ROUND_UP_TO(infrared_get_protocol_command_length(message->protocol), 4), + message->command); + } + } else { + furi_assert(0); + } + + dialog_ex_set_text(dialog_ex, infrared->text_store[0], 64, 31, AlignCenter, AlignCenter); + dialog_ex_set_icon(dialog_ex, 0, 0, NULL); + dialog_ex_set_left_button_text(dialog_ex, "Cancel"); + dialog_ex_set_right_button_text(dialog_ex, "Move"); + dialog_ex_set_result_callback(dialog_ex, infrared_scene_edit_move_dialog_result_callback); + dialog_ex_set_context(dialog_ex, context); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx); +} + +bool infrared_scene_edit_move_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + SceneManager* scene_manager = infrared->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == DialogExResultLeft) { + scene_manager_previous_scene(scene_manager); + consumed = true; + } else if(event.event == DialogExResultRight) { + bool success = false; + InfraredRemote* remote = infrared->remote; + InfraredAppState* app_state = &infrared->app_state; + const InfraredEditTarget edit_target = app_state->edit_target; + + if(edit_target == InfraredEditTargetButton) { + furi_assert(app_state->current_button_index != InfraredButtonIndexNone); + success = infrared_remote_move_button( + remote, + app_state->current_button_index_move_orig, + app_state->current_button_index); + app_state->current_button_index_move_orig = InfraredButtonIndexNone; + app_state->current_button_index = InfraredButtonIndexNone; + } else { + furi_assert(0); + } + + if(success) { + scene_manager_next_scene(scene_manager, InfraredSceneEditMoveDone); + } else { + const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart}; + scene_manager_search_and_switch_to_previous_scene_one_of( + scene_manager, possible_scenes, COUNT_OF(possible_scenes)); + } + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_edit_move_on_exit(void* context) { + Infrared* infrared = context; + UNUSED(infrared); +} diff --git a/applications/main/infrared/scenes/infrared_scene_edit_move_done.c b/applications/main/infrared/scenes/infrared_scene_edit_move_done.c new file mode 100644 index 00000000000..9f9b4b80d3e --- /dev/null +++ b/applications/main/infrared/scenes/infrared_scene_edit_move_done.c @@ -0,0 +1,48 @@ +#include "../infrared_i.h" + +void infrared_scene_edit_move_done_on_enter(void* context) { + Infrared* infrared = context; + Popup* popup = infrared->popup; + + popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); + popup_set_header(popup, "Moved", 83, 19, AlignLeft, AlignBottom); + + popup_set_callback(popup, infrared_popup_closed_callback); + popup_set_context(popup, context); + popup_set_timeout(popup, 1500); + popup_enable_timeout(popup); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup); +} + +bool infrared_scene_edit_move_done_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + SceneManager* scene_manager = infrared->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == InfraredCustomEventTypePopupClosed) { + const InfraredEditTarget edit_target = infrared->app_state.edit_target; + if(edit_target == InfraredEditTargetButton) { + scene_manager_search_and_switch_to_previous_scene( + scene_manager, InfraredSceneRemote); + } else if(edit_target == InfraredEditTargetRemote) { + const uint32_t possible_scenes[] = {InfraredSceneStart, InfraredSceneRemoteList}; + if(!scene_manager_search_and_switch_to_previous_scene_one_of( + scene_manager, possible_scenes, COUNT_OF(possible_scenes))) { + view_dispatcher_stop(infrared->view_dispatcher); + } + } else { + furi_assert(0); + } + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_edit_move_done_on_exit(void* context) { + Infrared* infrared = context; + UNUSED(infrared); +} From 035e447009b6e075ef2f94fd5e761ffb2ed87f99 Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Wed, 2 Aug 2023 12:58:39 +0900 Subject: [PATCH 2/2] [FL-3462] External apps icounter (#2928) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/external/hid_app/hid.c | 5 ----- applications/services/dolphin/helpers/dolphin_deed.c | 2 +- applications/services/loader/loader_applications.c | 3 +++ 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/applications/external/hid_app/hid.c b/applications/external/hid_app/hid.c index a969a933a12..2be9afd919c 100644 --- a/applications/external/hid_app/hid.c +++ b/applications/external/hid_app/hid.c @@ -1,7 +1,6 @@ #include "hid.h" #include "views.h" #include -#include #define TAG "HidApp" @@ -389,8 +388,6 @@ int32_t hid_usb_app(void* p) { bt_hid_connection_status_changed_callback(BtStatusConnected, app); - dolphin_deed(DolphinDeedPluginStart); - view_dispatcher_run(app->view_dispatcher); furi_hal_usb_set_config(usb_mode_prev, NULL); @@ -429,8 +426,6 @@ int32_t hid_ble_app(void* p) { furi_hal_bt_start_advertising(); bt_set_status_changed_callback(app->bt, bt_hid_connection_status_changed_callback, app); - dolphin_deed(DolphinDeedPluginStart); - view_dispatcher_run(app->view_dispatcher); bt_set_status_changed_callback(app->bt, NULL, NULL); diff --git a/applications/services/dolphin/helpers/dolphin_deed.c b/applications/services/dolphin/helpers/dolphin_deed.c index 51db56fdf68..f1f42b770fd 100644 --- a/applications/services/dolphin/helpers/dolphin_deed.c +++ b/applications/services/dolphin/helpers/dolphin_deed.c @@ -39,7 +39,7 @@ static const DolphinDeedWeight dolphin_deed_weights[] = { {1, DolphinAppPlugin}, // DolphinDeedGpioUartBridge - {1, DolphinAppPlugin}, // DolphinDeedPluginStart + {2, DolphinAppPlugin}, // DolphinDeedPluginStart {1, DolphinAppPlugin}, // DolphinDeedPluginGameStart {10, DolphinAppPlugin}, // DolphinDeedPluginGameWin }; diff --git a/applications/services/loader/loader_applications.c b/applications/services/loader/loader_applications.c index 8ae91d76408..2e1de6134aa 100644 --- a/applications/services/loader/loader_applications.c +++ b/applications/services/loader/loader_applications.c @@ -6,6 +6,7 @@ #include #include #include +#include #define TAG "LoaderApplications" @@ -119,6 +120,8 @@ static void loader_pubsub_callback(const void* message, void* context) { static void loader_applications_start_app(LoaderApplicationsApp* app) { const char* name = furi_string_get_cstr(app->fap_path); + dolphin_deed(DolphinDeedPluginStart); + // load app FuriThreadId thread_id = furi_thread_get_current_id(); FuriPubSubSubscription* subscription =