From d7b151ab883376962996123c65d5ffe2f991d5ee Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Tue, 26 Nov 2024 22:17:01 +0100 Subject: [PATCH] refactor app code (#93) --- AppEsp32/Source/HelloWorld/HelloWorld.cpp | 4 +- AppSim/Source/HelloWorld/hello_world.cpp | 4 +- Tactility/Private/app/AppInstance.h | 66 ++++++++++++ Tactility/Private/service/loader/Loader_i.h | 5 +- Tactility/Source/Tactility.cpp | 8 +- Tactility/Source/app/App.cpp | 102 ------------------ Tactility/Source/app/App.h | 96 +++-------------- Tactility/Source/app/AppInstance.cpp | 60 +++++++++++ Tactility/Source/app/Manifest.h | 21 ++-- Tactility/Source/app/ManifestRegistry.cpp | 38 +++---- Tactility/Source/app/ManifestRegistry.h | 8 +- Tactility/Source/app/desktop/Desktop.cpp | 6 +- Tactility/Source/app/display/Display.cpp | 14 +-- Tactility/Source/app/files/Files.cpp | 18 ++-- Tactility/Source/app/gpio/Gpio.cpp | 29 +++-- .../Source/app/i2csettings/I2cSettings.cpp | 4 +- .../Source/app/imageviewer/ImageViewer.cpp | 6 +- Tactility/Source/app/power/Power.cpp | 24 ++--- .../Source/app/screenshot/Screenshot.cpp | 18 ++-- .../Source/app/screenshot/ScreenshotUi.cpp | 2 +- .../Source/app/screenshot/ScreenshotUi.h | 2 +- Tactility/Source/app/settings/Settings.cpp | 12 +-- .../Source/app/systeminfo/SystemInfo.cpp | 8 +- .../Source/app/textviewer/TextViewer.cpp | 6 +- .../Source/app/wificonnect/WifiConnect.cpp | 25 +++-- .../app/wificonnect/WifiConnectView.cpp | 4 +- .../Source/app/wificonnect/WifiConnectView.h | 2 +- .../Source/app/wifimanage/WifiManage.cpp | 25 +++-- .../Source/app/wifimanage/WifiManageView.cpp | 2 +- .../Source/app/wifimanage/WifiManageView.h | 2 +- Tactility/Source/lvgl/Toolbar.cpp | 5 +- Tactility/Source/lvgl/Toolbar.h | 2 +- Tactility/Source/service/gui/Gui.cpp | 9 +- Tactility/Source/service/gui/Gui.h | 2 +- Tactility/Source/service/gui/GuiDraw.cpp | 8 +- Tactility/Source/service/gui/ViewPort.cpp | 22 ++-- Tactility/Source/service/gui/ViewPort.h | 21 ++-- Tactility/Source/service/loader/Loader.cpp | 100 ++++++++--------- Tactility/Source/service/loader/Loader.h | 10 +- .../service/screenshot/ScreenshotTask.cpp | 6 +- 40 files changed, 367 insertions(+), 439 deletions(-) create mode 100644 Tactility/Private/app/AppInstance.h delete mode 100644 Tactility/Source/app/App.cpp create mode 100644 Tactility/Source/app/AppInstance.cpp diff --git a/AppEsp32/Source/HelloWorld/HelloWorld.cpp b/AppEsp32/Source/HelloWorld/HelloWorld.cpp index 3d73a157..77668c13 100644 --- a/AppEsp32/Source/HelloWorld/HelloWorld.cpp +++ b/AppEsp32/Source/HelloWorld/HelloWorld.cpp @@ -1,7 +1,7 @@ #include "lvgl.h" #include "lvgl/Toolbar.h" -static void app_show(tt::app::App app, lv_obj_t* parent) { +static void app_show(tt::app::App& app, lv_obj_t* parent) { lv_obj_t* toolbar = tt::lvgl::toolbar_create(parent, app); lv_obj_align(toolbar, LV_ALIGN_TOP_MID, 0, 0); @@ -14,5 +14,5 @@ extern const tt::app::Manifest hello_world_app = { .id = "HelloWorld", .name = "Hello World", .type = tt::app::TypeUser, - .on_show = &app_show, + .onShow = &app_show, }; diff --git a/AppSim/Source/HelloWorld/hello_world.cpp b/AppSim/Source/HelloWorld/hello_world.cpp index 4f2e8478..2bf384e5 100644 --- a/AppSim/Source/HelloWorld/hello_world.cpp +++ b/AppSim/Source/HelloWorld/hello_world.cpp @@ -1,6 +1,6 @@ #include "lvgl/Toolbar.h" -static void app_show(tt::app::App app, lv_obj_t* parent) { +static void app_show(tt::app::App& app, lv_obj_t* parent) { lv_obj_t* toolbar = tt::lvgl::toolbar_create(parent, app); lv_obj_align(toolbar, LV_ALIGN_TOP_MID, 0, 0); @@ -13,5 +13,5 @@ extern const tt::app::Manifest hello_world_app = { .id = "HelloWorld", .name = "Hello World", .type = tt::app::TypeUser, - .on_show = &app_show + .onShow = &app_show }; diff --git a/Tactility/Private/app/AppInstance.h b/Tactility/Private/app/AppInstance.h new file mode 100644 index 00000000..7cfc59fd --- /dev/null +++ b/Tactility/Private/app/AppInstance.h @@ -0,0 +1,66 @@ +#pragma once + +#include "app/App.h" +#include "app/Manifest.h" +#include "Bundle.h" +#include "Mutex.h" + +namespace tt::app { + +typedef enum { + StateInitial, // App is being activated in loader + StateStarted, // App is in memory + StateShowing, // App view is created + StateHiding, // App view is destroyed + StateStopped // App is not in memory +} State; + +/** + * Thread-safe app instance. + */ +class AppInstance : public App { + +private: + + Mutex mutex = Mutex(MutexTypeNormal); + const Manifest& manifest; + State state = StateInitial; + Flags flags = { .showStatusbar = true }; + /** @brief Optional parameters to start the app with + * When these are stored in the app struct, the struct takes ownership. + * Do not mutate after app creation. + */ + tt::Bundle parameters; + /** @brief @brief Contextual data related to the running app's instance + * The app can attach its data to this. + * The lifecycle is determined by the on_start and on_stop methods in the AppManifest. + * These manifest methods can optionally allocate/free data that is attached here. + */ + void* _Nullable data = nullptr; + +public: + + AppInstance(const Manifest& manifest) : + manifest(manifest) {} + + AppInstance(const Manifest& manifest, const Bundle& parameters) : + manifest(manifest), + parameters(parameters) {} + + ~AppInstance() {} + + void setState(State state); + State getState() const; + + const Manifest& getManifest() const; + + Flags getFlags() const; + void setFlags(Flags flags); + + _Nullable void* getData() const; + void setData(void* data); + + const Bundle& getParameters() const; +}; + +} // namespace diff --git a/Tactility/Private/service/loader/Loader_i.h b/Tactility/Private/service/loader/Loader_i.h index b5784d20..5220c1ca 100644 --- a/Tactility/Private/service/loader/Loader_i.h +++ b/Tactility/Private/service/loader/Loader_i.h @@ -1,11 +1,13 @@ #pragma once #include "app/Manifest.h" +#include "app/AppInstance.h" #include "MessageQueue.h" #include "Pubsub.h" #include "Thread.h" #include "service/gui/ViewPort.h" #include "service/loader/Loader.h" +#include #ifdef ESP_PLATFORM #include "freertos/FreeRTOS.h" @@ -108,8 +110,7 @@ struct Loader { PubSub* pubsub_external; MessageQueue queue = MessageQueue(1, sizeof(LoaderMessage)); Mutex* mutex; - int8_t app_stack_index; - app::App app_stack[APP_STACK_SIZE]; + std::stack app_stack; }; } // namespace diff --git a/Tactility/Source/Tactility.cpp b/Tactility/Source/Tactility.cpp index 4e19e0ae..a70f4455 100644 --- a/Tactility/Source/Tactility.cpp +++ b/Tactility/Source/Tactility.cpp @@ -76,11 +76,11 @@ static const std::vector system_apps = { static void register_system_apps() { TT_LOG_I(TAG, "Registering default apps"); for (const auto& app_manifest: system_apps) { - app_manifest_registry_add(app_manifest); + addApp(app_manifest); } if (getConfiguration()->hardware->power != nullptr) { - app_manifest_registry_add(&app::power::manifest); + addApp(&app::power::manifest); } } @@ -89,7 +89,7 @@ static void register_user_apps(const app::Manifest* const apps[TT_CONFIG_APPS_LI for (size_t i = 0; i < TT_CONFIG_APPS_LIMIT; i++) { const app::Manifest* manifest = apps[i]; if (manifest != nullptr) { - app_manifest_registry_add(manifest); + addApp(manifest); } else { // reached end of list break; @@ -129,8 +129,6 @@ void init(const Configuration* config) { lvgl::init(config->hardware); - app::app_manifest_registry_init(); - // Note: the order of starting apps and services is critical! // System services are registered first so the apps below can find them if needed register_and_start_system_services(); diff --git a/Tactility/Source/app/App.cpp b/Tactility/Source/app/App.cpp deleted file mode 100644 index f379d9d0..00000000 --- a/Tactility/Source/app/App.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include "app/App.h" - -namespace tt::app { - -#define TAG "app" - -void AppInstance::setState(State newState) { - mutex.acquire(TtWaitForever); - state = newState; - mutex.release(); -} - -State AppInstance::getState() { - mutex.acquire(TtWaitForever); - auto result = state; - mutex.release(); - return result; -} - -/** TODO: Make this thread-safe. - * In practice, the bundle is writeable, so someone could be writing to it - * while it is being accessed from another thread. - * Consider creating MutableBundle vs Bundle. - * Consider not exposing bundle, but expose `app_get_bundle_int(key)` methods with locking in it. - */ -const Manifest& AppInstance::getManifest() { - return manifest; -} - -Flags AppInstance::getFlags() { - mutex.acquire(TtWaitForever); - auto result = flags; - mutex.release(); - return result; -} - -void AppInstance::setFlags(Flags newFlags) { - mutex.acquire(TtWaitForever); - flags = newFlags; - mutex.release(); -} - -_Nullable void* AppInstance::getData() { - mutex.acquire(TtWaitForever); - auto result = data; - mutex.release(); - return result; -} - -void AppInstance::setData(void* newData) { - mutex.acquire(TtWaitForever); - data = newData; - mutex.release(); -} - -const Bundle& AppInstance::getParameters() { - return parameters; -} - -App tt_app_alloc(const Manifest& manifest, const Bundle& parameters) { - auto* instance = new AppInstance(manifest, parameters); - return static_cast(instance); -} - -void tt_app_free(App app) { - auto* instance = static_cast(app); - delete instance; -} - -void tt_app_set_state(App app, State state) { - static_cast(app)->setState(state); -} - -State tt_app_get_state(App app) { - return static_cast(app)->getState(); -} - -const Manifest& tt_app_get_manifest(App app) { - return static_cast(app)->getManifest(); -} - -Flags tt_app_get_flags(App app) { - return static_cast(app)->getFlags(); -} - -void tt_app_set_flags(App app, Flags flags) { - return static_cast(app)->setFlags(flags); -} - -void* tt_app_get_data(App app) { - return static_cast(app)->getData(); -} - -void tt_app_set_data(App app, void* data) { - return static_cast(app)->setData(data); -} - -const Bundle& tt_app_get_parameters(App app) { - return static_cast(app)->getParameters(); -} - -} // namespace diff --git a/Tactility/Source/app/App.h b/Tactility/Source/app/App.h index 9e4a9e52..80125514 100644 --- a/Tactility/Source/app/App.h +++ b/Tactility/Source/app/App.h @@ -2,98 +2,28 @@ #include "Manifest.h" #include "Bundle.h" -#include "Mutex.h" namespace tt::app { -typedef enum { - StateInitial, // App is being activated in loader - StateStarted, // App is in memory - StateShowing, // App view is created - StateHiding, // App view is destroyed - StateStopped // App is not in memory -} State; - typedef union { struct { - bool show_statusbar : 1; + bool showStatusbar : 1; }; unsigned char flags; } Flags; - -class AppInstance { - -private: - - Mutex mutex = Mutex(MutexTypeNormal); - const Manifest& manifest; - State state = StateInitial; - Flags flags = { .show_statusbar = true }; - /** @brief Optional parameters to start the app with - * When these are stored in the app struct, the struct takes ownership. - * Do not mutate after app creation. - */ - tt::Bundle parameters; - /** @brief @brief Contextual data related to the running app's instance - * The app can attach its data to this. - * The lifecycle is determined by the on_start and on_stop methods in the AppManifest. - * These manifest methods can optionally allocate/free data that is attached here. - */ - void* _Nullable data = nullptr; - +/** + * A limited representation of the application instance. + * Do not store references or pointers to these! + */ +class App { public: - - AppInstance(const Manifest& manifest) : - manifest(manifest) {} - - AppInstance(const Manifest& manifest, const Bundle& parameters) : - manifest(manifest), - parameters(parameters) {} - - void setState(State state); - State getState(); - - const Manifest& getManifest(); - - Flags getFlags(); - void setFlags(Flags flags); - - _Nullable void* getData(); - void setData(void* data); - - const Bundle& getParameters(); + virtual ~App() {}; + virtual const Manifest& getManifest() const = 0; + virtual _Nullable void* getData() const = 0; + virtual void setData(void* data) = 0; + virtual const Bundle& getParameters() const = 0; + virtual Flags getFlags() const = 0; }; -/** @brief Create an app - * @param manifest - * @param parameters optional bundle. memory ownership is transferred to App - * @return - */ -[[deprecated("use class")]] -App tt_app_alloc(const Manifest& manifest, const Bundle& parameters); -[[deprecated("use class")]] -void tt_app_free(App app); - -[[deprecated("use class")]] -void tt_app_set_state(App app, State state); -[[deprecated("use class")]] -State tt_app_get_state(App app); - -[[deprecated("use class")]] -const Manifest& tt_app_get_manifest(App app); - -[[deprecated("use class")]] -Flags tt_app_get_flags(App app); -[[deprecated("use class")]] -void tt_app_set_flags(App app, Flags flags); - -[[deprecated("use class")]] -void* _Nullable tt_app_get_data(App app); -[[deprecated("use class")]] -void tt_app_set_data(App app, void* data); - -[[deprecated("use class")]] -const Bundle& tt_app_get_parameters(App app); - -} // namespace +} diff --git a/Tactility/Source/app/AppInstance.cpp b/Tactility/Source/app/AppInstance.cpp new file mode 100644 index 00000000..a55f2793 --- /dev/null +++ b/Tactility/Source/app/AppInstance.cpp @@ -0,0 +1,60 @@ +#include "app/AppInstance.h" + +namespace tt::app { + +#define TAG "app" + +void AppInstance::setState(State newState) { + mutex.acquire(TtWaitForever); + state = newState; + mutex.release(); +} + +State AppInstance::getState() const { + mutex.acquire(TtWaitForever); + auto result = state; + mutex.release(); + return result; +} + +/** TODO: Make this thread-safe. + * In practice, the bundle is writeable, so someone could be writing to it + * while it is being accessed from another thread. + * Consider creating MutableBundle vs Bundle. + * Consider not exposing bundle, but expose `app_get_bundle_int(key)` methods with locking in it. + */ +const Manifest& AppInstance::getManifest() const { + return manifest; +} + +Flags AppInstance::getFlags() const { + mutex.acquire(TtWaitForever); + auto result = flags; + mutex.release(); + return result; +} + +void AppInstance::setFlags(Flags newFlags) { + mutex.acquire(TtWaitForever); + flags = newFlags; + mutex.release(); +} + +_Nullable void* AppInstance::getData() const { + mutex.acquire(TtWaitForever); + auto result = data; + mutex.release(); + return result; +} + +void AppInstance::setData(void* newData) { + mutex.acquire(TtWaitForever); + data = newData; + mutex.release(); +} + +const Bundle& AppInstance::getParameters() const { + return parameters; +} + +} // namespace diff --git a/Tactility/Source/app/Manifest.h b/Tactility/Source/app/Manifest.h index c8b3517d..ad2585be 100644 --- a/Tactility/Source/app/Manifest.h +++ b/Tactility/Source/app/Manifest.h @@ -8,7 +8,7 @@ typedef struct _lv_obj_t lv_obj_t; namespace tt::app { -typedef void* App; +class App; typedef enum { /** A desktop app sits at the root of the app stack managed by the Loader service */ @@ -23,10 +23,11 @@ typedef enum { TypeUser } Type; -typedef void (*AppOnStart)(App app); -typedef void (*AppOnStop)(App app); -typedef void (*AppOnShow)(App app, lv_obj_t* parent); -typedef void (*AppOnHide)(App app); + +typedef void (*AppOnStart)(App& app); +typedef void (*AppOnStop)(App& app); +typedef void (*AppOnShow)(App& app, lv_obj_t* parent); +typedef void (*AppOnHide)(App& app); typedef struct Manifest { /** @@ -52,26 +53,26 @@ typedef struct Manifest { /** * Non-blocking method to call when app is started. */ - const AppOnStart on_start = nullptr; + const AppOnStart onStart = nullptr; /** * Non-blocking method to call when app is stopped. */ - const AppOnStop _Nullable on_stop = nullptr; + const AppOnStop _Nullable onStop = nullptr; /** * Non-blocking method to create the GUI */ - const AppOnShow _Nullable on_show = nullptr; + const AppOnShow _Nullable onShow = nullptr; /** * Non-blocking method, called before gui is destroyed */ - const AppOnHide _Nullable on_hide = nullptr; + const AppOnHide _Nullable onHide = nullptr; } AppManifest; struct { - bool operator()(const Manifest* a, const Manifest* b) const { return a->name < b->name; } + bool operator()(const Manifest* left, const Manifest* right) const { return left->name < right->name; } } SortAppManifestByName; } // namespace diff --git a/Tactility/Source/app/ManifestRegistry.cpp b/Tactility/Source/app/ManifestRegistry.cpp index 6bcb8ee7..e25a6a92 100644 --- a/Tactility/Source/app/ManifestRegistry.cpp +++ b/Tactility/Source/app/ManifestRegistry.cpp @@ -3,52 +3,38 @@ #include "TactilityCore.h" #include -#define TAG "app_registry" +#define TAG "app" namespace tt::app { typedef std::unordered_map AppManifestMap; static AppManifestMap app_manifest_map; -static Mutex* hash_mutex = nullptr; +static Mutex hash_mutex(MutexTypeNormal); -static void app_registry_lock() { - tt_assert(hash_mutex != nullptr); - tt_mutex_acquire(hash_mutex, TtWaitForever); -} +void addApp(const Manifest* manifest) { + TT_LOG_I(TAG, "Registering manifest %s", manifest->id.c_str()); -static void app_registry_unlock() { - tt_assert(hash_mutex != nullptr); - tt_mutex_release(hash_mutex); -} - -void app_manifest_registry_init() { - tt_assert(hash_mutex == nullptr); - hash_mutex = tt_mutex_alloc(MutexTypeNormal); -} -void app_manifest_registry_add(const Manifest* manifest) { - TT_LOG_I(TAG, "adding %s", manifest->id.c_str()); - - app_registry_lock(); + hash_mutex.acquire(TtWaitForever); app_manifest_map[manifest->id] = manifest; - app_registry_unlock(); + hash_mutex.release(); } -_Nullable const Manifest * app_manifest_registry_find_by_id(const std::string& id) { - app_registry_lock(); +_Nullable const Manifest * findAppById(const std::string& id) { + hash_mutex.acquire(TtWaitForever); auto iterator = app_manifest_map.find(id); _Nullable const Manifest* result = iterator != app_manifest_map.end() ? iterator->second : nullptr; - app_registry_unlock(); + hash_mutex.release(); return result; } -std::vector app_manifest_registry_get() { +std::vector getApps() { std::vector manifests; - app_registry_lock(); + hash_mutex.acquire(TtWaitForever); for (const auto& item: app_manifest_map) { manifests.push_back(item.second); } - app_registry_unlock(); + hash_mutex.release(); return manifests; } diff --git a/Tactility/Source/app/ManifestRegistry.h b/Tactility/Source/app/ManifestRegistry.h index 33840737..cf2b5821 100644 --- a/Tactility/Source/app/ManifestRegistry.h +++ b/Tactility/Source/app/ManifestRegistry.h @@ -6,10 +6,8 @@ namespace tt::app { -void app_manifest_registry_init(); -void app_manifest_registry_add(const Manifest* manifest); -void app_manifest_registry_remove(const Manifest* manifest); -const Manifest _Nullable* app_manifest_registry_find_by_id(const std::string& id); -std::vector app_manifest_registry_get(); +void addApp(const Manifest* manifest); +const Manifest _Nullable* findAppById(const std::string& id); +std::vector getApps(); } // namespace diff --git a/Tactility/Source/app/desktop/Desktop.cpp b/Tactility/Source/app/desktop/Desktop.cpp index e2e734e7..4a46b1ee 100644 --- a/Tactility/Source/app/desktop/Desktop.cpp +++ b/Tactility/Source/app/desktop/Desktop.cpp @@ -23,12 +23,12 @@ static void create_app_widget(const Manifest* manifest, void* parent) { lv_obj_add_event_cb(btn, &on_app_pressed, LV_EVENT_CLICKED, (void*)manifest); } -static void desktop_show(TT_UNUSED App app, lv_obj_t* parent) { +static void desktop_show(TT_UNUSED App& app, lv_obj_t* parent) { lv_obj_t* list = lv_list_create(parent); lv_obj_set_size(list, LV_PCT(100), LV_PCT(100)); lv_obj_center(list); - auto manifests = app_manifest_registry_get(); + auto manifests = getApps(); std::sort(manifests.begin(), manifests.end(), SortAppManifestByName); lv_list_add_text(list, "User"); @@ -50,7 +50,7 @@ extern const Manifest manifest = { .id = "Desktop", .name = "Desktop", .type = TypeDesktop, - .on_show = &desktop_show, + .onShow = &desktop_show, }; } // namespace diff --git a/Tactility/Source/app/display/Display.cpp b/Tactility/Source/app/display/Display.cpp index 4ab494da..b5ed4f14 100644 --- a/Tactility/Source/app/display/Display.cpp +++ b/Tactility/Source/app/display/Display.cpp @@ -67,7 +67,7 @@ static void on_orientation_set(lv_event_t* event) { } } -static void app_show(App app, lv_obj_t* parent) { +static void app_show(App& app, lv_obj_t* parent) { lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lvgl::toolbar_create(parent, app); @@ -89,7 +89,7 @@ static void app_show(App app, lv_obj_t* parent) { lv_obj_set_width(brightness_slider, LV_PCT(50)); lv_obj_align(brightness_slider, LV_ALIGN_TOP_RIGHT, -8, 0); lv_slider_set_range(brightness_slider, 0, 255); - lv_obj_add_event_cb(brightness_slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_add_event_cb(brightness_slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, nullptr); const Configuration* config = getConfiguration(); hal::SetBacklightDuty set_backlight_duty = config->hardware->display.setBacklightDuty; @@ -115,7 +115,7 @@ static void app_show(App app, lv_obj_t* parent) { lv_dropdown_set_selected(orientation_dropdown, orientation_selected); } -static void app_hide(TT_UNUSED App app) { +static void app_hide(TT_UNUSED App& app) { if (backlight_duty_set) { preferences_set_backlight_duty(backlight_duty); } @@ -126,10 +126,10 @@ extern const Manifest manifest = { .name = "Display", .icon = TT_ASSETS_APP_ICON_DISPLAY_SETTINGS, .type = TypeSettings, - .on_start = nullptr, - .on_stop = nullptr, - .on_show = &app_show, - .on_hide = &app_hide + .onStart = nullptr, + .onStop = nullptr, + .onShow = &app_show, + .onHide = &app_hide }; } // namespace diff --git a/Tactility/Source/app/files/Files.cpp b/Tactility/Source/app/files/Files.cpp index 46c4d67b..4980b523 100644 --- a/Tactility/Source/app/files/Files.cpp +++ b/Tactility/Source/app/files/Files.cpp @@ -180,8 +180,8 @@ static void update_views(Data* data) { // region Lifecycle -static void on_show(App app, lv_obj_t* parent) { - auto* data = static_cast(tt_app_get_data(app)); +static void on_show(App& app, lv_obj_t* parent) { + auto* data = static_cast(app.getData()); lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); @@ -196,7 +196,7 @@ static void on_show(App app, lv_obj_t* parent) { update_views(data); } -static void on_start(App app) { +static void on_start(App& app) { auto* data = data_alloc(); // PC platform is bound to current work directory because of the LVGL file system mapping if (get_platform() == PlatformPc) { @@ -211,11 +211,11 @@ static void on_start(App app) { data_set_entries_for_path(data, "/"); } - tt_app_set_data(app, data); + app.setData(data); } -static void on_stop(App app) { - auto* data = static_cast(tt_app_get_data(app)); +static void on_stop(App& app) { + auto* data = static_cast(app.getData()); data_free(data); } @@ -226,9 +226,9 @@ extern const Manifest manifest = { .name = "Files", .icon = TT_ASSETS_APP_ICON_FILES, .type = TypeSystem, - .on_start = &on_start, - .on_stop = &on_stop, - .on_show = &on_show, + .onStart = &on_start, + .onStop = &on_stop, + .onShow = &on_show, }; } // namespace diff --git a/Tactility/Source/app/gpio/Gpio.cpp b/Tactility/Source/app/gpio/Gpio.cpp index d9051953..e44c455f 100644 --- a/Tactility/Source/app/gpio/Gpio.cpp +++ b/Tactility/Source/app/gpio/Gpio.cpp @@ -120,8 +120,8 @@ static void task_stop(Gpio* gpio) { // region App lifecycle -static void app_show(App app, lv_obj_t* parent) { - auto* gpio = static_cast(tt_app_get_data(app)); +static void app_show(App& app, lv_obj_t* parent) { + auto* gpio = (Gpio*)app.getData(); lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lv_obj_t* toolbar = lvgl::toolbar_create(parent, app); @@ -176,27 +176,26 @@ static void app_show(App app, lv_obj_t* parent) { task_start(gpio); } -static void on_hide(App app) { - auto* gpio = static_cast(tt_app_get_data(app)); +static void on_hide(App& app) { + auto* gpio = (Gpio*)app.getData(); task_stop(gpio); } -static void on_start(App app) { - auto* gpio = static_cast(malloc(sizeof(Gpio))); - *gpio = (Gpio) { +static void on_start(App& app) { + auto* gpio = new Gpio { .lv_pins = { nullptr }, .pin_states = { 0 }, .thread = nullptr, .mutex = tt_mutex_alloc(MutexTypeNormal), .thread_interrupted = true, }; - tt_app_set_data(app, gpio); + app.setData(gpio); } -static void on_stop(App app) { - auto* gpio = static_cast(tt_app_get_data(app)); +static void on_stop(App& app) { + auto* gpio = (Gpio*)app.getData(); tt_mutex_free(gpio->mutex); - free(gpio); + delete gpio; } // endregion App lifecycle @@ -205,10 +204,10 @@ extern const Manifest manifest = { .id = "Gpio", .name = "GPIO", .type = TypeSystem, - .on_start = &on_start, - .on_stop = &on_stop, - .on_show = &app_show, - .on_hide = &on_hide + .onStart = &on_start, + .onStop = &on_stop, + .onShow = &app_show, + .onHide = &on_hide }; } // namespace diff --git a/Tactility/Source/app/i2csettings/I2cSettings.cpp b/Tactility/Source/app/i2csettings/I2cSettings.cpp index 20b715ca..f8e8cadb 100644 --- a/Tactility/Source/app/i2csettings/I2cSettings.cpp +++ b/Tactility/Source/app/i2csettings/I2cSettings.cpp @@ -69,7 +69,7 @@ static void show(lv_obj_t* parent, const hal::i2c::Configuration& configuration) } } -static void on_show(App app, lv_obj_t* parent) { +static void on_show(App& app, lv_obj_t* parent) { lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lvgl::toolbar_create(parent, app); @@ -90,7 +90,7 @@ extern const Manifest manifest = { .name = "I2C", .icon = TT_ASSETS_APP_ICON_I2C_SETTINGS, .type = TypeSettings, - .on_show = &on_show + .onShow = &on_show }; } // namespace diff --git a/Tactility/Source/app/imageviewer/ImageViewer.cpp b/Tactility/Source/app/imageviewer/ImageViewer.cpp index 07996ebe..595806bf 100644 --- a/Tactility/Source/app/imageviewer/ImageViewer.cpp +++ b/Tactility/Source/app/imageviewer/ImageViewer.cpp @@ -8,7 +8,7 @@ namespace tt::app::imageviewer { #define TAG "image_viewer" -static void on_show(App app, lv_obj_t* parent) { +static void on_show(App& app, lv_obj_t* parent) { lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lvgl::toolbar_create(parent, app); @@ -22,7 +22,7 @@ static void on_show(App app, lv_obj_t* parent) { lv_obj_t* image = lv_img_create(wrapper); lv_obj_align(image, LV_ALIGN_CENTER, 0, 0); - const Bundle& bundle = tt_app_get_parameters(app); + const Bundle& bundle = app.getParameters(); std::string file_argument; if (bundle.optString(IMAGE_VIEWER_FILE_ARGUMENT, file_argument)) { std::string prefixed_path = "A:" + file_argument; @@ -35,7 +35,7 @@ extern const Manifest manifest = { .id = "ImageViewer", .name = "Image Viewer", .type = TypeHidden, - .on_show = &on_show + .onShow = &on_show }; } // namespace diff --git a/Tactility/Source/app/power/Power.cpp b/Tactility/Source/app/power/Power.cpp index d334fea8..32459074 100644 --- a/Tactility/Source/app/power/Power.cpp +++ b/Tactility/Source/app/power/Power.cpp @@ -53,7 +53,7 @@ static void on_power_enabled_change(lv_event_t* event) { } } -static void app_show(App app, lv_obj_t* parent) { +static void app_show(App& app, lv_obj_t* parent) { lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lvgl::toolbar_create(parent, app); @@ -64,7 +64,7 @@ static void app_show(App app, lv_obj_t* parent) { lv_obj_set_flex_grow(wrapper, 1); lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN); - auto* data = static_cast(tt_app_get_data(app)); + auto* data = static_cast(app.getData()); // Top row: enable/disable lv_obj_t* switch_container = lv_obj_create(wrapper); @@ -90,21 +90,21 @@ static void app_show(App app, lv_obj_t* parent) { data->update_timer->start(ms_to_ticks(1000)); } -static void app_hide(TT_UNUSED App app) { - auto* data = static_cast(tt_app_get_data(app)); +static void app_hide(TT_UNUSED App& app) { + auto* data = static_cast(app.getData()); data->update_timer->stop(); } -static void app_start(App app) { +static void app_start(App& app) { auto* data = new AppData(); data->update_timer = new Timer(Timer::TypePeriodic, &app_update_ui, data); data->power = getConfiguration()->hardware->power; assert(data->power != nullptr); // The Power app only shows up on supported devices - tt_app_set_data(app, data); + app.setData(data); } -static void app_stop(App app) { - auto* data = static_cast(tt_app_get_data(app)); +static void app_stop(App& app) { + auto* data = static_cast(app.getData()); delete data->update_timer; delete data; } @@ -114,10 +114,10 @@ extern const Manifest manifest = { .name = "Power", .icon = TT_ASSETS_APP_ICON_POWER_SETTINGS, .type = TypeSettings, - .on_start = &app_start, - .on_stop = &app_stop, - .on_show = &app_show, - .on_hide = &app_hide + .onStart = &app_start, + .onStop = &app_stop, + .onShow = &app_show, + .onHide = &app_hide }; } // namespace diff --git a/Tactility/Source/app/screenshot/Screenshot.cpp b/Tactility/Source/app/screenshot/Screenshot.cpp index f3e3a870..97e72eab 100644 --- a/Tactility/Source/app/screenshot/Screenshot.cpp +++ b/Tactility/Source/app/screenshot/Screenshot.cpp @@ -2,18 +2,18 @@ namespace tt::app::screenshot { -static void on_show(App app, lv_obj_t* parent) { - auto* ui = static_cast(tt_app_get_data(app)); +static void on_show(App& app, lv_obj_t* parent) { + auto* ui = static_cast(app.getData()); create_ui(app, ui, parent); } -static void on_start(App app) { +static void on_start(App& app) { auto* ui = static_cast(malloc(sizeof(ScreenshotUi))); - tt_app_set_data(app, ui); + app.setData(ui); } -static void on_stop(App app) { - auto* ui = static_cast(tt_app_get_data(app)); +static void on_stop(App& app) { + auto* ui = static_cast(app.getData()); free(ui); } @@ -22,9 +22,9 @@ extern const Manifest manifest = { .name = "_Screenshot", // So it gets put at the bottom of the desktop and becomes less visible on small screen devices .icon = LV_SYMBOL_IMAGE, .type = TypeSystem, - .on_start = &on_start, - .on_stop = &on_stop, - .on_show = &on_show, + .onStart = &on_start, + .onStop = &on_stop, + .onShow = &on_show, }; } // namespace diff --git a/Tactility/Source/app/screenshot/ScreenshotUi.cpp b/Tactility/Source/app/screenshot/ScreenshotUi.cpp index 3cb7e4fe..a04af99b 100644 --- a/Tactility/Source/app/screenshot/ScreenshotUi.cpp +++ b/Tactility/Source/app/screenshot/ScreenshotUi.cpp @@ -153,7 +153,7 @@ static void create_timer_settings_ui(ScreenshotUi* ui, lv_obj_t* parent) { lv_label_set_text(delay_unit_label, "seconds"); } -void create_ui(App app, ScreenshotUi* ui, lv_obj_t* parent) { +void create_ui(const App& app, ScreenshotUi* ui, lv_obj_t* parent) { lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lv_obj_t* toolbar = lvgl::toolbar_create(parent, app); lv_obj_align(toolbar, LV_ALIGN_TOP_MID, 0, 0); diff --git a/Tactility/Source/app/screenshot/ScreenshotUi.h b/Tactility/Source/app/screenshot/ScreenshotUi.h index 4a11ecc3..282f6536 100644 --- a/Tactility/Source/app/screenshot/ScreenshotUi.h +++ b/Tactility/Source/app/screenshot/ScreenshotUi.h @@ -13,6 +13,6 @@ typedef struct { lv_obj_t* delay_textarea; } ScreenshotUi; -void create_ui(App app, ScreenshotUi* ui, lv_obj_t* parent); +void create_ui(const App& app, ScreenshotUi* ui, lv_obj_t* parent); } // namespace diff --git a/Tactility/Source/app/settings/Settings.cpp b/Tactility/Source/app/settings/Settings.cpp index 9449a6d3..3c345ce8 100644 --- a/Tactility/Source/app/settings/Settings.cpp +++ b/Tactility/Source/app/settings/Settings.cpp @@ -24,7 +24,7 @@ static void create_app_widget(const Manifest* manifest, void* parent) { lv_obj_add_event_cb(btn, &on_app_pressed, LV_EVENT_CLICKED, (void*)manifest); } -static void on_show(App app, lv_obj_t* parent) { +static void on_show(App& app, lv_obj_t* parent) { lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lvgl::toolbar_create(parent, app); @@ -33,7 +33,7 @@ static void on_show(App app, lv_obj_t* parent) { lv_obj_set_width(list, LV_PCT(100)); lv_obj_set_flex_grow(list, 1); - auto manifests = app_manifest_registry_get(); + auto manifests = getApps(); std::sort(manifests.begin(), manifests.end(), SortAppManifestByName); for (const auto& manifest: manifests) { if (manifest->type == TypeSettings) { @@ -47,10 +47,10 @@ extern const Manifest manifest = { .name = "Settings", .icon = TT_ASSETS_APP_ICON_SETTINGS, .type = TypeSystem, - .on_start = nullptr, - .on_stop = nullptr, - .on_show = &on_show, - .on_hide = nullptr + .onStart = nullptr, + .onStop = nullptr, + .onShow = &on_show, + .onHide = nullptr }; } // namespace diff --git a/Tactility/Source/app/systeminfo/SystemInfo.cpp b/Tactility/Source/app/systeminfo/SystemInfo.cpp index b0f91827..e7a32b64 100644 --- a/Tactility/Source/app/systeminfo/SystemInfo.cpp +++ b/Tactility/Source/app/systeminfo/SystemInfo.cpp @@ -65,7 +65,7 @@ static void add_memory_bar(lv_obj_t* parent, const char* label, size_t used, siz lv_obj_set_style_text_align(bottom_label, LV_TEXT_ALIGN_RIGHT, 0); } -static void on_show(App app, lv_obj_t* parent) { +static void on_show(App& app, lv_obj_t* parent) { lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lvgl::toolbar_create(parent, app); @@ -106,9 +106,9 @@ extern const Manifest manifest = { .name = "System Info", .icon = TT_ASSETS_APP_ICON_SYSTEM_INFO, .type = TypeSystem, - .on_start = nullptr, - .on_stop = nullptr, - .on_show = &on_show + .onStart = nullptr, + .onStop = nullptr, + .onShow = &on_show }; } // namespace diff --git a/Tactility/Source/app/textviewer/TextViewer.cpp b/Tactility/Source/app/textviewer/TextViewer.cpp index b8e5edf4..f21a46f6 100644 --- a/Tactility/Source/app/textviewer/TextViewer.cpp +++ b/Tactility/Source/app/textviewer/TextViewer.cpp @@ -9,7 +9,7 @@ namespace tt::app::textviewer { -static void on_show(App app, lv_obj_t* parent) { +static void on_show(App& app, lv_obj_t* parent) { lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lvgl::toolbar_create(parent, app); @@ -22,7 +22,7 @@ static void on_show(App app, lv_obj_t* parent) { lv_obj_t* label = lv_label_create(wrapper); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); - const Bundle& bundle = tt_app_get_parameters(app); + const Bundle& bundle = app.getParameters(); std::string file_argument; if (bundle.optString(TEXT_VIEWER_FILE_ARGUMENT, file_argument)) { std::string prefixed_path = "A:" + file_argument; @@ -35,7 +35,7 @@ extern const Manifest manifest = { .id = "TextViewer", .name = "Text Viewer", .type = TypeHidden, - .on_show = &on_show + .onShow = &on_show }; } // namespace diff --git a/Tactility/Source/app/wificonnect/WifiConnect.cpp b/Tactility/Source/app/wificonnect/WifiConnect.cpp index 28d542c7..def0bf56 100644 --- a/Tactility/Source/app/wificonnect/WifiConnect.cpp +++ b/Tactility/Source/app/wificonnect/WifiConnect.cpp @@ -101,8 +101,8 @@ static void event_callback(const void* message, void* context) { request_view_update(wifi); } -static void app_show(App app, lv_obj_t* parent) { - auto* wifi = static_cast(tt_app_get_data(app)); +static void app_show(App& app, lv_obj_t* parent) { + auto* wifi = static_cast(app.getData()); lock(wifi); wifi->view_enabled = true; @@ -111,8 +111,8 @@ static void app_show(App app, lv_obj_t* parent) { unlock(wifi); } -static void app_hide(App app) { - auto* wifi = static_cast(tt_app_get_data(app)); +static void app_hide(App& app) { + auto* wifi = static_cast(app.getData()); // No need to lock view, as this is called from within Gui's LVGL context view_destroy(&wifi->view); lock(wifi); @@ -120,16 +120,15 @@ static void app_hide(App app) { unlock(wifi); } -static void app_start(App app) { +static void app_start(App& app) { auto* wifi_connect = wifi_connect_alloc(); - tt_app_set_data(app, wifi_connect); + app.setData(wifi_connect); } -static void app_stop(App app) { - auto* wifi = static_cast(tt_app_get_data(app)); +static void app_stop(App& app) { + auto* wifi = static_cast(app.getData()); tt_assert(wifi != nullptr); wifi_connect_free(wifi); - tt_app_set_data(app, nullptr); } extern const Manifest manifest = { @@ -137,10 +136,10 @@ extern const Manifest manifest = { .name = "Wi-Fi Connect", .icon = LV_SYMBOL_WIFI, .type = TypeSettings, - .on_start = &app_start, - .on_stop = &app_stop, - .on_show = &app_show, - .on_hide = &app_hide + .onStart = &app_start, + .onStop = &app_stop, + .onShow = &app_show, + .onHide = &app_hide }; } // namespace diff --git a/Tactility/Source/app/wificonnect/WifiConnectView.cpp b/Tactility/Source/app/wificonnect/WifiConnectView.cpp index 778898dc..c68374cb 100644 --- a/Tactility/Source/app/wificonnect/WifiConnectView.cpp +++ b/Tactility/Source/app/wificonnect/WifiConnectView.cpp @@ -113,7 +113,7 @@ void view_create_bottom_buttons(WifiConnect* wifi, lv_obj_t* parent) { } // TODO: Standardize dialogs -void view_create(App app, void* wifi, lv_obj_t* parent) { +void view_create(const App& app, void* wifi, lv_obj_t* parent) { WifiConnect* wifi_connect = (WifiConnect*)wifi; WifiConnectView* view = &wifi_connect->view; @@ -195,7 +195,7 @@ void view_create(App app, void* wifi, lv_obj_t* parent) { service::gui::keyboard_add_textarea(view->password_textarea); // Init from app parameters - const Bundle& bundle = tt_app_get_parameters(app); + const Bundle& bundle = app.getParameters(); std::string ssid; if (bundle.optString(WIFI_CONNECT_PARAM_SSID, ssid)) { lv_textarea_set_text(view->ssid_textarea, ssid.c_str()); diff --git a/Tactility/Source/app/wificonnect/WifiConnectView.h b/Tactility/Source/app/wificonnect/WifiConnectView.h index 84ad8e2d..c2b6952a 100644 --- a/Tactility/Source/app/wificonnect/WifiConnectView.h +++ b/Tactility/Source/app/wificonnect/WifiConnectView.h @@ -20,7 +20,7 @@ typedef struct { lv_group_t* group; } WifiConnectView; -void view_create(App app, void* wifi, lv_obj_t* parent); +void view_create(const App& app, void* wifi, lv_obj_t* parent); void view_update(WifiConnectView* view, WifiConnectBindings* bindings, WifiConnectState* state); void view_destroy(WifiConnectView* view); diff --git a/Tactility/Source/app/wifimanage/WifiManage.cpp b/Tactility/Source/app/wifimanage/WifiManage.cpp index a3feccc8..d52fadf2 100644 --- a/Tactility/Source/app/wifimanage/WifiManage.cpp +++ b/Tactility/Source/app/wifimanage/WifiManage.cpp @@ -116,8 +116,8 @@ static void wifi_manage_event_callback(const void* message, void* context) { request_view_update(wifi); } -static void app_show(App app, lv_obj_t* parent) { - auto* wifi = (WifiManage*)tt_app_get_data(app); +static void app_show(App& app, lv_obj_t* parent) { + auto* wifi = (WifiManage*)app.getData(); PubSub* wifi_pubsub = service::wifi::get_pubsub(); wifi->wifi_subscription = tt_pubsub_subscribe(wifi_pubsub, &wifi_manage_event_callback, wifi); @@ -144,8 +144,8 @@ static void app_show(App app, lv_obj_t* parent) { } } -static void app_hide(App app) { - auto* wifi = (WifiManage*)tt_app_get_data(app); +static void app_hide(App& app) { + auto* wifi = (WifiManage*)app.getData(); lock(wifi); PubSub* wifi_pubsub = service::wifi::get_pubsub(); tt_pubsub_unsubscribe(wifi_pubsub, wifi->wifi_subscription); @@ -154,16 +154,15 @@ static void app_hide(App app) { unlock(wifi); } -static void app_start(App app) { +static void app_start(App& app) { WifiManage* wifi = wifi_manage_alloc(); - tt_app_set_data(app, wifi); + app.setData(wifi); } -static void app_stop(App app) { - auto* wifi = (WifiManage*)tt_app_get_data(app); +static void app_stop(App& app) { + auto* wifi = (WifiManage*)app.getData(); tt_assert(wifi != nullptr); wifi_manage_free(wifi); - tt_app_set_data(app, nullptr); } extern const Manifest manifest = { @@ -171,10 +170,10 @@ extern const Manifest manifest = { .name = "Wi-Fi", .icon = LV_SYMBOL_WIFI, .type = TypeSettings, - .on_start = &app_start, - .on_stop = &app_stop, - .on_show = &app_show, - .on_hide = &app_hide + .onStart = &app_start, + .onStop = &app_stop, + .onShow = &app_show, + .onHide = &app_hide }; } // namespace diff --git a/Tactility/Source/app/wifimanage/WifiManageView.cpp b/Tactility/Source/app/wifimanage/WifiManageView.cpp index 94a6e7ca..e72409bb 100644 --- a/Tactility/Source/app/wifimanage/WifiManageView.cpp +++ b/Tactility/Source/app/wifimanage/WifiManageView.cpp @@ -129,7 +129,7 @@ static void update_connected_ap(WifiManageView* view, WifiManageState* state, TT // region Main -void view_create(App app, WifiManageView* view, WifiManageBindings* bindings, lv_obj_t* parent) { +void view_create(const App& app, WifiManageView* view, WifiManageBindings* bindings, lv_obj_t* parent) { view->root = parent; lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); diff --git a/Tactility/Source/app/wifimanage/WifiManageView.h b/Tactility/Source/app/wifimanage/WifiManageView.h index 7c64d067..08ae4712 100644 --- a/Tactility/Source/app/wifimanage/WifiManageView.h +++ b/Tactility/Source/app/wifimanage/WifiManageView.h @@ -17,7 +17,7 @@ typedef struct { lv_obj_t* connected_ap_label; } WifiManageView; -void view_create(App app, WifiManageView* view, WifiManageBindings* bindings, lv_obj_t* parent); +void view_create(const App& app, WifiManageView* view, WifiManageBindings* bindings, lv_obj_t* parent); void view_update(WifiManageView* view, WifiManageBindings* bindings, WifiManageState* state); } // namespace diff --git a/Tactility/Source/lvgl/Toolbar.cpp b/Tactility/Source/lvgl/Toolbar.cpp index 17c15ae1..08b43226 100644 --- a/Tactility/Source/lvgl/Toolbar.cpp +++ b/Tactility/Source/lvgl/Toolbar.cpp @@ -86,9 +86,8 @@ lv_obj_t* toolbar_create(lv_obj_t* parent, const std::string& title) { return obj; } -lv_obj_t* toolbar_create(lv_obj_t* parent, app::App app) { - const app::Manifest& manifest = app::tt_app_get_manifest(app); - lv_obj_t* toolbar = toolbar_create(parent, manifest.name); +lv_obj_t* toolbar_create(lv_obj_t* parent, const app::App& app) { + lv_obj_t* toolbar = toolbar_create(parent, app.getManifest().name); toolbar_set_nav_action(toolbar, LV_SYMBOL_CLOSE, &stop_app, nullptr); return toolbar; } diff --git a/Tactility/Source/lvgl/Toolbar.h b/Tactility/Source/lvgl/Toolbar.h index 15457ce3..d3396ab5 100644 --- a/Tactility/Source/lvgl/Toolbar.h +++ b/Tactility/Source/lvgl/Toolbar.h @@ -19,7 +19,7 @@ typedef struct { } ToolbarAction; lv_obj_t* toolbar_create(lv_obj_t* parent, const std::string& title); -lv_obj_t* toolbar_create(lv_obj_t* parent, app::App app); +lv_obj_t* toolbar_create(lv_obj_t* parent, const app::App& app); void toolbar_set_title(lv_obj_t* obj, const std::string& title); void toolbar_set_nav_action(lv_obj_t* obj, const char* icon, lv_event_cb_t callback, void* user_data); uint8_t toolbar_add_action(lv_obj_t* obj, const char* icon, const char* text, lv_event_cb_t callback, void* user_data); diff --git a/Tactility/Source/service/gui/Gui.cpp b/Tactility/Source/service/gui/Gui.cpp index 7dbb60b9..b5fec158 100644 --- a/Tactility/Source/service/gui/Gui.cpp +++ b/Tactility/Source/service/gui/Gui.cpp @@ -20,13 +20,12 @@ static int32_t gui_main(void*); Gui* gui = nullptr; -typedef void (*PubSubCallback)(const void* message, void* context); void loader_callback(const void* message, TT_UNUSED void* context) { auto* event = static_cast(message); if (event->type == loader::LoaderEventTypeApplicationShowing) { - app::App* app = event->app_showing.app; - const app::Manifest& app_manifest = app::tt_app_get_manifest(app); - show_app(app, app_manifest.on_show, app_manifest.on_hide); + app::App& app = event->app_showing.app; + const app::Manifest& app_manifest = app.getManifest(); + show_app(app, app_manifest.onShow, app_manifest.onHide); } else if (event->type == loader::LoaderEventTypeApplicationHiding) { hide_app(); } @@ -83,7 +82,7 @@ void request_draw() { thread_flags_set(thread_id, GUI_THREAD_FLAG_DRAW); } -void show_app(app::App app, ViewPortShowCallback on_show, ViewPortHideCallback on_hide) { +void show_app(app::App& app, ViewPortShowCallback on_show, ViewPortHideCallback on_hide) { lock(); tt_check(gui->app_view_port == nullptr); gui->app_view_port = view_port_alloc(app, on_show, on_hide); diff --git a/Tactility/Source/service/gui/Gui.h b/Tactility/Source/service/gui/Gui.h index 56bd53c4..6107969b 100644 --- a/Tactility/Source/service/gui/Gui.h +++ b/Tactility/Source/service/gui/Gui.h @@ -14,7 +14,7 @@ typedef struct Gui Gui; * @param on_show * @param on_hide */ -void show_app(app::App app, ViewPortShowCallback on_show, ViewPortHideCallback on_hide); +void show_app(app::App& app, ViewPortShowCallback on_show, ViewPortHideCallback on_hide); /** * Hide the current app's viewport. diff --git a/Tactility/Source/service/gui/GuiDraw.cpp b/Tactility/Source/service/gui/GuiDraw.cpp index a3def7c7..d45bd4da 100644 --- a/Tactility/Source/service/gui/GuiDraw.cpp +++ b/Tactility/Source/service/gui/GuiDraw.cpp @@ -9,7 +9,7 @@ namespace tt::service::gui { #define TAG "gui" -static lv_obj_t* create_app_views(Gui* gui, lv_obj_t* parent, app::App app) { +static lv_obj_t* create_app_views(Gui* gui, lv_obj_t* parent, app::App& app) { lvgl::obj_set_style_bg_blacken(parent); lv_obj_t* vertical_container = lv_obj_create(parent); @@ -19,8 +19,8 @@ static lv_obj_t* create_app_views(Gui* gui, lv_obj_t* parent, app::App app) { lvgl::obj_set_style_bg_blacken(vertical_container); // TODO: Move statusbar into separate ViewPort - app::Flags flags = app::tt_app_get_flags(app); - if (flags.show_statusbar) { + app::Flags flags = app.getFlags(); + if (flags.showStatusbar) { lvgl::statusbar_create(vertical_container); } @@ -49,7 +49,7 @@ void redraw(Gui* gui) { ViewPort* view_port = gui->app_view_port; if (view_port != nullptr) { - app::App app = view_port->app; + app::App& app = view_port->app; lv_obj_t* container = create_app_views(gui, gui->lvgl_parent, app); view_port_show(view_port, container); } else { diff --git a/Tactility/Source/service/gui/ViewPort.cpp b/Tactility/Source/service/gui/ViewPort.cpp index 33ddf9d9..f45d07ab 100644 --- a/Tactility/Source/service/gui/ViewPort.cpp +++ b/Tactility/Source/service/gui/ViewPort.cpp @@ -9,35 +9,35 @@ namespace tt::service::gui { #define TAG "viewport" ViewPort* view_port_alloc( - app::App app, + app::App& app, ViewPortShowCallback on_show, ViewPortHideCallback on_hide ) { - auto* view_port = static_cast(malloc(sizeof(ViewPort))); - view_port->app = app; - view_port->on_show = on_show; - view_port->on_hide = on_hide; - return view_port; + return new ViewPort( + app, + on_show, + on_hide + ); } void view_port_free(ViewPort* view_port) { tt_assert(view_port); - free(view_port); + delete view_port; } void view_port_show(ViewPort* view_port, lv_obj_t* parent) { tt_assert(view_port); tt_assert(parent); - if (view_port->on_show) { + if (view_port->onShow) { lvgl::obj_set_style_no_padding(parent); - view_port->on_show(view_port->app, parent); + view_port->onShow(view_port->app, parent); } } void view_port_hide(ViewPort* view_port) { tt_assert(view_port); - if (view_port->on_hide) { - view_port->on_hide(view_port->app); + if (view_port->onHide) { + view_port->onHide(view_port->app); } } diff --git a/Tactility/Source/service/gui/ViewPort.h b/Tactility/Source/service/gui/ViewPort.h index c4381534..9e2cb647 100644 --- a/Tactility/Source/service/gui/ViewPort.h +++ b/Tactility/Source/service/gui/ViewPort.h @@ -8,16 +8,21 @@ namespace tt::service::gui { /** ViewPort Draw callback * @warning called from GUI thread */ -typedef void (*ViewPortShowCallback)(app::App app, lv_obj_t* parent); -typedef void (*ViewPortHideCallback)(app::App app); +typedef void (*ViewPortShowCallback)(app::App& app, lv_obj_t* parent); +typedef void (*ViewPortHideCallback)(app::App& app); // TODO: Move internally, use handle publicly -typedef struct { - app::App app; - ViewPortShowCallback on_show; - ViewPortHideCallback _Nullable on_hide; - bool app_toolbar; +typedef struct ViewPort { + app::App& app; + ViewPortShowCallback onShow; + ViewPortHideCallback _Nullable onHide; + + ViewPort( + app::App& app, + ViewPortShowCallback on_show, + ViewPortHideCallback _Nullable on_hide + ) : app(app), onShow(on_show), onHide(on_hide) {} } ViewPort; /** ViewPort allocator @@ -30,7 +35,7 @@ typedef struct { * @return ViewPort instance */ ViewPort* view_port_alloc( - app::App app, + app::App& app, ViewPortShowCallback on_show, ViewPortHideCallback on_hide ); diff --git a/Tactility/Source/service/loader/Loader.cpp b/Tactility/Source/service/loader/Loader.cpp index 00e68ddb..ac54cc7c 100644 --- a/Tactility/Source/service/loader/Loader.cpp +++ b/Tactility/Source/service/loader/Loader.cpp @@ -1,4 +1,5 @@ #include "Tactility.h" +#include #include "app/Manifest.h" #include "app/ManifestRegistry.h" #include "service/Manifest.h" @@ -39,8 +40,6 @@ static Loader* loader_alloc() { nullptr ); loader_singleton->mutex = tt_mutex_alloc(MutexTypeRecursive); - loader_singleton->app_stack_index = -1; - memset(loader_singleton->app_stack, 0, sizeof(app::App) * APP_STACK_SIZE); return loader_singleton; } @@ -100,14 +99,12 @@ void stop_app() { loader_singleton->queue.put(&message, TtWaitForever); } -app::App _Nullable get_current_app() { +app::App* _Nullable get_current_app() { tt_assert(loader_singleton); loader_lock(); - app::App app = (loader_singleton->app_stack_index >= 0) - ? loader_singleton->app_stack[loader_singleton->app_stack_index] - : nullptr; + app::AppInstance* app = loader_singleton->app_stack.top(); loader_unlock(); - return app; + return dynamic_cast(app); } PubSub* get_pubsub() { @@ -135,9 +132,9 @@ static const char* app_state_to_string(app::State state) { } } -static void app_transition_to_state(app::App app, app::State state) { - const app::Manifest& manifest = app::tt_app_get_manifest(app); - const app::State old_state = app::tt_app_get_state(app); +static void app_transition_to_state(app::AppInstance& app, app::State state) { + const app::Manifest& manifest = app.getManifest(); + const app::State old_state = app.getState(); TT_LOG_I( TAG, @@ -149,42 +146,42 @@ static void app_transition_to_state(app::App app, app::State state) { switch (state) { case app::StateInitial: - tt_app_set_state(app, app::StateInitial); + app.setState(app::StateInitial); break; case app::StateStarted: - if (manifest.on_start != nullptr) { - manifest.on_start(app); + if (manifest.onStart != nullptr) { + manifest.onStart(app); } - tt_app_set_state(app, app::StateStarted); + app.setState(app::StateStarted); break; case app::StateShowing: { LoaderEvent event_showing = { .type = LoaderEventTypeApplicationShowing, .app_showing = { - .app = static_cast(app) + .app = dynamic_cast(app) } }; tt_pubsub_publish(loader_singleton->pubsub_external, &event_showing); - tt_app_set_state(app, app::StateShowing); + app.setState(app::StateShowing); break; } case app::StateHiding: { LoaderEvent event_hiding = { .type = LoaderEventTypeApplicationHiding, .app_hiding = { - .app = static_cast(app) + .app = dynamic_cast(app) } }; tt_pubsub_publish(loader_singleton->pubsub_external, &event_hiding); - tt_app_set_state(app, app::StateHiding); + app.setState(app::StateHiding); break; } case app::StateStopped: - if (manifest.on_stop) { - manifest.on_stop(app); + if (manifest.onStop) { + manifest.onStop(app); } - app::tt_app_set_data(app, nullptr); - tt_app_set_state(app, app::StateStopped); + app.setData(nullptr); + app.setState(app::StateStopped); break; } } @@ -197,27 +194,18 @@ static LoaderStatus loader_do_start_app_with_manifest( loader_lock(); - if (loader_singleton->app_stack_index >= (APP_STACK_SIZE - 1)) { - TT_LOG_E(TAG, "failed to start app: stack limit of %d reached", APP_STACK_SIZE); - return LoaderStatusErrorInternal; - } - - int8_t previous_index = loader_singleton->app_stack_index; - loader_singleton->app_stack_index++; - - app::App app = tt_app_alloc(*manifest, bundle); - tt_check(loader_singleton->app_stack[loader_singleton->app_stack_index] == nullptr); - loader_singleton->app_stack[loader_singleton->app_stack_index] = app; - app_transition_to_state(app, app::StateInitial); - app_transition_to_state(app, app::StateStarted); + auto previous_app = !loader_singleton->app_stack.empty() ? loader_singleton->app_stack.top() : nullptr; + auto new_app = new app::AppInstance(*manifest, bundle); + loader_singleton->app_stack.push(new_app); + app_transition_to_state(*new_app, app::StateInitial); + app_transition_to_state(*new_app, app::StateStarted); // We might have to hide the previous app first - if (previous_index != -1) { - app::App previous_app = loader_singleton->app_stack[previous_index]; - app_transition_to_state(previous_app, app::StateHiding); + if (previous_app != nullptr) { + app_transition_to_state(*previous_app, app::StateHiding); } - app_transition_to_state(app, app::StateShowing); + app_transition_to_state(*new_app, app::StateShowing); loader_unlock(); @@ -227,7 +215,7 @@ static LoaderStatus loader_do_start_app_with_manifest( LoaderEvent event_external = { .type = LoaderEventTypeApplicationStarted, .app_started = { - .app = static_cast(app) + .app = dynamic_cast(*new_app) } }; tt_pubsub_publish(loader_singleton->pubsub_external, &event_external); @@ -241,7 +229,7 @@ static LoaderStatus do_start_by_id( ) { TT_LOG_I(TAG, "Start by id %s", id.c_str()); - const app::Manifest* manifest = app::app_manifest_registry_find_by_id(id); + const app::Manifest* manifest = app::findAppById(id); if (manifest == nullptr) { return LoaderStatusErrorUnknownApp; } else { @@ -253,38 +241,40 @@ static LoaderStatus do_start_by_id( static void do_stop_app() { loader_lock(); - int8_t current_app_index = loader_singleton->app_stack_index; + size_t original_stack_size = loader_singleton->app_stack.size(); - if (current_app_index == -1) { + if (original_stack_size == 0) { loader_unlock(); TT_LOG_E(TAG, "Stop app: no app running"); return; } - if (current_app_index == 0) { + if (original_stack_size == 1) { loader_unlock(); TT_LOG_E(TAG, "Stop app: can't stop root app"); return; } // Stop current app - app::App app_to_stop = loader_singleton->app_stack[current_app_index]; - const app::Manifest& manifest = app::tt_app_get_manifest(app_to_stop); - app_transition_to_state(app_to_stop, app::StateHiding); - app_transition_to_state(app_to_stop, app::StateStopped); + app::AppInstance* app_to_stop = loader_singleton->app_stack.top(); + const app::Manifest& manifest = app_to_stop->getManifest(); + app_transition_to_state(*app_to_stop, app::StateHiding); + app_transition_to_state(*app_to_stop, app::StateStopped); - app::tt_app_free(app_to_stop); - loader_singleton->app_stack[current_app_index] = nullptr; - loader_singleton->app_stack_index--; + loader_singleton->app_stack.pop(); + delete app_to_stop; #ifdef ESP_PLATFORM TT_LOG_I(TAG, "Free heap: %zu", heap_caps_get_free_size(MALLOC_CAP_INTERNAL)); #endif // Resume previous app - tt_assert(loader_singleton->app_stack[loader_singleton->app_stack_index] != nullptr); - app::App app_to_resume = loader_singleton->app_stack[loader_singleton->app_stack_index]; - app_transition_to_state(app_to_resume, app::StateShowing); + if (original_stack_size > 1) { + + } + app::AppInstance* app_to_resume = loader_singleton->app_stack.top(); + tt_assert(app_to_resume); + app_transition_to_state(*app_to_resume, app::StateShowing); loader_unlock(); @@ -294,7 +284,7 @@ static void do_stop_app() { LoaderEvent event_external = { .type = LoaderEventTypeApplicationStopped, .app_stopped = { - .manifest = &manifest + .manifest = manifest } }; tt_pubsub_publish(loader_singleton->pubsub_external, &event_external); diff --git a/Tactility/Source/service/loader/Loader.h b/Tactility/Source/service/loader/Loader.h index aad722ac..82a581a4 100644 --- a/Tactility/Source/service/loader/Loader.h +++ b/Tactility/Source/service/loader/Loader.h @@ -24,19 +24,19 @@ typedef enum { } LoaderEventType; typedef struct { - app::App* app; + app::App& app; } LoaderEventAppStarted; typedef struct { - app::App* app; + app::App& app; } LoaderEventAppShowing; typedef struct { - app::App* app; + app::App& app; } LoaderEventAppHiding; typedef struct { - const app::Manifest* manifest; + const app::Manifest& manifest; } LoaderEventAppStopped; typedef struct { @@ -63,7 +63,7 @@ LoaderStatus start_app(const std::string& id, bool blocking, const Bundle& bundl */ void stop_app(); -app::App _Nullable get_current_app(); +app::App* _Nullable get_current_app(); /** * @brief PubSub for LoaderEvent diff --git a/Tactility/Source/service/screenshot/ScreenshotTask.cpp b/Tactility/Source/service/screenshot/ScreenshotTask.cpp index af8c47f7..39e42e02 100644 --- a/Tactility/Source/service/screenshot/ScreenshotTask.cpp +++ b/Tactility/Source/service/screenshot/ScreenshotTask.cpp @@ -98,9 +98,9 @@ static int32_t screenshot_task(void* context) { break; // Interrupted loop } } else if (data->work.type == TASK_WORK_TYPE_APPS) { - app::App _Nullable app = loader::get_current_app(); + app::App* _Nullable app = loader::get_current_app(); if (app) { - const app::Manifest& manifest = app::tt_app_get_manifest(app); + const app::Manifest& manifest = app->getManifest(); if (manifest.id != last_app_id) { delay_ms(100); last_app_id = manifest.id; @@ -125,7 +125,7 @@ static int32_t screenshot_task(void* context) { static void task_start(ScreenshotTaskData* data) { task_lock(data); - tt_check(data->thread == NULL); + tt_check(data->thread == nullptr); data->thread = new Thread( "screenshot", 8192,