fix(media): 物理播放/暂停键(164)改发 PLAYCTL cmd=6 toggle + App 前台状态栏音量%实时刷新

Bug1: SDK meow_ui_media 按 g_last_state 本地判 play/pause,但 ncm 走自有 ipc_media
线程不经 SDK meta 上报 → g_last_state 恒 0 → 恒发 cmd=1(播放),播放中按键无效。
修:SDK 164 恒发 cmd=6 toggle(删 g_last_state 判定),ncm apply_playctl case 6
按 player_manager_state() 当前态翻转(源是状态权威);launcher meow_media/util
本就透传 cmd 不动结构,仅 meow_ipc.h/SPEC_REF 注释补 6=toggle。媒体卡片/NP 页
按钮(按 launcher 侧 s->state 判,来自 META 是准的)维持现状。

Bug2: App 前台时状态栏为 launcher 叠加层,App 内 SDK 改音量/亮度只写
settings.conf+DAC,launcher meow_settings 内存表不感知 → g_sys.vol 停旧值。
修:app_overlay_statusbar 前插 app_overlay_settings_poll——1s 节流 stat
settings.conf,mtime 变才 meow_settings_init 重读+sync 缓存+g_sys.vol/brightness
(meow_settings 新增 meow_settings_file_path() 访问器防硬编码分叉)。

验证:宿主 test_sdk_input_keys 19/19(K4 改 toggle 断言)、test_media +cmd=6
透传用例 ALL PASS、ncm bench/toggle_sim 10/10(新)、player_flow/cache_evict
sim PASS、ncm core 宿主+qemu-mipsel PASS、test_settings_brightness PASS;
mipsel 交叉 -Wall -Wextra 0 warning(改动文件单独验+整构建)。
真机(0.7.91):ncm 热更(.new+mv)后 autoplay(Docu) 起播缓存曲 → meow_ipc
playctl 6 二连发 → paused(pos=139691)/resumed 日志实证 toggle 全链路。
md5:ncm 8f10eee5 / meow_ui.a 7b359ec9(gitignore)/ launcher eba4f2b2
(/usr/bin 只读,fw_content.conf 已更新待固件)。物理键 164 实体按压留用户终验。
This commit is contained in:
MeowOS committed 2026-09-01 14:44:55 +08:00
1 parent 9a4ea10c64
commit 820d1e52bf
17 files changed
+173 -26

No files matched your search

+26
View File
@@ -1084,6 +1084,31 @@ static int app_sbar_mode_read(void)
}
/* App 前台会话:App 进程(SDK 输入层音量键 / App 自身设置)改音量/亮度只写 settings.conf+DAC,
* launcher 的 meow_settings 内存表与 g_sys 缓存不感知 → 状态栏叠加层 VOL/亮度数字停旧值(真机 bug)。
* 修法:1s 节流 stat settings.conf,mtime 变化才 meow_settings_init() 重读 + 同步缓存全局
* (不在热路径每秒全量重读;顶条动画期 ~30ms 快刷也不会放大 stat 频率——节流在 stat 之前)。 */
static void app_overlay_settings_poll(void)
{
static unsigned long long last_poll_ms = 0;
static long long last_mtime = -1;
unsigned long long now = now_ms();
if (last_poll_ms && now - last_poll_ms < 1000) return;
last_poll_ms = now;
struct stat st;
if (stat(meow_settings_file_path(), &st) != 0) return;
if (last_mtime >= 0 && (long long)st.st_mtime == last_mtime) return;
int first = (last_mtime < 0);
last_mtime = (long long)st.st_mtime;
if (first) return; /* 首调只锚定 mtime(启动已 settings_load 过) */
meow_settings_init(); /* 幂等:重置默认 + 重读 settings.conf */
settings_sync_cache_from_backend(); /* audio.volume 等 → settings_volume 等缓存 */
g_sys.vol = settings_volume_get();
g_sys.brightness = meow_settings_brightness_clamped();
logmsg("app-overlay: settings.conf changed -> reload vol=%d bri=%d",
g_sys.vol, g_sys.brightness);
}
static void app_overlay_statusbar(void)
{
if (!back_buf_ok || !fb) return; /* 无 SDK back_buf(直写模式):无法叠加,跳过 */
@@ -1101,6 +1126,7 @@ static void app_overlay_statusbar(void)
meow_ui_set_fullscreen(0);
meow_ui_statusbar_set_collapsed(0);
}
app_overlay_settings_poll(); /* settings.conf mtime 变 → 重读(App 侧改音量/亮度跟进) */
meow_sys_light(); /* 刷新 g_sys(电池/WiFi/音量/蓝牙;唯一权威源) */
meow_theme_reload(); /* SDK 状态栏主题随 launcher 换肤(重读 settings) */
meow_ui_feed f;
+5 -3
View File
@@ -215,12 +215,14 @@ typedef struct m_meta {
} m_meta_t; /* 128+128+128+16+192+192+32 = 828 B */
/* MSG_PLAYCTL ↓(launcher→App)/↑(控制器→launcher 转发到最近活跃媒体会话):播放控制。
* cmd:1=播放 2=暂停 3=上一首 4=下一首 5=seek;其余保留。
* cmd:1=播放 2=暂停 3=上一首 4=下一首 5=seek 6=播放/暂停切换(toggle,源侧按当前态翻转);其余保留。
* seek_ms:cmd=5 时目标位置(ms);其余置 0。
* 语义:通知中心卡片/播放页按钮、物理媒体键 → meow_media_playctl(cmd,seek_ms) 经
* 「最近活跃媒体会话」的连接 fd 下发;宿主验证经 meow_ipc playctl 发到 launcher 转发。 */
* 「最近活跃媒体会话」的连接 fd 下发;宿主验证经 meow_ipc playctl 发到 launcher 转发。
* 物理播放/暂停键(164)在 SDK 侧恒映射 cmd=6(不再本地判 state:走自有 IPC 线程的源
* 不经 SDK meta 上报,SDK 侧 state 可能恒 0);launcher 透传 cmd 不改写。 */
typedef struct m_playctl {
uint32_t cmd; /* 1=播放 2=暂停 3=上一首 4=下一首 5=seek */
uint32_t cmd; /* 1=播放 2=暂停 3=上一首 4=下一首 5=seek 6=播放/暂停toggle */
int64_t seek_ms; /* cmd=5: 目标位置 ms;否则 0 */
} m_playctl_t; /* 4 (+4 pad) + 8 = 16 B(mipsel int64 8 对齐) */
Binary file not shown.
+8
View File
@@ -255,6 +255,14 @@ int meow_settings_loaded(void)
return g_loaded_from_file;
}
/* 存储文件路径(= 编译期 MEOW_SETTINGS_FILE,默认 /usr/data/meow/settings.conf)。
* 供跨进程变更轮询(launcher App 前台会话 stat mtime,见 app_launcher.c)等场景取权威路径,
* 避免调用方硬编码与编译期覆盖分叉。 */
const char *meow_settings_file_path(void)
{
return MEOW_SETTINGS_FILE;
}
/* ---- 按类型把字符串值 apply 到 cur(读文件/导入时用;含 clamp/校验)---- */
static void apply_value(meow_setting *s, const char *v)
{
+4
View File
@@ -82,6 +82,10 @@ int meow_settings_brightness_clamped(void);
* 1 = 文件已读到:键缺失走各自默认(属「已知」态),用户设定可信。 */
int meow_settings_loaded(void);
/* 存储文件绝对路径(编译期 MEOW_SETTINGS_FILE,默认 /usr/data/meow/settings.conf)。
* 供调用方做 mtime 轮询等(App 前台会话状态栏刷新,见 app_launcher.c)。 */
const char *meow_settings_file_path(void);
int meow_settings_set_int (const char *key, int v); /* clamp 到取值域 */
int meow_settings_set_str (const char *key, const char *v);/* 长度截断 MEOW_SET_MAX_LEN */
int meow_settings_set_enum(const char *key, int idx); /* 校验枚举合法,越界拒绝 */
+6
View File
@@ -145,6 +145,12 @@ int main(void)
memcpy(&c, rbuf, sizeof c);
CHECK(type == MSG_PLAYCTL && c.cmd == 5 && c.seek_ms == 12345, "downlink seek cmd=5 seek=12345");
/* 5b) toggle 透传:cmd=6(物理播放/暂停键)原样下发,launcher 不改写 cmd */
CHECK(meow_media_playctl(6, 0) == 0, "playctl sends (cmd=toggle)");
n = read_frame(sv[1], &type, &req, rbuf, sizeof rbuf);
memcpy(&c, rbuf, sizeof c);
CHECK(type == MSG_PLAYCTL && c.cmd == 6 && c.seek_ms == 0, "downlink cmd=6 passthrough");
/* playctl_to 目标 app(另一会话) */
CHECK(meow_media_playctl_to("com.player2", 3, 0) == 0, "playctl_to player2 sends");
n = read_frame(sv[1], &type, &req, rbuf, sizeof rbuf);