diff --git a/meow_ui_media.c b/meow_ui_media.c index 3632302..59c54a8 100644 --- a/meow_ui_media.c +++ b/meow_ui_media.c @@ -30,11 +30,6 @@ static pthread_t g_thr; static int g_thr_on = 0; static volatile int g_quit = 0; static meow_media_playctl_fn g_cb = NULL; -/* 本进程最后一次经 meow_ui_media_meta 上报的 state(0=停 1=播放 2=暂停 3=缓冲)。 - * 供「物理播放/暂停键」做切换判据:播放中→暂停(2),否则→播放(1)。与 launcher - * now_playing.c 的同款判定(state==PLAYING ? 2 : 1)对齐。 */ -static int g_last_state = 0; -#define MEOW_UI_MEDIA_STATE_PLAYING 1 /* 后台线程主体(定义在文件后段;on_playctl 懒起时引用)。 */ static void *media_thread_main(void *arg); @@ -182,7 +177,6 @@ void meow_ui_media_meta(uint32_t state, uint32_t pos_ms, uint32_t dur_ms, memset(&mm, 0, sizeof mm); pthread_mutex_lock(&g_mu); media_app_id(); - g_last_state = (int)state; /* 记录最近上报 state:供物理播放/暂停键切换判据(见 sys_key) */ snprintf(mm.app_id, sizeof mm.app_id, "%s", g_app); mm.state = state; mm.pos_ms = pos_ms; @@ -218,14 +212,16 @@ void meow_ui_media_stop(void) * 本进程注册过 playctl 回调(= 本 App 是媒体源)→ 直接本地回调(最简,无 IPC 往返); * 否则经 IPC 发 MSG_PLAYCTL 给 launcher 转发到「最近活跃媒体会话」。best-effort 绝不崩。 */ -/* 物理媒体键 keycode → MSG_PLAYCTL cmd(1=播放 2=暂停 3=上一首 4=下一首 5=seek)。 - * 播放/暂停(164)按最近上报 state 切换(播放中→暂停,否则→播放);上一曲 165/19→3,下一曲 163→4。 - * 非媒体键返回 -1。last_state 由调用方在持锁下传入(读 g_last_state 快照)。 */ -static int media_key_cmd(int code, int last_state) +/* 物理媒体键 keycode → MSG_PLAYCTL cmd(1=播放 2=暂停 3=上一首 4=下一首 5=seek 6=播放/暂停切换)。 + * 播放/暂停(164)恒发 cmd=6 toggle——SDK 本地不再按「最近上报 state」判 play/pause: + * 走自有 IPC 线程的媒体源(如 ncm 的 ipc_media.c)不经 meow_ui_media_meta 上报, + * 本地 state 恒 0 → 恒发「播放」,播放中按键无效(真机 bug)。toggle 由媒体源按自身 + * 当前态翻转(权威在源)。上一曲 165/19→3,下一曲 163→4。非媒体键返回 -1。 */ +static int media_key_cmd(int code) { switch (code) { - case 164: /* KEY_PLAYPAUSE:切换(依最近上报 state) */ - return (last_state == MEOW_UI_MEDIA_STATE_PLAYING) ? 2 : 1; + case 164: /* KEY_PLAYPAUSE:toggle(源侧按当前态翻转) */ + return 6; case 165: case 19: /* KEY_PREVIOUSSONG / 旧码 */ return 3; case 163: /* KEY_NEXTSONG */ @@ -264,8 +260,8 @@ void meow_ui_media_sys_key(int code) { pthread_mutex_lock(&g_mu); meow_media_playctl_fn cb = g_cb; - int cmd = media_key_cmd(code, g_last_state); pthread_mutex_unlock(&g_mu); + int cmd = media_key_cmd(code); if (cmd <= 0) return; if (cb) { cb(cmd, 0); return; } /* 本 App 是媒体源(注册过回调)→ 本地回调 */ send_playctl_upstream(cmd, 0); /* 否则经 IPC 发 launcher 转发到最近活跃会话 */ diff --git a/meow_ui_media.h b/meow_ui_media.h index a5ef67d..20394f3 100644 --- a/meow_ui_media.h +++ b/meow_ui_media.h @@ -19,7 +19,8 @@ extern "C" { #endif -/* 播放控制回调:cmd 1=播放 2=暂停 3=上一首 4=下一首 5=seek(seek_ms 为毫秒)。 */ +/* 播放控制回调:cmd 1=播放 2=暂停 3=上一首 4=下一首 5=seek(seek_ms 为毫秒)6=播放/暂停切换 + * (toggle:物理播放/暂停键 164 恒发 6,由媒体源按自身当前态翻转——源是状态权威)。 */ typedef void (*meow_media_playctl_fn)(int cmd, int64_t seek_ms); /* 指定 app_id(NULL=env MEOW_LOG_APP,缺省 "app")。幂等,首次调用生效。 */ @@ -40,7 +41,7 @@ void meow_ui_media_meta(uint32_t state, uint32_t pos_ms, uint32_t dur_ms, void meow_ui_media_stop(void); /* 物理媒体键 → 系统语义(SDK 输入层调用;App 前台也生效)。 - * code:164=播放/暂停、165/19=上一曲、163=下一曲。 + * code:164=播放/暂停(恒发 cmd=6 toggle,源侧翻转)、165/19=上一曲、163=下一曲。 * 本 App 注册过 playctl 回调(媒体源)→ 本地直接回调 cb(cmd,seek_ms); * 否则经 IPC 发 MSG_PLAYCTL 给 launcher 转发到最近活跃媒体会话。非媒体键/无源静默。 * best-effort:无 launcher/socket → 优雅降级,绝不崩。 */ diff --git a/test_sdk_input_keys b/test_sdk_input_keys index 174a543..d38b64b 100755 Binary files a/test_sdk_input_keys and b/test_sdk_input_keys differ diff --git a/test_sdk_input_keys.c b/test_sdk_input_keys.c index bf93ee0..8a5dfb1 100644 --- a/test_sdk_input_keys.c +++ b/test_sdk_input_keys.c @@ -6,7 +6,8 @@ * K2 音量 ± clamp:volume_max 软上限、0 下限、硬上限 100;到限不再写; * K3 保留其它键:改 audio.volume 不整文件 O_TRUNC(display.brightness/注释保留); * K4 媒体键本地回调:注册 playctl 回调后,sys_key(上一曲/下一曲/播放暂停) → 回调 cmd 正确 - * (播放/暂停按最近上报 state 切换:播放中→暂停(2),暂停/停止→播放(1)); + * (播放/暂停恒发 toggle(6),SDK 不再本地判 state——走自有 IPC 线程的源不经 SDK meta + * 上报,本地 state 恒 0 会恒发「播放」致播放中按键无效;源侧按当前态翻转); * K5 媒体键 IPC 兜底:未注册回调(g_cb==NULL)→ 走 IPC 发 launcher(无 socket → 静默不崩)。 * * 编译(宿主 gcc,仅链 vol/media 两个 TU;无需 meow_ui 其它子系统): @@ -101,16 +102,16 @@ int main(void) meow_ui_media_sys_key(19); /* 旧码上一曲 */ check("K4 旧码(19) -> cb(3)", cb_calls == 3 && cb_cmd == 3); - /* 播放/暂停按最近上报 state 切换 */ + /* 播放/暂停物理键恒发 toggle(6):与最近上报 state 无关(源侧按当前态翻转) */ meow_ui_media_meta(1, 0, 0, "t", "a", "al", NULL, NULL); /* state=PLAYING */ meow_ui_media_sys_key(164); - check("K4 播放中按播放/暂停 -> cb(2) 暂停", cb_calls == 4 && cb_cmd == 2); + check("K4 播放中按播放/暂停 -> cb(6) toggle", cb_calls == 4 && cb_cmd == 6); meow_ui_media_meta(2, 0, 0, "t", "a", "al", NULL, NULL); /* state=PAUSED */ meow_ui_media_sys_key(164); - check("K4 暂停中按播放/暂停 -> cb(1) 播放", cb_calls == 5 && cb_cmd == 1); + check("K4 暂停中按播放/暂停 -> cb(6) toggle", cb_calls == 5 && cb_cmd == 6); meow_ui_media_meta(0, 0, 0, "t", "a", "al", NULL, NULL); /* state=STOPPED */ meow_ui_media_sys_key(164); - check("K4 停止中按播放/暂停 -> cb(1) 播放", cb_calls == 6 && cb_cmd == 1); + check("K4 停止中按播放/暂停 -> cb(6) toggle", cb_calls == 6 && cb_cmd == 6); meow_ui_media_stop();