fix(sdk+launcher): 图标不渲染真根因(agent-219) — meow_ui_img.c scale_buf cover 采样把乘写成除(÷缩放比→采到源图左上角透明区,全丢); 改乘+居中裁剪偏移修正; 宿主旧测试用纯色图掩盖了该bug。+ main_menu App退出/结构变化重绘时 fb_pan_buf0_force 无条件pan回buffer0(防App翻页留buffer1致菜单残帧)

meow_ui.a→3e0ee8f7 launcher→9d0efc2f hello→9609ea6e files→90f5cf07 ncm→be8be221(均已上卡); 真机截图证据 .tmp/meowbug/fix1.png+fix_b2_after.png
This commit is contained in:
MeowOS committed 2026-08-31 15:42:24 +08:00
1 parent 05a19a9ea3
commit ab4da09e75
45 files changed
+1926 -147

No files matched your search

+64
View File
@@ -30,6 +30,11 @@ 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);
@@ -177,6 +182,7 @@ 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;
@@ -207,6 +213,64 @@ void meow_ui_media_stop(void)
pthread_mutex_unlock(&g_mu);
}
/* ---- 物理媒体键 → 系统语义(M2.xx:SDK 输入层接管,App 前台也生效)----
* 物理键是系统资源(APPS.md §3.4.1):播放/暂停/上一曲/下一曲 → 转发到当前媒体会话。
* 本进程注册过 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)
{
switch (code) {
case 164: /* KEY_PLAYPAUSE:切换(依最近上报 state) */
return (last_state == MEOW_UI_MEDIA_STATE_PLAYING) ? 2 : 1;
case 165: case 19: /* KEY_PREVIOUSSONG / 旧码 */
return 3;
case 163: /* KEY_NEXTSONG */
return 4;
default:
return -1;
}
}
/* 控制器路径:发 MSG_PLAYCTL 给 launcher 转发到最近活跃媒体会话(launcher ipc_dispatch
* MSG_PLAYCTL → meow_media_playctl → 下发到当前源 fd)。
* 专门开一条临时连接(不复用媒体源持久连接 g_fd,避免与后台线程 poll/读竞争);
* 无 launcher/断线 → 静默降级(绝不崩)。 */
static void send_playctl_upstream(int cmd, int64_t seek_ms)
{
int fd = connect_path(sock_path());
if (fd < 0) return;
m_playctl_t c;
memset(&c, 0, sizeof c);
c.cmd = (uint32_t)cmd;
c.seek_ms = seek_ms;
if (send_frame(fd, MSG_PLAYCTL, 1, &c, sizeof c) != 0) { close(fd); return; }
/* 读 ACK(best-effort):带 200ms poll,防 launcher 挂死导致输入线程阻塞。 */
struct pollfd p;
p.fd = fd; p.events = POLLIN; p.revents = 0;
if (poll(&p, 1, 200) > 0 && (p.revents & POLLIN)) {
uint8_t rbuf[128];
uint16_t rt;
(void)read_frame(fd, &rt, rbuf, sizeof rbuf);
}
close(fd);
}
/* 物理媒体键按下边沿(val==1 时由输入线程调用;重复/抬起不重复触发)。 */
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);
if (cmd <= 0) return;
if (cb) { cb(cmd, 0); return; } /* 本 App 是媒体源(注册过回调)→ 本地回调 */
send_playctl_upstream(cmd, 0); /* 否则经 IPC 发 launcher 转发到最近活跃会话 */
}
/* 后台线程主体:懒连 + poll 读 launcher 下发 MSG_PLAYCTL → 调 cb。 */
static void *media_thread_main(void *arg)
{