| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- /*!
- * @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"
- #define XREMOTE_APP_SETTINGS ANY_PATH("infrared/assets/xremote.cfg")
- #define TAG "XRemoteApp"
- XRemoteAppSettings* xremote_app_settings_alloc()
- {
- XRemoteAppSettings* settings = malloc(sizeof(XRemoteAppSettings));
- settings->orientation = ViewOrientationHorizontal;
- settings->exit_behavior = XRemoteAppExitPress;
- settings->repeat_count = 2;
- 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(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 settings file", 1)) break;
- if (!flipper_format_write_comment_cstr(ff, "")) break;
- /* Write actual configuration to the settings file */
- if (!flipper_format_write_uint32(ff, "orientation", (uint32_t*)&settings->orientation, 1)) break;
- if (!flipper_format_write_uint32(ff, "repeat", (uint32_t*)&settings->repeat_count, 1)) break;
- if (!flipper_format_write_uint32(ff, "exit", (uint32_t*)&settings->exit_behavior, 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(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 settings file") || (version != 1)) break;
- /* Parse config data from the buffer */
- if (!flipper_format_read_uint32(ff, "orientation", &value, 1)) break;
- settings->orientation = value;
- if (!flipper_format_read_uint32(ff, "repeat", &value, 1)) break;
- settings->repeat_count = value;
- if (!flipper_format_read_uint32(ff, "exit", &value, 1)) break;
- settings->exit_behavior = value;
- success = true;
- } while(false);
- furi_record_close(RECORD_STORAGE);
- furi_string_free(header);
- flipper_format_free(ff);
- return success;
- }
- 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);
- /* 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);
- }
- const char* xremote_app_context_get_exit_str(XRemoteAppContext* ctx)
- {
- XRemoteAppExit exit_behavior = ctx->app_settings->exit_behavior;
- return exit_behavior == XRemoteAppExitHold ? "Hold to exit" : "Press to exit";
- }
- 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_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;
- submenu_set_orientation(app->submenu, settings->orientation);
- view_set_previous_callback(submenu_get_view(app->submenu), prev_cb);
- ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
- view_dispatcher_add_view(view_disp, app->submenu_id, submenu_get_view(app->submenu));
- }
- 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, XRemoteViewClearCallback 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, XRemoteAppClearCallback 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));
- 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);
- if (app->on_clear != NULL)
- app->on_clear(app->context);
- free(app);
- }
|