Files
ESP32C3-0.42OLED-OS/components/sys_app/sys_app.c
T
2026-09-03 00:46:04 +01:00

158 lines
3.9 KiB
C

#include "os_app.h"
#include "os_gfx.h"
#include "os_status.h"
#include "os_event.h"
#include <string.h>
#include "esp_log.h"
static const char *TAG = "SYS_APP";
#define MAX_APPS 16
static const sys_app_t *s_registry[MAX_APPS];
static size_t s_app_count = 0;
static const sys_app_t *s_current_app = NULL;
static bool s_in_launcher = true;
static size_t s_launcher_selected = 0;
static void launcher_update(uint32_t delta_ms)
{
sys_status_t status;
sys_status_get(&status);
sys_gfx_draw_status_bar(&status);
sys_gfx_draw_str_3x5(2, 9, "--- APPS ---", COLOR_WHITE);
const char *names[MAX_APPS];
for (size_t i = 0; i < s_app_count; i++) {
names[i] = s_registry[i]->name;
}
sys_gfx_draw_menu(15, names, s_app_count, s_launcher_selected);
}
static void launcher_handle_input(input_action_t action)
{
if (s_app_count == 0) return;
if (action == INPUT_ACTION_CLICK) {
s_launcher_selected = (s_launcher_selected + 1) % s_app_count;
} else if (action == INPUT_ACTION_DOUBLE_CLICK) {
if (s_launcher_selected == 0) {
s_launcher_selected = s_app_count - 1;
} else {
s_launcher_selected--;
}
} else if (action == INPUT_ACTION_LONG_PRESS) {
sys_app_launch_by_index(s_launcher_selected);
}
}
esp_err_t sys_app_init(void)
{
s_app_count = 0;
s_current_app = NULL;
s_in_launcher = true;
s_launcher_selected = 0;
sys_status_set_active_app_name("Launcher");
ESP_LOGI(TAG, "App Manager initialized");
return ESP_OK;
}
esp_err_t sys_app_register(const sys_app_t *app)
{
if (!app || !app->id || !app->name) return ESP_ERR_INVALID_ARG;
if (s_app_count >= MAX_APPS) return ESP_ERR_NO_MEM;
s_registry[s_app_count++] = app;
if (app->init) {
app->init();
}
ESP_LOGI(TAG, "Registered app: [%s] '%s'", app->id, app->name);
return ESP_OK;
}
esp_err_t sys_app_launch_by_id(const char *id)
{
if (!id) return ESP_ERR_INVALID_ARG;
for (size_t i = 0; i < s_app_count; i++) {
if (strcmp(s_registry[i]->id, id) == 0) {
return sys_app_launch_by_index(i);
}
}
ESP_LOGW(TAG, "App not found: %s", id);
return ESP_ERR_NOT_FOUND;
}
esp_err_t sys_app_launch_by_index(size_t index)
{
if (index >= s_app_count) return ESP_ERR_INVALID_ARG;
if (s_current_app && s_current_app->exit) {
s_current_app->exit();
}
s_current_app = s_registry[index];
s_in_launcher = false;
sys_status_set_active_app_name(s_current_app->name);
if (s_current_app->enter) {
s_current_app->enter();
}
sys_event_post(SYS_EVENT_APP_SWITCH, (int32_t)index, (void *)s_current_app->id);
sys_gfx_show_toast(s_current_app->name, 800);
ESP_LOGI(TAG, "Switched to app: %s", s_current_app->name);
return ESP_OK;
}
void sys_app_launch_launcher(void)
{
if (s_current_app && s_current_app->exit) {
s_current_app->exit();
}
s_current_app = NULL;
s_in_launcher = true;
sys_status_set_active_app_name("Launcher");
sys_gfx_show_toast("Launcher", 600);
ESP_LOGI(TAG, "Returned to App Launcher");
}
const sys_app_t *sys_app_get_current(void)
{
return s_current_app;
}
void sys_app_update(uint32_t delta_ms)
{
if (s_in_launcher) {
launcher_update(delta_ms);
} else if (s_current_app && s_current_app->update) {
s_current_app->update(delta_ms);
}
}
void sys_app_dispatch_input(input_action_t action)
{
if (action == INPUT_ACTION_HOLD_HOME) {
sys_app_launch_launcher();
return;
}
if (s_in_launcher) {
launcher_handle_input(action);
} else if (s_current_app && s_current_app->handle_input) {
s_current_app->handle_input(action);
}
}
size_t sys_app_get_count(void)
{
return s_app_count;
}
const sys_app_t *sys_app_get_by_index(size_t index)
{
if (index >= s_app_count) return NULL;
return s_registry[index];
}