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:
1 parent
9a4ea10c64
commit
820d1e52bf
17 files changed
+173
-26
No files matched your search
@@ -58,7 +58,7 @@
|
||||
### 2.2 meow_ipc 消息协议(AF_UNIX,全小端 LE)
|
||||
- 帧头 16B:`magic=0x4D4F5701`('MEOW'|1)/`version=1`/`type`/`req_id`/`len`;`len` 上限 **MEOW_IPC_MAX=4096**;列表编码 `[u16 count]`+NUL 串 `[FRAMEWORK_DESIGN §1]`
|
||||
- 消息类型:`MSG_HELLO 0x0001↑ / ACK 0x0002↓ / ERR 0x0003↓ / REGISTER 0x0010↑ / SERVICE_OK 0x0011↓ / SERVICE_STOP 0x0012↑ / MSG_NOTIFY 0x0020↑ / NOTIFY_ACK 0x0021↓ / NOTIFY_DISMISS 0x0022↑ / NOTIFY_LIST 0x0023↓ / NOTIFY_PROGRESS 0x0024↑ / ACT_DECLARE 0x0030↑ / ACT_QUERY 0x0031↑ / ACT_RESULT 0x0032↓ / ACT_FOCUS 0x0033↑ / ACT_BACK 0x0034↑ / NAV 0x0040↑ / SHOW_ACTIVITY 0x0041↓ / PERF_QUERY 0x0050↑ / PERF_RESULT 0x0051↓ / POWER_ACTION 0x0060↑ / POWER_STATUS 0x0061↓ / SYS 0x00F0↓` `[FRAMEWORK_DESIGN §1][meow_ipc.h]`
|
||||
- 媒体:`MSG_META`(元数据)、`MSG_PLAYCTL`(cmd 1=播放2=暂停3=上一首4=下一首5=seek)、`MSG_PROGRESS` `[附录 B]`
|
||||
- 媒体:`MSG_META`(元数据)、`MSG_PLAYCTL`(cmd 1=播放2=暂停3=上一首4=下一首5=seek6=播放/暂停toggle——物理键164恒发6由源侧按当前态翻转,launcher 透传)、`MSG_PROGRESS` `[附录 B]`
|
||||
- IPC 线程**只读帧+解析+入队**;状态变更主循环单写者(eventfd 唤醒,10ms 热键轮询非阻塞排空)`[FRAMEWORK_DESIGN §0][§6]`
|
||||
|
||||
### 2.3 watchdog / supervisor 信号
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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); /* 校验枚举合法,越界拒绝 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -71,6 +71,7 @@ enum {
|
||||
NCM_CTL_PREV = 3,
|
||||
NCM_CTL_NEXT = 4,
|
||||
NCM_CTL_SEEK = 5,
|
||||
NCM_CTL_TOGGLE = 6, /* 播放/暂停切换(物理键 164 恒发此;按当前态翻转) */
|
||||
};
|
||||
|
||||
/* 跨线程播放运行时状态(main 只读展示;play 线程写,IPC 线程读)。 */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* 连接:AF_UNIX SOCK_STREAM 到 MEOW_IPC_SOCK(缺省 /usr/data/meow_ipc.sock)。HELLO(app_id,
|
||||
* MF_PLAYBACK) 注册为媒体源;之后**同一连接**周期发 MSG_META(~1s,进度随播放推进)并阻塞等
|
||||
* launcher 下发 MSG_PLAYCTL(播放/暂停/上下曲/seek)。launcher 经该连接 fd 回发(meow_media.c
|
||||
* launcher 下发 MSG_PLAYCTL(播放/暂停/上下曲/seek/toggle)。launcher 经该连接 fd 回发(meow_media.c
|
||||
* send_playctl 用最近活跃会话的 fd)。无 socket/launcher 不跑 → 优雅跳过(打日志不崩)。
|
||||
* 线程模型:独立线程(main 起了 meow_ui_run 阻塞;播放线程归 player_manager,本线程只做 IPC 收发)。
|
||||
*/
|
||||
@@ -145,6 +145,12 @@ static void apply_playctl(const m_playctl_t *c)
|
||||
case NCM_CTL_PREV: player_manager_next(-1); break;
|
||||
case NCM_CTL_NEXT: player_manager_next(1); break;
|
||||
case NCM_CTL_SEEK: player_manager_seek(c->seek_ms); break;
|
||||
case NCM_CTL_TOGGLE:
|
||||
/* 物理播放/暂停键(SDK 164 恒发 toggle,不再本地判 state):源是状态权威,
|
||||
* 按当前态翻转(与播放页按钮 ui/player.c 同款判定)。非 PLAYING/PAUSED
|
||||
* (停止/缓冲)时 pause() 内部按态过滤,天然 no-op 安全。 */
|
||||
player_manager_pause(player_manager_state() == NCM_PC_PAUSED ? 0 : 1);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/* bench/toggle_sim.c — MSG_PLAYCTL cmd=6(toggle) 离线回归(0 真实请求)。
|
||||
*
|
||||
* 背景(真机 bug):物理播放/暂停键(164)在 SDK 侧曾按「最近上报 state」本地判 play/pause,
|
||||
* 但 ncm 走自有 ipc_media 线程、不经 SDK meow_ui_media_meta 上报 → SDK 侧 state 恒 0 →
|
||||
* 恒发 cmd=1(播放),播放中按键无效。修法:SDK 恒发 cmd=6 toggle,源侧(本文件 apply_playctl)
|
||||
* 按自身当前态翻转——源是状态权威。
|
||||
*
|
||||
* 同 TU 平移 app/play/ipc_media.c(含 static apply_playctl),player_manager_* 用记录桩
|
||||
* (-ffunction-sections + --gc-sections 丢弃未触达的 send_meta/ipc_thread 及其依赖)。
|
||||
*
|
||||
* 用例:
|
||||
* T1 播放中 toggle → pause(1);
|
||||
* T2 暂停中 toggle → pause(0);
|
||||
* T3 停止/缓冲中 toggle → pause(1)(player_manager_pause 内部按态过滤,no-op 安全);
|
||||
* T4 旧 cmd 回归:1=play→pause(0) 2=pause→pause(1) 3=prev→next(-1) 4=next→next(1) 5=seek。
|
||||
*
|
||||
* 编译(宿主,ncm_app 目录下):
|
||||
* gcc -Wall -Wextra -O2 -ffunction-sections -DJSMN_HEADER -I. -I../sdk -I../meow_launcherd \
|
||||
* -Icore -Ivendor/jsmn -c bench/toggle_sim.c -o /tmp/tg.o
|
||||
* gcc -O2 -Wl,--gc-sections -o toggle_sim /tmp/tg.o -lpthread -lm
|
||||
* 运行:./toggle_sim (PASS/FAIL 退出码)
|
||||
*/
|
||||
#include "../app/ncm_app_internal.h"
|
||||
|
||||
/* ---- player_manager 记录桩(覆盖真实实现,仅记录调用)---- */
|
||||
static int g_fake_state = NCM_PC_STOPPED;
|
||||
static int g_pause_calls = 0, g_pause_last = -1;
|
||||
static int g_next_calls = 0, g_next_last = 0;
|
||||
static int g_seek_calls = 0; static int64_t g_seek_last = -1;
|
||||
|
||||
int player_manager_state(void) { return g_fake_state; }
|
||||
void player_manager_pause(int on) { g_pause_calls++; g_pause_last = on; }
|
||||
void player_manager_next(int dir) { g_next_calls++; g_next_last = dir; }
|
||||
void player_manager_seek(int64_t ms) { g_seek_calls++; g_seek_last = ms; }
|
||||
|
||||
/* ---- 被平移 TU 引用但本测试不触达的符号(gc-sections 会丢,仅为防漏列桩)---- */
|
||||
#include "../app/play/ipc_media.c"
|
||||
|
||||
static int failures = 0;
|
||||
static void check(const char *name, int cond)
|
||||
{
|
||||
printf("%s %s\n", cond ? "PASS" : "FAIL", name);
|
||||
if (!cond) failures++;
|
||||
}
|
||||
|
||||
static m_playctl_t mk(uint32_t cmd, int64_t seek)
|
||||
{
|
||||
m_playctl_t c;
|
||||
memset(&c, 0, sizeof c);
|
||||
c.cmd = cmd;
|
||||
c.seek_ms = seek;
|
||||
return c;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
m_playctl_t c;
|
||||
|
||||
/* T1 播放中 toggle → 暂停 */
|
||||
g_fake_state = NCM_PC_PLAYING;
|
||||
c = mk(NCM_CTL_TOGGLE, 0);
|
||||
apply_playctl(&c);
|
||||
check("T1 PLAYING+toggle -> pause(1)", g_pause_calls == 1 && g_pause_last == 1);
|
||||
|
||||
/* T2 暂停中 toggle → 播放 */
|
||||
g_fake_state = NCM_PC_PAUSED;
|
||||
apply_playctl(&c);
|
||||
check("T2 PAUSED+toggle -> pause(0)", g_pause_calls == 2 && g_pause_last == 0);
|
||||
|
||||
/* T3 停止/缓冲 toggle → pause(1)(内部按态过滤,不崩) */
|
||||
g_fake_state = NCM_PC_STOPPED;
|
||||
apply_playctl(&c);
|
||||
check("T3 STOPPED+toggle -> pause(1) 内部过滤", g_pause_calls == 3 && g_pause_last == 1);
|
||||
g_fake_state = NCM_PC_BUFFER;
|
||||
apply_playctl(&c);
|
||||
check("T3 BUFFER+toggle -> pause(1) 内部过滤", g_pause_calls == 4 && g_pause_last == 1);
|
||||
|
||||
/* T4 旧 cmd 回归 */
|
||||
c = mk(NCM_CTL_PLAY, 0); apply_playctl(&c);
|
||||
check("T4 PLAY -> pause(0)", g_pause_calls == 5 && g_pause_last == 0);
|
||||
c = mk(NCM_CTL_PAUSE, 0); apply_playctl(&c);
|
||||
check("T4 PAUSE -> pause(1)", g_pause_calls == 6 && g_pause_last == 1);
|
||||
c = mk(NCM_CTL_PREV, 0); apply_playctl(&c);
|
||||
check("T4 PREV -> next(-1)", g_next_calls == 1 && g_next_last == -1);
|
||||
c = mk(NCM_CTL_NEXT, 0); apply_playctl(&c);
|
||||
check("T4 NEXT -> next(1)", g_next_calls == 2 && g_next_last == 1);
|
||||
c = mk(NCM_CTL_SEEK, 12345); apply_playctl(&c);
|
||||
check("T4 SEEK -> seek(12345)", g_seek_calls == 1 && g_seek_last == 12345);
|
||||
c = mk(99, 0); apply_playctl(&c); /* 未知 cmd:无动作不崩 */
|
||||
check("T4 unknown cmd=99 -> no-op",
|
||||
g_pause_calls == 6 && g_next_calls == 2 && g_seek_calls == 1);
|
||||
|
||||
printf("\n%s (%d failure%s)\n", failures ? "RESULT: FAIL" : "RESULT: PASS",
|
||||
failures, failures == 1 ? "" : "s");
|
||||
return failures ? 1 : 0;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -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 转发到最近活跃会话 */
|
||||
|
||||
@@ -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 → 优雅降级,绝不崩。 */
|
||||
|
||||
Binary file not shown.
@@ -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();
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
# ---- 用户态/服务守护二进制(usr/bin,全部 chmod 755 静态 MIPS)----
|
||||
patch_v2/bootmenu/meow_bootmenu|/usr/bin/meow_bootmenu|4441822d87e76bfce2ce584604ac3830|引导选单 M2.85(sysui让位 agent-216)
|
||||
patch_v2/meow_launcherd/meow_launcherd|/usr/bin/meow_launcherd|adf97ff57cfe24028360cb55a5ae8ce8|主屏 launcher M2.95(+音量反转修复 CS43198 衰减映射)
|
||||
patch_v2/meow_launcherd/meow_launcherd|/usr/bin/meow_launcherd|eba4f2b25f01fe756fbf36a9c0844823|主屏 launcher M2.95+(App 前台状态栏 settings.conf mtime 1s 节流重读,修 App 内音量%不刷新;PLAYCTL cmd=6 toggle 透传注释)
|
||||
patch_v2/meow_watchdog/meow_watchdog|/usr/bin/meow_watchdog|96e80c855e8ca7fd772a2826adbd2639|应用看门狗 M2.95(+音量反转修复)
|
||||
patch_v2/meow_svcd/meow_svcd|/usr/bin/meow_svcd|605646c4cc93f2baf29071ea6bc870ea|服务管理器 M2.77(+崩溃上报 meow_crash agent-187)
|
||||
mips-repo/bins/meow_mdns/bin/meow_mdns|/usr/bin/meow_mdns|d6b0151bda26768f19952dae1342610d|mDNS 应答器 M2.78(启动竞态+换IP重检 agent-194)
|
||||
|
||||
Reference in new issue
Block a user