| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608 |
- /*!
- * @file flipper-xremote/xremote_app.c
- @license This project is released under the GNU GPLv3 License
- * @copyright (c) 2023 Sandro Kalatozishvili (s.kalatoz@gmail.com)
- *
- * @brief Shared functionality and data types between the apps.
- */
- #include "xremote_app.h"
- //////////////////////////////////////////////////////////////////////////////
- // XRemote generic functions and definitions
- //////////////////////////////////////////////////////////////////////////////
- #define XREMOTE_APP_SETTINGS APP_DATA_PATH("xremote.cfg")
- #define XREMOTE_ORIENTATION_TEXT_HORIZONTAL "Horizontal"
- #define XREMOTE_ORIENTATION_TEXT_VERTICAL "Vertical"
- #define XREMOTE_ORIENTATION_INDEX_HORIZONTAL 0
- #define XREMOTE_ORIENTATION_INDEX_VERTICAL 1
- #define XREMOTE_EXIT_BEHAVIOR_TEXT_PRESS "Press"
- #define XREMOTE_EXIT_BEHAVIOR_TEXT_HOLD "Hold"
- #define XREMOTE_EXIT_BEHAVIOR_INDEX_PRESS 0
- #define XREMOTE_EXIT_BEHAVIOR_INDEX_HOLD 1
- const NotificationSequence g_sequence_blink_purple_50 = {
- &message_red_255,
- &message_blue_255,
- &message_delay_50,
- NULL,
- };
- XRemoteAppExit xremote_app_get_exit_behavior(uint8_t exit_index) {
- return exit_index ? XRemoteAppExitHold : XRemoteAppExitPress;
- }
- ViewOrientation xremote_app_get_orientation(uint8_t orientation_index) {
- return orientation_index ? ViewOrientationVertical : ViewOrientationHorizontal;
- }
- const char* xremote_app_get_exit_str(XRemoteAppExit exit_behavior) {
- return exit_behavior == XRemoteAppExitPress ? "Press" : "Hold";
- }
- const char* xremote_app_get_alt_names_str(uint8_t alt_names_index) {
- return alt_names_index ? "On" : "Off";
- }
- const char* xremote_app_get_orientation_str(ViewOrientation view_orientation) {
- return view_orientation == ViewOrientationHorizontal ? "Horizontal" : "Vertical";
- }
- uint32_t xremote_app_get_orientation_index(ViewOrientation view_orientation) {
- return view_orientation == ViewOrientationHorizontal ? 0 : 1;
- }
- uint32_t xremote_app_get_exit_index(XRemoteAppExit exit_behavior) {
- return exit_behavior == XRemoteAppExitPress ? 0 : 1;
- }
- void xremote_app_notification_blink(NotificationApp* notifications) {
- xremote_app_assert_void(notifications);
- notification_message(notifications, &g_sequence_blink_purple_50);
- }
- //////////////////////////////////////////////////////////////////////////////
- // XRemote buttons and custom button pairs
- //////////////////////////////////////////////////////////////////////////////
- bool xremote_app_extension_load(XRemoteAppButtons* buttons, FuriString* path) {
- Storage* storage = furi_record_open(RECORD_STORAGE);
- FlipperFormat* ff = flipper_format_buffered_file_alloc(storage);
- FuriString* tmp = furi_string_alloc();
- bool success = false;
- do {
- /* Open file and read the header */
- if(!flipper_format_buffered_file_open_existing(ff, furi_string_get_cstr(path))) break;
- if(!flipper_format_read_string(ff, "custom_ok", tmp)) break;
- furi_string_set(buttons->custom_ok, tmp);
- if(!flipper_format_read_string(ff, "custom_up", tmp)) break;
- furi_string_set(buttons->custom_up, tmp);
- if(!flipper_format_read_string(ff, "custom_down", tmp)) break;
- furi_string_set(buttons->custom_down, tmp);
- if(!flipper_format_read_string(ff, "custom_left", tmp)) break;
- furi_string_set(buttons->custom_left, tmp);
- if(!flipper_format_read_string(ff, "custom_right", tmp)) break;
- furi_string_set(buttons->custom_right, tmp);
- if(!flipper_format_read_string(ff, "custom_ok_hold", tmp)) break;
- furi_string_set(buttons->custom_ok_hold, tmp);
- if(!flipper_format_read_string(ff, "custom_up_hold", tmp)) break;
- furi_string_set(buttons->custom_up_hold, tmp);
- if(!flipper_format_read_string(ff, "custom_down_hold", tmp)) break;
- furi_string_set(buttons->custom_down_hold, tmp);
- if(!flipper_format_read_string(ff, "custom_left_hold", tmp)) break;
- furi_string_set(buttons->custom_left_hold, tmp);
- if(!flipper_format_read_string(ff, "custom_right_hold", tmp)) break;
- furi_string_set(buttons->custom_right_hold, tmp);
- success = true;
- } while(false);
- furi_record_close(RECORD_STORAGE);
- flipper_format_free(ff);
- furi_string_free(tmp);
- return success;
- }
- bool xremote_app_extension_store(XRemoteAppButtons* buttons, FuriString* path) {
- Storage* storage = furi_record_open(RECORD_STORAGE);
- FlipperFormat* ff = flipper_format_file_alloc(storage);
- bool success = false;
- do {
- if(!flipper_format_file_open_append(ff, furi_string_get_cstr(path))) break;
- if(!flipper_format_write_comment_cstr(ff, "XRemote extension")) break;
- if(!flipper_format_write_string(ff, "custom_ok", buttons->custom_ok)) break;
- if(!flipper_format_write_string(ff, "custom_up", buttons->custom_up)) break;
- if(!flipper_format_write_string(ff, "custom_down", buttons->custom_down)) break;
- if(!flipper_format_write_string(ff, "custom_left", buttons->custom_left)) break;
- if(!flipper_format_write_string(ff, "custom_right", buttons->custom_right)) break;
- if(!flipper_format_write_string(ff, "custom_ok_hold", buttons->custom_ok_hold)) break;
- if(!flipper_format_write_string(ff, "custom_up_hold", buttons->custom_up_hold)) break;
- if(!flipper_format_write_string(ff, "custom_down_hold", buttons->custom_down_hold)) break;
- if(!flipper_format_write_string(ff, "custom_left_hold", buttons->custom_left_hold)) break;
- if(!flipper_format_write_string(ff, "custom_right_hold", buttons->custom_right_hold))
- break;
- success = true;
- } while(false);
- furi_record_close(RECORD_STORAGE);
- flipper_format_free(ff);
- return success;
- }
- bool xremote_app_alt_names_check_and_init() {
- Storage* storage = furi_record_open(RECORD_STORAGE);
- FlipperFormat* ff = flipper_format_file_alloc(storage);
- bool success = false;
- do {
- if(!flipper_format_file_open_new(ff, XREMOTE_ALT_NAMES)) break;
- if(!flipper_format_write_header_cstr(ff, "XRemote Alt-Names", 1)) break;
- if(!flipper_format_write_comment_cstr(ff, "")) break;
- if(!flipper_format_write_string_cstr(ff, "Power", "shutdown,off,on,standby")) break;
- if(!flipper_format_write_string_cstr(ff, "Setup", "settings,config,cfg")) break;
- if(!flipper_format_write_string_cstr(ff, "Input", "source,select")) break;
- if(!flipper_format_write_string_cstr(ff, "Menu", "osd,gui")) break;
- if(!flipper_format_write_string_cstr(ff, "List", "guide")) break;
- if(!flipper_format_write_string_cstr(ff, "Info", "display")) break;
- if(!flipper_format_write_string_cstr(ff, "Mode", "aspect,format")) break;
- if(!flipper_format_write_string_cstr(ff, "Back", "return,exit")) break;
- if(!flipper_format_write_string_cstr(ff, "Ok", "enter,select")) break;
- if(!flipper_format_write_string_cstr(ff, "Up", "uparrow")) break;
- if(!flipper_format_write_string_cstr(ff, "Down", "downarrow")) break;
- if(!flipper_format_write_string_cstr(ff, "Left", "leftarrow")) break;
- if(!flipper_format_write_string_cstr(ff, "Right", "rightarrow")) break;
- if(!flipper_format_write_string_cstr(ff, "Mute", "silence,silent,unmute")) break;
- if(!flipper_format_write_string_cstr(ff, "Vol_up", "vol+,volume+,volup,+")) break;
- if(!flipper_format_write_string_cstr(ff, "Vol_dn", "vol-,volume-,voldown,-")) break;
- if(!flipper_format_write_string_cstr(ff, "Ch_next", "ch+,channel+,chup")) break;
- if(!flipper_format_write_string_cstr(ff, "Ch_prev", "ch-,channel-,chdown")) break;
- if(!flipper_format_write_string_cstr(ff, "Next", "next,skip,ffwd")) break;
- if(!flipper_format_write_string_cstr(ff, "Prev", "prev,back,rewind,rew")) break;
- if(!flipper_format_write_string_cstr(ff, "Fast_fo", "fastfwd,fastforward,ff")) break;
- if(!flipper_format_write_string_cstr(ff, "Fast_ba", "fastback,fastrewind,fb")) break;
- if(!flipper_format_write_string_cstr(ff, "Play_pa", "playpause,play,pause")) break;
- success = true;
- } while(false);
- furi_record_close(RECORD_STORAGE);
- flipper_format_free(ff);
- return success;
- }
- void xremote_app_buttons_free(XRemoteAppButtons* buttons) {
- xremote_app_assert_void(buttons);
- infrared_remote_free(buttons->remote);
- furi_string_free(buttons->custom_up);
- furi_string_free(buttons->custom_down);
- furi_string_free(buttons->custom_left);
- furi_string_free(buttons->custom_right);
- furi_string_free(buttons->custom_ok);
- furi_string_free(buttons->custom_up_hold);
- furi_string_free(buttons->custom_down_hold);
- furi_string_free(buttons->custom_left_hold);
- furi_string_free(buttons->custom_right_hold);
- furi_string_free(buttons->custom_ok_hold);
- free(buttons);
- }
- XRemoteAppButtons* xremote_app_buttons_alloc() {
- XRemoteAppButtons* buttons = malloc(sizeof(XRemoteAppButtons));
- buttons->remote = infrared_remote_alloc();
- buttons->app_ctx = NULL;
- /* Setup default buttons for custom layout */
- buttons->custom_up = furi_string_alloc_set_str(XREMOTE_COMMAND_UP);
- buttons->custom_down = furi_string_alloc_set_str(XREMOTE_COMMAND_DOWN);
- buttons->custom_left = furi_string_alloc_set_str(XREMOTE_COMMAND_LEFT);
- buttons->custom_right = furi_string_alloc_set_str(XREMOTE_COMMAND_RIGHT);
- buttons->custom_ok = furi_string_alloc_set_str(XREMOTE_COMMAND_OK);
- buttons->custom_up_hold = furi_string_alloc_set_str(XREMOTE_COMMAND_INPUT);
- buttons->custom_down_hold = furi_string_alloc_set_str(XREMOTE_COMMAND_SETUP);
- buttons->custom_left_hold = furi_string_alloc_set_str(XREMOTE_COMMAND_MENU);
- buttons->custom_right_hold = furi_string_alloc_set_str(XREMOTE_COMMAND_LIST);
- buttons->custom_ok_hold = furi_string_alloc_set_str(XREMOTE_COMMAND_POWER);
- return buttons;
- }
- XRemoteAppButtons* xremote_app_buttons_load(XRemoteAppContext* app_ctx) {
- /* Show file selection dialog (returns selected file path with app_ctx->file_path) */
- if(!xremote_app_context_select_file(app_ctx, XREMOTE_APP_EXTENSION)) return NULL;
- XRemoteAppButtons* buttons = xremote_app_buttons_alloc();
- buttons->app_ctx = app_ctx;
- /* Load buttons from the selected path */
- if(!infrared_remote_load(buttons->remote, app_ctx->file_path)) {
- xremote_app_buttons_free(buttons);
- return NULL;
- }
- /* Load custom buttons from the selected path */
- xremote_app_extension_load(buttons, app_ctx->file_path);
- return buttons;
- }
- //////////////////////////////////////////////////////////////////////////////
- // XRemote application settings
- //////////////////////////////////////////////////////////////////////////////
- XRemoteAppSettings* xremote_app_settings_alloc() {
- XRemoteAppSettings* settings = malloc(sizeof(XRemoteAppSettings));
- settings->orientation = ViewOrientationHorizontal;
- settings->exit_behavior = XRemoteAppExitPress;
- settings->repeat_count = 2;
- settings->alt_names = 1;
- return settings;
- }
- void xremote_app_settings_free(XRemoteAppSettings* settings) {
- xremote_app_assert_void(settings);
- free(settings);
- }
- bool xremote_app_settings_store(XRemoteAppSettings* settings) {
- Storage* storage = furi_record_open(RECORD_STORAGE);
- FlipperFormat* ff = flipper_format_file_alloc(storage);
- FURI_LOG_I(XREMOTE_APP_TAG, "store config file: \'%s\'", XREMOTE_APP_SETTINGS);
- bool success = false;
- do {
- /* Write header in config file */
- if(!flipper_format_file_open_always(ff, XREMOTE_APP_SETTINGS)) break;
- if(!flipper_format_write_header_cstr(ff, "XRemote", 1)) break;
- if(!flipper_format_write_comment_cstr(ff, "")) break;
- /* Write actual configuration to the settings file */
- uint32_t value = xremote_app_get_orientation_index(settings->orientation);
- if(!flipper_format_write_uint32(ff, "orientation", &value, 1)) break;
- value = xremote_app_get_exit_index(settings->exit_behavior);
- if(!flipper_format_write_uint32(ff, "appexit", &value, 1)) break;
- value = settings->repeat_count;
- if(!flipper_format_write_uint32(ff, "repeat", &value, 1)) break;
- value = settings->alt_names;
- if(!flipper_format_write_uint32(ff, "altNames", &value, 1)) break;
- success = true;
- } while(false);
- furi_record_close(RECORD_STORAGE);
- flipper_format_free(ff);
- return success;
- }
- bool xremote_app_settings_load(XRemoteAppSettings* settings) {
- Storage* storage = furi_record_open(RECORD_STORAGE);
- FlipperFormat* ff = flipper_format_buffered_file_alloc(storage);
- FuriString* header = furi_string_alloc();
- FURI_LOG_I(XREMOTE_APP_TAG, "load config file: \'%s\'", XREMOTE_APP_SETTINGS);
- uint32_t version = 0;
- uint32_t value = 0;
- bool success = false;
- do {
- /* Open file and read the header */
- if(!flipper_format_buffered_file_open_existing(ff, XREMOTE_APP_SETTINGS)) break;
- if(!flipper_format_read_header(ff, header, &version)) break;
- if(!furi_string_equal(header, "XRemote") || (version != 1)) break;
- /* Parse config data from the buffer */
- if(!flipper_format_read_uint32(ff, "orientation", &value, 1)) break;
- settings->orientation = xremote_app_get_orientation(value);
- if(!flipper_format_read_uint32(ff, "appexit", &value, 1)) break;
- settings->exit_behavior = xremote_app_get_exit_behavior(value);
- if(!flipper_format_read_uint32(ff, "repeat", &value, 1)) break;
- settings->repeat_count = value;
- if(!flipper_format_read_uint32(ff, "altNames", &value, 1)) break;
- settings->alt_names = value;
- success = true;
- } while(false);
- furi_record_close(RECORD_STORAGE);
- furi_string_free(header);
- flipper_format_free(ff);
- return success;
- }
- //////////////////////////////////////////////////////////////////////////////
- // XRemote gloal context shared between every child application
- //////////////////////////////////////////////////////////////////////////////
- XRemoteAppContext* xremote_app_context_alloc(void* arg) {
- XRemoteAppContext* ctx = malloc(sizeof(XRemoteAppContext));
- ctx->app_argument = arg;
- ctx->file_path = NULL;
- /* Open GUI and norification records */
- ctx->gui = furi_record_open(RECORD_GUI);
- ctx->notifications = furi_record_open(RECORD_NOTIFICATION);
- /* Allocate and load global app settings */
- ctx->app_settings = xremote_app_settings_alloc();
- xremote_app_settings_load(ctx->app_settings);
- /* Initialize alternative names */
- if(ctx->app_settings->alt_names) xremote_app_alt_names_check_and_init();
- /* Allocate and setup view dispatcher */
- ctx->view_dispatcher = view_dispatcher_alloc();
- view_dispatcher_enable_queue(ctx->view_dispatcher);
- view_dispatcher_attach_to_gui(ctx->view_dispatcher, ctx->gui, ViewDispatcherTypeFullscreen);
- return ctx;
- }
- void xremote_app_context_free(XRemoteAppContext* ctx) {
- xremote_app_assert_void(ctx);
- notification_internal_message(ctx->notifications, &sequence_reset_blue);
- xremote_app_settings_free(ctx->app_settings);
- view_dispatcher_free(ctx->view_dispatcher);
- furi_record_close(RECORD_NOTIFICATION);
- furi_record_close(RECORD_GUI);
- if(ctx->file_path != NULL) {
- furi_string_free(ctx->file_path);
- ctx->file_path = NULL;
- }
- free(ctx);
- }
- bool xremote_app_browser_select_file(FuriString** file_path, const char* extension) {
- DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
- Storage* storage = furi_record_open(RECORD_STORAGE);
- storage_simply_mkdir(storage, XREMOTE_APP_FOLDER);
- if(*file_path == NULL) {
- *file_path = furi_string_alloc();
- furi_string_set(*file_path, XREMOTE_APP_FOLDER);
- }
- /* Open file browser (view and dialogs are managed by the browser itself) */
- DialogsFileBrowserOptions browser;
- dialog_file_browser_set_basic_options(&browser, extension, &I_IR_Icon_10x10);
- browser.base_path = XREMOTE_APP_FOLDER;
- /* Show file selection dialog (returns selected file path with file_path) */
- bool status = dialog_file_browser_show(dialogs, *file_path, *file_path, &browser);
- /* Cleanup file loading context */
- furi_record_close(RECORD_STORAGE);
- furi_record_close(RECORD_DIALOGS);
- return status;
- }
- bool xremote_app_context_select_file(XRemoteAppContext* app_ctx, const char* extension) {
- if(app_ctx == NULL) return false;
- return xremote_app_browser_select_file(&app_ctx->file_path, extension);
- }
- const char* xremote_app_context_get_exit_str(XRemoteAppContext* app_ctx) {
- XRemoteAppExit exit_behavior = app_ctx->app_settings->exit_behavior;
- return exit_behavior == XRemoteAppExitHold ? "Hold to exit" : "Press to exit";
- }
- void xremote_app_context_notify_led(XRemoteAppContext* app_ctx) {
- xremote_app_assert_void(app_ctx);
- xremote_app_notification_blink(app_ctx->notifications);
- }
- bool xremote_app_send_signal(XRemoteAppContext* app_ctx, InfraredSignal* signal) {
- xremote_app_assert(signal, false);
- XRemoteAppSettings* settings = app_ctx->app_settings;
- infrared_signal_transmit_times(signal, settings->repeat_count);
- xremote_app_context_notify_led(app_ctx);
- return true;
- }
- //////////////////////////////////////////////////////////////////////////////
- // XRemote application factory
- //////////////////////////////////////////////////////////////////////////////
- void xremote_app_view_alloc(XRemoteApp* app, uint32_t view_id, XRemoteViewAllocator allocator) {
- furi_assert(app);
- xremote_app_assert_void(app->app_ctx);
- if(app->view_id == view_id && app->view_ctx != NULL) return;
- xremote_app_view_free(app);
- app->view_id = view_id;
- app->view_ctx = allocator(app->app_ctx);
- View* app_view = xremote_view_get_view(app->view_ctx);
- ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
- view_dispatcher_add_view(view_disp, app->view_id, app_view);
- }
- void xremote_app_view_alloc2(
- XRemoteApp* app,
- uint32_t view_id,
- XRemoteViewAllocator2 allocator,
- void* model_ctx) {
- furi_assert(app);
- xremote_app_assert_void(app->app_ctx);
- if(app->view_id == view_id && app->view_ctx != NULL) return;
- xremote_app_view_free(app);
- app->view_id = view_id;
- app->view_ctx = allocator(app->app_ctx, model_ctx);
- View* app_view = xremote_view_get_view(app->view_ctx);
- ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
- view_dispatcher_add_view(view_disp, app->view_id, app_view);
- }
- void xremote_app_view_free(XRemoteApp* app) {
- xremote_app_assert_void(app);
- if(app->app_ctx != NULL && app->view_id != XRemoteViewNone) {
- ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
- view_dispatcher_remove_view(view_disp, app->view_id);
- app->view_id = XRemoteViewNone;
- }
- if(app->view_ctx != NULL) {
- xremote_view_free(app->view_ctx);
- app->view_ctx = NULL;
- }
- }
- bool xremote_app_has_view(XRemoteApp* app, uint32_t view_id) {
- xremote_app_assert(app, false);
- return (app->view_id == view_id || app->submenu_id == view_id);
- }
- void xremote_app_switch_to_view(XRemoteApp* app, uint32_t view_id) {
- furi_assert(app);
- xremote_app_assert_void(app->app_ctx);
- ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
- view_dispatcher_switch_to_view(view_disp, view_id);
- }
- void xremote_app_switch_to_submenu(XRemoteApp* app) {
- furi_assert(app);
- xremote_app_assert_void(app->app_ctx);
- ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
- view_dispatcher_switch_to_view(view_disp, app->submenu_id);
- }
- void xremote_app_submenu_add(
- XRemoteApp* app,
- const char* name,
- uint32_t index,
- SubmenuItemCallback callback) {
- furi_assert(app);
- xremote_app_assert_void(app->submenu);
- submenu_add_item(app->submenu, name, index, callback, app);
- }
- void xremote_app_submenu_alloc(XRemoteApp* app, uint32_t index, ViewNavigationCallback prev_cb) {
- furi_assert(app);
- app->submenu = submenu_alloc();
- app->submenu_id = index;
- XRemoteAppSettings* settings = app->app_ctx->app_settings;
- View* view = submenu_get_view(app->submenu);
- view_set_previous_callback(view, prev_cb);
- #if defined(FW_ORIGIN_Unleashed) || defined(FW_ORIGIN_RM) || defined(FW_ORIGIN_Momentum)
- submenu_set_orientation(app->submenu, settings->orientation);
- #else
- view_set_orientation(view, settings->orientation);
- #endif
- ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
- view_dispatcher_add_view(view_disp, app->submenu_id, view);
- }
- void xremote_app_submenu_free(XRemoteApp* app) {
- xremote_app_assert_void(app);
- /* Remove submenu view from dispatcher */
- if(app->submenu_id != XRemoteViewNone && app->app_ctx != NULL) {
- ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
- view_dispatcher_remove_view(view_disp, app->submenu_id);
- app->submenu_id = XRemoteViewNone;
- }
- /* Free submenu */
- if(app->submenu != NULL) {
- submenu_free(app->submenu);
- app->submenu = NULL;
- }
- }
- void xremote_app_view_set_previous_callback(XRemoteApp* app, ViewNavigationCallback callback) {
- furi_assert(app);
- xremote_app_assert_void(app->view_ctx);
- View* view = xremote_view_get_view(app->view_ctx);
- view_set_previous_callback(view, callback);
- }
- void xremote_app_set_view_context(XRemoteApp* app, void* context, XRemoteClearCallback on_clear) {
- furi_assert(app);
- xremote_app_assert_void(app->view_ctx);
- xremote_view_set_context(app->view_ctx, context, on_clear);
- }
- void xremote_app_set_user_context(XRemoteApp* app, void* context, XRemoteClearCallback on_clear) {
- furi_assert(app);
- app->on_clear = on_clear;
- app->context = context;
- }
- void xremote_app_user_context_free(XRemoteApp* app) {
- furi_assert(app);
- xremote_app_assert_void(app->context);
- xremote_app_assert_void(app->on_clear);
- app->on_clear(app->context);
- app->on_clear = NULL;
- app->context = NULL;
- }
- XRemoteApp* xremote_app_alloc(XRemoteAppContext* ctx) {
- furi_assert(ctx);
- XRemoteApp* app = malloc(sizeof(XRemoteApp));
- xremote_app_assert(app, NULL);
- app->submenu_id = XRemoteViewNone;
- app->view_id = XRemoteViewNone;
- app->app_ctx = ctx;
- app->submenu = NULL;
- app->view_ctx = NULL;
- app->on_clear = NULL;
- app->context = NULL;
- return app;
- }
- void xremote_app_free(XRemoteApp* app) {
- xremote_app_assert_void(app);
- xremote_app_submenu_free(app);
- xremote_app_view_free(app);
- /* Call clear callback if there is an user context attached */
- if(app->on_clear != NULL) app->on_clear(app->context);
- free(app);
- }
|