mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-18 10:53:17 +00:00
implemented service registry (#8)
+ implemented app and service context for data sharing
This commit is contained in:
parent
051b1548ec
commit
83e226f696
@ -8,7 +8,9 @@
|
||||
App* furi_app_alloc(const AppManifest* _Nonnull manifest) {
|
||||
App app = {
|
||||
.manifest = manifest,
|
||||
.ep_thread_args = NULL
|
||||
.context = {
|
||||
.data = NULL
|
||||
}
|
||||
};
|
||||
App* app_ptr = malloc(sizeof(App));
|
||||
return memcpy(app_ptr, &app, sizeof(App));
|
||||
@ -16,11 +18,5 @@ App* furi_app_alloc(const AppManifest* _Nonnull manifest) {
|
||||
|
||||
void furi_app_free(App* app) {
|
||||
furi_assert(app);
|
||||
|
||||
if (app->ep_thread_args) {
|
||||
free(app->ep_thread_args);
|
||||
app->ep_thread_args = NULL;
|
||||
}
|
||||
|
||||
free(app);
|
||||
}
|
||||
|
||||
@ -9,11 +9,9 @@ extern "C" {
|
||||
|
||||
typedef struct {
|
||||
const AppManifest* manifest;
|
||||
void* ep_thread_args;
|
||||
Context context;
|
||||
} App;
|
||||
|
||||
const char* furi_app_type_to_string(AppType type);
|
||||
FuriThread* furi_app_alloc_thread(App* _Nonnull app, const char* args);
|
||||
App* furi_app_alloc(const AppManifest* _Nonnull manifest);
|
||||
void furi_app_free(App* _Nonnull app);
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "context.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -15,20 +16,20 @@ typedef enum {
|
||||
AppTypeUser
|
||||
} AppType;
|
||||
|
||||
typedef void (*AppOnStart)(void _Nonnull* parameter);
|
||||
typedef void (*AppOnStop)();
|
||||
typedef void (*AppOnShow)(lv_obj_t* parent, void* context);
|
||||
typedef void (*AppOnStart)(Context* context);
|
||||
typedef void (*AppOnStop)(Context* context);
|
||||
typedef void (*AppOnShow)(Context* context, lv_obj_t* parent);
|
||||
|
||||
typedef struct {
|
||||
/**
|
||||
* The identifier by which the app is launched by the system and other apps.
|
||||
*/
|
||||
const char* _Nonnull id;
|
||||
const char* id;
|
||||
|
||||
/**
|
||||
* The user-readable name of the app. Used in UI.
|
||||
*/
|
||||
const char* _Nonnull name;
|
||||
const char* name;
|
||||
|
||||
/**
|
||||
* Optional icon.
|
||||
|
||||
11
components/furi/src/context.h
Normal file
11
components/furi/src/context.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
/** 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* data;
|
||||
} Context;
|
||||
@ -1,7 +1,9 @@
|
||||
#include "furi.h"
|
||||
|
||||
#include "app_manifest_registry.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "service_registry.h"
|
||||
|
||||
#define TAG "furi"
|
||||
|
||||
@ -22,6 +24,7 @@ void furi_init() {
|
||||
NVIC_SetPriority(SVCall_IRQn, 0U);
|
||||
#endif
|
||||
|
||||
service_registry_init();
|
||||
app_manifest_registry_init();
|
||||
FURI_LOG_I(TAG, "init complete");
|
||||
}
|
||||
|
||||
21
components/furi/src/service.c
Normal file
21
components/furi/src/service.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include "service_i.h"
|
||||
#include "furi_core.h"
|
||||
#include "log.h"
|
||||
|
||||
#define TAG "service"
|
||||
|
||||
Service* furi_service_alloc(const ServiceManifest* _Nonnull manifest) {
|
||||
Service app = {
|
||||
.manifest = manifest,
|
||||
.context = {
|
||||
.data = NULL
|
||||
}
|
||||
};
|
||||
Service* app_ptr = malloc(sizeof(Service));
|
||||
return memcpy(app_ptr, &app, sizeof(Service));
|
||||
}
|
||||
|
||||
void furi_service_free(Service* app) {
|
||||
furi_assert(app);
|
||||
free(app);
|
||||
}
|
||||
12
components/furi/src/service_i.h
Normal file
12
components/furi/src/service_i.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "service_manifest.h"
|
||||
#include "context.h"
|
||||
|
||||
typedef struct {
|
||||
const ServiceManifest* manifest;
|
||||
Context context;
|
||||
} Service;
|
||||
|
||||
Service* furi_service_alloc(const ServiceManifest* _Nonnull manifest);
|
||||
void furi_service_free(Service* _Nonnull service);
|
||||
@ -1,13 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include "context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*ServiceOnStart)(void _Nonnull* parameter);
|
||||
typedef void (*ServiceOnStop)();
|
||||
typedef void (*ServiceOnStart)(Context* context);
|
||||
typedef void (*ServiceOnStop)(Context* context);
|
||||
|
||||
typedef struct {
|
||||
/**
|
||||
|
||||
136
components/furi/src/service_registry.c
Normal file
136
components/furi/src/service_registry.c
Normal file
@ -0,0 +1,136 @@
|
||||
#include "service_registry.h"
|
||||
|
||||
#include "furi_core.h"
|
||||
#include "m-dict.h"
|
||||
#include "m_cstr_dup.h"
|
||||
#include "mutex.h"
|
||||
#include "service_i.h"
|
||||
|
||||
#define TAG "service_registry"
|
||||
|
||||
DICT_DEF2(ServiceManifestDict, const char*, M_CSTR_DUP_OPLIST, const ServiceManifest*, M_PTR_OPLIST)
|
||||
DICT_DEF2(ServiceInstanceDict, const char*, M_CSTR_DUP_OPLIST, const Service*, M_PTR_OPLIST)
|
||||
|
||||
#define APP_REGISTRY_FOR_EACH(manifest_var_name, code_to_execute) \
|
||||
{ \
|
||||
service_registry_manifest_lock(); \
|
||||
ServiceManifestDict_it_t it; \
|
||||
for (ServiceManifestDict_it(it, service_manifest_dict); !ServiceManifestDict_end_p(it); ServiceManifestDict_next(it)) { \
|
||||
const ServiceManifest*(manifest_var_name) = ServiceManifestDict_cref(it)->value; \
|
||||
code_to_execute; \
|
||||
} \
|
||||
service_registry_manifest_unlock(); \
|
||||
}
|
||||
|
||||
ServiceManifestDict_t service_manifest_dict;
|
||||
ServiceInstanceDict_t service_instance_dict;
|
||||
FuriMutex* manifest_mutex = NULL;
|
||||
FuriMutex* instance_mutex = NULL;
|
||||
|
||||
void service_registry_init() {
|
||||
furi_assert(manifest_mutex == NULL);
|
||||
manifest_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
ServiceManifestDict_init(service_manifest_dict);
|
||||
|
||||
furi_assert(instance_mutex == NULL);
|
||||
instance_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
ServiceInstanceDict_init(service_instance_dict);
|
||||
}
|
||||
|
||||
void service_registry_instance_lock() {
|
||||
furi_assert(instance_mutex != NULL);
|
||||
furi_mutex_acquire(instance_mutex, FuriWaitForever);
|
||||
}
|
||||
|
||||
void service_registry_instance_unlock() {
|
||||
furi_assert(instance_mutex != NULL);
|
||||
furi_mutex_release(instance_mutex);
|
||||
}
|
||||
|
||||
void service_registry_manifest_lock() {
|
||||
furi_assert(manifest_mutex != NULL);
|
||||
furi_mutex_acquire(manifest_mutex, FuriWaitForever);
|
||||
}
|
||||
|
||||
void service_registry_manifest_unlock() {
|
||||
furi_assert(manifest_mutex != NULL);
|
||||
furi_mutex_release(manifest_mutex);
|
||||
}
|
||||
void service_registry_add(const ServiceManifest _Nonnull* manifest) {
|
||||
FURI_LOG_I(TAG, "adding %s", manifest->id);
|
||||
|
||||
service_registry_manifest_lock();
|
||||
ServiceManifestDict_set_at(service_manifest_dict, manifest->id, manifest);
|
||||
service_registry_manifest_unlock();
|
||||
}
|
||||
|
||||
void service_registry_remove(const ServiceManifest _Nonnull* manifest) {
|
||||
FURI_LOG_I(TAG, "removing %s", manifest->id);
|
||||
service_registry_manifest_lock();
|
||||
ServiceManifestDict_erase(service_manifest_dict, manifest->id);
|
||||
service_registry_manifest_unlock();
|
||||
}
|
||||
|
||||
const ServiceManifest* _Nullable service_registry_find_manifest_by_id(const char* id) {
|
||||
service_registry_manifest_lock();
|
||||
const ServiceManifest** _Nullable manifest = ServiceManifestDict_get(service_manifest_dict, id);
|
||||
service_registry_manifest_unlock();
|
||||
return (manifest != NULL) ? *manifest : NULL;
|
||||
}
|
||||
|
||||
Service* _Nullable service_registry_find_instance_by_id(const char* id) {
|
||||
service_registry_instance_lock();
|
||||
const Service** _Nullable service_ptr = ServiceInstanceDict_get(service_instance_dict, id);
|
||||
if (service_ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
Service* service = (Service*) *service_ptr;
|
||||
service_registry_instance_unlock();
|
||||
return service;
|
||||
}
|
||||
|
||||
void service_registry_for_each_manifest(ServiceManifestCallback callback, void* _Nullable context) {
|
||||
APP_REGISTRY_FOR_EACH(manifest, {
|
||||
callback(manifest, context);
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: return proper error/status instead of BOOL
|
||||
bool service_registry_start(const char* service_id) {
|
||||
FURI_LOG_I(TAG, "starting %s", service_id);
|
||||
const ServiceManifest* manifest = service_registry_find_manifest_by_id(service_id);
|
||||
if (manifest == NULL) {
|
||||
FURI_LOG_I(TAG, "manifest not found for %s", service_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
Service* service = furi_service_alloc(manifest);
|
||||
service->manifest->on_start(&service->context);
|
||||
|
||||
service_registry_instance_lock();
|
||||
ServiceInstanceDict_set_at(service_instance_dict, manifest->id, service);
|
||||
service_registry_instance_unlock();
|
||||
FURI_LOG_I(TAG, "started %s", service_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool service_registry_stop(const char* service_id) {
|
||||
FURI_LOG_I(TAG, "stopping %s", service_id);
|
||||
Service* service = service_registry_find_instance_by_id(service_id);
|
||||
if (service == NULL) {
|
||||
FURI_LOG_I(TAG, "service not running: %s", service_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
service->manifest->on_stop(&service->context);
|
||||
furi_service_free(service);
|
||||
|
||||
service_registry_instance_lock();
|
||||
ServiceInstanceDict_erase(service_instance_dict, service_id);
|
||||
service_registry_instance_unlock();
|
||||
|
||||
FURI_LOG_I(TAG, "stopped %s", service_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
25
components/furi/src/service_registry.h
Normal file
25
components/furi/src/service_registry.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "service_manifest.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef void (*ServiceManifestCallback)(const ServiceManifest*, void* context);
|
||||
|
||||
void service_registry_init();
|
||||
|
||||
void service_registry_add(const ServiceManifest* manifest);
|
||||
void service_registry_remove(const ServiceManifest* manifest);
|
||||
const ServiceManifest _Nullable* service_registry_find_manifest_by_id(const char* id);
|
||||
void service_registry_for_each_manifest(ServiceManifestCallback callback, void* _Nullable context);
|
||||
|
||||
bool service_registry_start(const char* service_id);
|
||||
bool service_registry_stop(const char* service_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -5,8 +5,19 @@ idf_component_register(
|
||||
"src/services/loader"
|
||||
"src/services/gui"
|
||||
"src/services/gui/widgets"
|
||||
|
||||
INCLUDE_DIRS "src"
|
||||
REQUIRES esp_lvgl_port esp_lcd esp_lcd_touch driver mlib cmsis_core furi nvs_flash spiffs fatfs
|
||||
|
||||
REQUIRES cmsis_core
|
||||
esp_lcd
|
||||
esp_lcd_touch
|
||||
esp_lvgl_port
|
||||
driver
|
||||
fatfs
|
||||
furi
|
||||
mlib
|
||||
nvs_flash
|
||||
spiffs
|
||||
)
|
||||
|
||||
set(ASSETS_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/assets")
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
#include "system_info.h"
|
||||
#include "app_manifest.h"
|
||||
#include "furi_extra_defines.h"
|
||||
#include "thread.h"
|
||||
#include "lvgl.h"
|
||||
|
||||
static void app_show(lv_obj_t* parent, void* context) {
|
||||
static void app_show(Context* context, lv_obj_t* parent) {
|
||||
UNUSED(context);
|
||||
|
||||
lv_obj_t* heap_info = lv_label_create(parent);
|
||||
@ -38,5 +38,5 @@ AppManifest system_info_app = {
|
||||
.type = AppTypeSystem,
|
||||
.on_start = NULL,
|
||||
.on_stop = NULL,
|
||||
.on_show = app_show
|
||||
.on_show = &app_show
|
||||
};
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "app_manifest.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern AppManifest system_info_app;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -9,7 +9,7 @@ static void on_open_app(lv_event_t* e) {
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if (code == LV_EVENT_CLICKED) {
|
||||
const AppManifest* manifest = lv_event_get_user_data(e);
|
||||
loader_start_app_nonblocking(manifest->id, NULL);
|
||||
loader_start_app_nonblocking(manifest->id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ static void add_app_to_list(const AppManifest* manifest, void* _Nullable parent)
|
||||
lv_obj_add_event_cb(btn, &on_open_app, LV_EVENT_CLICKED, (void*)manifest);
|
||||
}
|
||||
|
||||
static void desktop_show(lv_obj_t* parent, void* context) {
|
||||
static void desktop_show(Context* context, 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);
|
||||
|
||||
@ -143,8 +143,8 @@ static int32_t gui_main(void* p) {
|
||||
|
||||
// region AppManifest
|
||||
|
||||
static void gui_start(void* parameter) {
|
||||
UNUSED(parameter);
|
||||
static void gui_start(Context* context) {
|
||||
UNUSED(context);
|
||||
|
||||
gui = gui_alloc();
|
||||
|
||||
@ -152,7 +152,9 @@ static void gui_start(void* parameter) {
|
||||
furi_thread_start(gui->thread);
|
||||
}
|
||||
|
||||
static void gui_stop() {
|
||||
static void gui_stop(Context* context) {
|
||||
UNUSED(context);
|
||||
|
||||
gui_lock();
|
||||
|
||||
FuriThreadId thread_id = furi_thread_get_id(gui->thread);
|
||||
|
||||
@ -21,7 +21,6 @@ typedef struct Gui Gui;
|
||||
*
|
||||
* @remark thread safe
|
||||
*
|
||||
* @param gui Gui instance
|
||||
* @param view_port ViewPort instance
|
||||
* @param[in] layer GuiLayer where to place view_port
|
||||
*/
|
||||
@ -31,7 +30,6 @@ void gui_add_view_port(ViewPort* view_port, GuiLayer layer);
|
||||
*
|
||||
* @remark thread safe
|
||||
*
|
||||
* @param gui Gui instance
|
||||
* @param view_port ViewPort instance
|
||||
*/
|
||||
void gui_remove_view_port(ViewPort* view_port);
|
||||
|
||||
@ -33,8 +33,6 @@ struct Gui {
|
||||
};
|
||||
|
||||
/** Update GUI, request redraw
|
||||
*
|
||||
* @param gui Gui instance
|
||||
*/
|
||||
void gui_request_draw();
|
||||
|
||||
@ -48,13 +46,9 @@ void gui_request_draw();
|
||||
//void gui_input_events_callback(const void* value, void* ctx);
|
||||
|
||||
/** Lock GUI
|
||||
*
|
||||
* @param gui The Gui instance
|
||||
*/
|
||||
void gui_lock();
|
||||
|
||||
/** Unlock GUI
|
||||
*
|
||||
* @param gui The Gui instance
|
||||
*/
|
||||
void gui_unlock();
|
||||
|
||||
@ -48,7 +48,7 @@ bool view_port_is_enabled(const ViewPort* view_port) {
|
||||
return is_enabled;
|
||||
}
|
||||
|
||||
void view_port_draw_callback_set(ViewPort* view_port, ViewPortDrawCallback callback, void* context) {
|
||||
void view_port_draw_callback_set(ViewPort* view_port, ViewPortDrawCallback callback, Context* context) {
|
||||
furi_assert(view_port);
|
||||
furi_check(furi_mutex_acquire(view_port->mutex, FuriWaitForever) == FuriStatusOk);
|
||||
view_port->draw_callback = callback;
|
||||
@ -91,7 +91,7 @@ void view_port_draw(ViewPort* view_port, lv_obj_t* parent) {
|
||||
if (view_port->draw_callback) {
|
||||
lv_obj_clean(parent);
|
||||
lv_obj_set_style_no_padding(parent);
|
||||
view_port->draw_callback(parent, view_port->draw_callback_context);
|
||||
view_port->draw_callback(view_port->draw_callback_context, parent);
|
||||
}
|
||||
|
||||
furi_mutex_release(view_port->mutex);
|
||||
|
||||
@ -5,6 +5,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "context.h"
|
||||
|
||||
typedef struct ViewPort ViewPort;
|
||||
|
||||
@ -19,7 +20,7 @@ typedef enum {
|
||||
/** ViewPort Draw callback
|
||||
* @warning called from GUI thread
|
||||
*/
|
||||
typedef void (*ViewPortDrawCallback)(lv_obj_t* parent, void* context);
|
||||
typedef void (*ViewPortDrawCallback)(Context* context, lv_obj_t* parent);
|
||||
|
||||
/** ViewPort allocator
|
||||
*
|
||||
@ -52,7 +53,7 @@ bool view_port_is_enabled(const ViewPort* view_port);
|
||||
* @param callback appropriate callback function
|
||||
* @param context context to pass to callback
|
||||
*/
|
||||
void view_port_draw_callback_set(ViewPort* view_port, ViewPortDrawCallback callback, void* context);
|
||||
void view_port_draw_callback_set(ViewPort* view_port, ViewPortDrawCallback callback, Context* context);
|
||||
/** Emit update signal to GUI system.
|
||||
*
|
||||
* Rendering will happen later after GUI system process signal.
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "context.h"
|
||||
#include "gui_i.h"
|
||||
#include "mutex.h"
|
||||
#include "view_port.h"
|
||||
@ -10,7 +11,7 @@ struct ViewPort {
|
||||
bool is_enabled;
|
||||
|
||||
ViewPortDrawCallback draw_callback;
|
||||
void* draw_callback_context;
|
||||
Context* draw_callback_context;
|
||||
|
||||
/*
|
||||
ViewPortInputCallback input_callback;
|
||||
|
||||
@ -27,7 +27,6 @@ static Loader* loader_alloc() {
|
||||
&loader_main,
|
||||
NULL
|
||||
);
|
||||
loader->app_data.args = NULL;
|
||||
loader->app_data.app = NULL;
|
||||
loader->app_data.view_port = NULL;
|
||||
loader->mutex = xSemaphoreCreateRecursiveMutex();
|
||||
@ -55,13 +54,12 @@ void loader_unlock() {
|
||||
furi_check(xSemaphoreGiveRecursive(loader->mutex) == pdPASS);
|
||||
}
|
||||
|
||||
LoaderStatus loader_start_app(const char* id, const char* args, FuriString* error_message) {
|
||||
LoaderStatus loader_start_app(const char* id, FuriString* error_message) {
|
||||
LoaderMessage message;
|
||||
LoaderMessageLoaderStatusResult result;
|
||||
|
||||
message.type = LoaderMessageTypeAppStart;
|
||||
message.start.id = id;
|
||||
message.start.args = args;
|
||||
message.start.error_message = error_message;
|
||||
message.api_lock = api_lock_alloc_locked();
|
||||
message.status_value = &result;
|
||||
@ -70,13 +68,12 @@ LoaderStatus loader_start_app(const char* id, const char* args, FuriString* erro
|
||||
return result.value;
|
||||
}
|
||||
|
||||
void loader_start_app_nonblocking(const char* id, const char* args) {
|
||||
void loader_start_app_nonblocking(const char* id) {
|
||||
LoaderMessage message;
|
||||
LoaderMessageLoaderStatusResult result;
|
||||
|
||||
message.type = LoaderMessageTypeAppStart;
|
||||
message.start.id = id;
|
||||
message.start.args = args;
|
||||
message.start.error_message = NULL;
|
||||
message.api_lock = NULL;
|
||||
message.status_value = &result;
|
||||
@ -142,8 +139,7 @@ static LoaderStatus loader_make_success_status(FuriString* error_message) {
|
||||
}
|
||||
|
||||
static void loader_start_app_with_manifest(
|
||||
const AppManifest* _Nonnull manifest,
|
||||
const char* args
|
||||
const AppManifest* _Nonnull manifest
|
||||
) {
|
||||
FURI_LOG_I(TAG, "start with manifest %s", manifest->id);
|
||||
|
||||
@ -156,17 +152,19 @@ static void loader_start_app_with_manifest(
|
||||
loader_lock();
|
||||
|
||||
loader->app_data.app = app;
|
||||
loader->app_data.args = (void*)args;
|
||||
|
||||
if (manifest->on_start != NULL) {
|
||||
manifest->on_start((void*)args);
|
||||
manifest->on_start(&loader->app_data.app->context);
|
||||
}
|
||||
|
||||
if (manifest->on_show != NULL) {
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
loader->app_data.view_port = view_port;
|
||||
view_port_draw_callback_set(view_port, manifest->on_show, NULL);
|
||||
|
||||
view_port_draw_callback_set(
|
||||
view_port,
|
||||
manifest->on_show,
|
||||
&loader->app_data.app->context
|
||||
);
|
||||
gui_add_view_port(view_port, GuiLayerWindow);
|
||||
} else {
|
||||
loader->app_data.view_port = NULL;
|
||||
@ -182,7 +180,6 @@ static void loader_start_app_with_manifest(
|
||||
|
||||
static LoaderStatus loader_do_start_by_id(
|
||||
const char* id,
|
||||
const char* args,
|
||||
FuriString* _Nullable error_message
|
||||
) {
|
||||
FURI_LOG_I(TAG, "Start by id %s", id);
|
||||
@ -197,7 +194,7 @@ static LoaderStatus loader_do_start_by_id(
|
||||
);
|
||||
}
|
||||
|
||||
loader_start_app_with_manifest(manifest, args);
|
||||
loader_start_app_with_manifest(manifest);
|
||||
return loader_make_success_status(error_message);
|
||||
}
|
||||
|
||||
@ -220,12 +217,7 @@ static void loader_do_stop_app() {
|
||||
}
|
||||
|
||||
if (app->manifest->on_stop) {
|
||||
app->manifest->on_stop();
|
||||
}
|
||||
|
||||
if (loader->app_data.args) {
|
||||
free(loader->app_data.args);
|
||||
loader->app_data.args = NULL;
|
||||
app->manifest->on_stop(&app->context);
|
||||
}
|
||||
|
||||
furi_app_free(loader->app_data.app);
|
||||
@ -268,7 +260,6 @@ static int32_t loader_main(void* p) {
|
||||
}
|
||||
message.status_value->value = loader_do_start_by_id(
|
||||
message.start.id,
|
||||
message.start.args,
|
||||
message.start.error_message
|
||||
);
|
||||
if (message.api_lock) {
|
||||
@ -290,8 +281,8 @@ static int32_t loader_main(void* p) {
|
||||
|
||||
// region AppManifest
|
||||
|
||||
static void loader_start(void* parameter) {
|
||||
UNUSED(parameter);
|
||||
static void loader_start(Context* context) {
|
||||
UNUSED(context);
|
||||
furi_check(loader == NULL);
|
||||
loader = loader_alloc();
|
||||
|
||||
@ -299,7 +290,8 @@ static void loader_start(void* parameter) {
|
||||
furi_thread_start(loader->thread);
|
||||
}
|
||||
|
||||
static void loader_stop() {
|
||||
static void loader_stop(Context* context) {
|
||||
UNUSED(context);
|
||||
furi_check(loader != NULL);
|
||||
LoaderMessage message = {
|
||||
.api_lock = NULL,
|
||||
|
||||
@ -29,21 +29,19 @@ typedef struct {
|
||||
|
||||
/**
|
||||
* @brief Close any running app, then start new one. Blocking.
|
||||
* @param[in] loader loader instance
|
||||
* @param[in] id application name or id
|
||||
* @param[in] args application arguments
|
||||
* @param[out] error_message detailed error message, can be NULL
|
||||
* @return LoaderStatus
|
||||
*/
|
||||
LoaderStatus loader_start_app(const char* id, const char* args, FuriString* error_message);
|
||||
LoaderStatus loader_start_app(const char* id, FuriString* error_message);
|
||||
|
||||
/**
|
||||
* @brief Close any running app, then start new one. Non-blocking.
|
||||
* @param[in] loader loader instance
|
||||
* @param[in] id application name or id
|
||||
* @param[in] args application arguments
|
||||
*/
|
||||
void loader_start_app_nonblocking(const char* id, const char* args);
|
||||
void loader_start_app_nonblocking(const char* id);
|
||||
|
||||
void loader_stop_app();
|
||||
|
||||
@ -52,7 +50,6 @@ bool loader_is_app_running();
|
||||
const AppManifest* _Nullable loader_get_current_app();
|
||||
/**
|
||||
* @brief Start application with GUI error message
|
||||
* @param[in] instance loader instance
|
||||
* @param[in] name application name or id
|
||||
* @param[in] args application arguments
|
||||
* @return LoaderStatus
|
||||
@ -61,13 +58,11 @@ const AppManifest* _Nullable loader_get_current_app();
|
||||
|
||||
/**
|
||||
* @brief Show loader menu
|
||||
* @param[in] instance loader instance
|
||||
*/
|
||||
void loader_show_menu();
|
||||
|
||||
/**
|
||||
* @brief Get loader pubsub
|
||||
* @param[in] instance loader instance
|
||||
* @return FuriPubSub*
|
||||
*/
|
||||
FuriPubSub* loader_get_pubsub();
|
||||
|
||||
@ -11,7 +11,6 @@
|
||||
#include "thread.h"
|
||||
|
||||
typedef struct {
|
||||
char* args;
|
||||
App* app;
|
||||
ViewPort* view_port;
|
||||
} LoaderAppData;
|
||||
@ -32,7 +31,6 @@ typedef enum {
|
||||
|
||||
typedef struct {
|
||||
const char* id;
|
||||
const char* args;
|
||||
FuriString* error_message;
|
||||
} LoaderMessageAppStart;
|
||||
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
#include "tactility.h"
|
||||
|
||||
#include "app_manifest_registry.h"
|
||||
#include "devices_i.h"
|
||||
#include "furi.h"
|
||||
#include "graphics_i.h"
|
||||
#include "partitions.h"
|
||||
#include "services/gui/gui.h"
|
||||
#include "tactility.h"
|
||||
#include "service_registry.h"
|
||||
|
||||
#define TAG "tactility"
|
||||
|
||||
Gui* gui_alloc();
|
||||
|
||||
// System services
|
||||
extern const ServiceManifest gui_service;
|
||||
extern const ServiceManifest loader_service;
|
||||
@ -18,13 +17,6 @@ extern const ServiceManifest desktop_service;
|
||||
// System apps
|
||||
extern const AppManifest system_info_app;
|
||||
|
||||
void start_service(const ServiceManifest* _Nonnull manifest) {
|
||||
FURI_LOG_I(TAG, "Starting service %s", manifest->id);
|
||||
furi_check(manifest->on_start, "service must define on_start");
|
||||
manifest->on_start(NULL);
|
||||
// TODO: keep track of running services
|
||||
}
|
||||
|
||||
static void register_system_apps() {
|
||||
FURI_LOG_I(TAG, "Registering default apps");
|
||||
app_manifest_registry_add(&system_info_app);
|
||||
@ -43,12 +35,18 @@ static void register_user_apps(const Config* _Nonnull config) {
|
||||
}
|
||||
}
|
||||
|
||||
static void register_system_services() {
|
||||
FURI_LOG_I(TAG, "Registering system services");
|
||||
service_registry_add(&gui_service);
|
||||
service_registry_add(&loader_service);
|
||||
service_registry_add(&desktop_service);
|
||||
}
|
||||
|
||||
static void start_system_services() {
|
||||
FURI_LOG_I(TAG, "Starting system services");
|
||||
start_service(&gui_service);
|
||||
start_service(&loader_service);
|
||||
start_service(&desktop_service);
|
||||
FURI_LOG_I(TAG, "System services started");
|
||||
service_registry_start(gui_service.id);
|
||||
service_registry_start(loader_service.id);
|
||||
service_registry_start(desktop_service.id);
|
||||
}
|
||||
|
||||
static void start_user_services(const Config* _Nonnull config) {
|
||||
@ -63,7 +61,6 @@ static void start_user_services(const Config* _Nonnull config) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
FURI_LOG_I(TAG, "User services started");
|
||||
}
|
||||
|
||||
__attribute__((unused)) extern void tactility_start(const Config* _Nonnull config) {
|
||||
@ -75,6 +72,7 @@ __attribute__((unused)) extern void tactility_start(const Config* _Nonnull confi
|
||||
/*NbLvgl lvgl =*/tt_graphics_init(&hardware);
|
||||
|
||||
// Register all apps
|
||||
register_system_services();
|
||||
register_system_apps();
|
||||
register_user_apps(config);
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#include "services/gui/gui.h"
|
||||
#include "services/loader/loader.h"
|
||||
|
||||
static void app_show(lv_obj_t* parent, void* context) {
|
||||
static void app_show(Context* context, lv_obj_t* parent) {
|
||||
UNUSED(context);
|
||||
|
||||
lv_obj_t* label = lv_label_create(parent);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user