/** **************************************************************************************************** * @file app.h * @author HiFi Player Project * @version V1.2 * @date 2026-01-01 * @brief 应用管理器:主界面(应用启动器)/ 各 App 切换 + 全局按键服务 * * 设计目的: * 把“哪个界面在运行”和“按键归谁处理”从各 App 里抽出来。 * 新增应用(设置、相册、录音等)只需要: * 1) 在 app_mode_t 里加一个模式; * 2) 在 app.c 的 s_apps[] 表里加一条记录; * 3) 新建自己的文件夹(如 APP/clock/),实现 ui_clock_create/show/tick/handle_key, * 并在 ui.c 的路由表里挂上。 * * 按键语义(由 ui.c 统一实现): * K0 短按 = 返回主界面(主界面时为切换下一个应用) * K0 长按 = 直接切换到下一个应用 * K1/K2/K3 = 由各 App 自己定义 * * 例外:实现了 ui_xxx_back() 的 App(如文件管理器)可以先用 K0 短按 * 完成“就地返回”(返回上一级目录),只有到顶层时才回主界面。 **************************************************************************************************** */ #ifndef __APP_H #define __APP_H #include #include #ifdef __cplusplus extern "C" { #endif /* ---------------- 应用(界面)模式 ---------------- */ typedef enum { APP_MODE_HOME = 0, /* 主界面:应用启动器 */ APP_MODE_PLAYER, /* 音乐播放器 */ APP_MODE_FILES, /* 文件管理器:浏览 SD 卡目录 */ APP_MODE_NUM, /* 模式总数(新增应用请加在这之前) */ } app_mode_t; #define APP_MODE_NONE APP_MODE_NUM /* “无对应界面”(禁用的表项使用) */ /* ---------------- 4 个物理按键(XL9555 的 KEY0~KEY3) ---------------- */ typedef enum { APP_KEY_0 = 0, /* KEY0 */ APP_KEY_1, /* KEY1 */ APP_KEY_2, /* KEY2 */ APP_KEY_3, /* KEY3 */ APP_KEY_NUM } app_key_t; /* ---------------- 按键事件类型 ---------------- */ typedef enum { APP_KEY_SHORT = 0, /* 短按(松开时上报) */ APP_KEY_LONG, /* 长按(按住达到阈值立即上报,松开不再上报短按) */ } app_key_event_t; typedef struct { uint8_t key; /* app_key_t */ uint8_t type; /* app_key_event_t */ } app_event_t; /* ---------------- 主界面应用表项 ---------------- */ typedef struct { const char *icon; /* 图标字形(LV_SYMBOL_xxx) */ const char *title; /* 图标下方名称 */ const char *subtitle; /* 选中时显示的说明(可选,NULL 表示不显示) */ app_mode_t mode; /* 进入后切到的模式(APP_MODE_NONE 表示尚未实现) */ bool enabled; /* 是否可进入 */ uint32_t color_from; /* 图标渐变起始色(顶部) */ uint32_t color_to; /* 图标渐变结束色(底部) */ } app_entry_t; /** * @brief 初始化应用管理器(创建按键服务任务与事件队列) * @note 必须在 xl9555_init() 之后调用 */ void app_start(void); /* ---------------- 模式 ---------------- */ app_mode_t app_get_mode(void); /** * @brief 切换应用模式 * @note 切换时会清空按键事件队列,避免上一次界面的按键“漏”到新界面 */ void app_set_mode(app_mode_t mode); /** 返回主界面(已在主界面时无动作) */ void app_back(void); /** * @brief 切换到“下一个可用的应用" * @retval true 切换成功;false 没有其它可切换的应用 * @note 主界面 K0、以及在任意 App 内长按 K0 都会调用它 */ bool app_switch_next(void); /* ---------------- 主界面应用表 ---------------- */ const app_entry_t *app_get_entries(int *count); int app_get_selection(void); void app_select_move(int delta); /* 在当前应用表中循环移动选择项 */ /* ---------------- 按键事件 ---------------- */ bool app_event_poll(app_event_t *ev); /* 非阻塞 */ bool app_event_wait(app_event_t *ev, uint32_t timeout_ms); /* 阻塞等待 */ void app_event_flush(void); /* 清空队列 */ #ifdef __cplusplus } #endif #endif /* __APP_H */