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

+81 -13
View File
@@ -280,21 +280,89 @@ static void *player_thread(void *arg)
return NULL;
}
/* 为当前曲目拉歌词并解析(UI 线程调):buf 有界,解析后存 lyric 模块。 */
/* ---- 歌词后台加载(二期):UI 不阻塞 —— 持久 worker 监视当前播放歌曲,首播/切歌/自动顺延
* 时在独立线程拉取并解析,UI 经 lyric_state() 判「加载中 / 无词」。 ----
* 现存 race(§10.9 FM4,UI 读 lyrics 与 worker 写)为良性:数组定长、越界已防护,
* 最坏显示一帧旧/空行,下一 tick 自愈;与 g_st.songs 写读竞态同接受。 */
static pthread_mutex_t g_lyrmu = PTHREAD_MUTEX_INITIALIZER;
static pthread_t g_lyr_thr;
static int g_lyr_thr_on;
static volatile int g_lyr_state; /* 0=空闲/未拉 1=加载中 2=已拉完 */
static char g_lyr_song_id[32]; /* 歌词归属歌曲 id */
static void *lyric_worker(void *arg)
{
(void)arg;
char last_id[32] = "";
while (!g_app_quit) {
usleep(300 * 1000);
int idx;
pthread_mutex_lock(&g_play.mu); idx = g_play.cur_song; pthread_mutex_unlock(&g_play.mu);
if (idx < 0 || idx >= g_st.song_count) {
lyric_clear();
pthread_mutex_lock(&g_lyrmu);
g_lyr_song_id[0] = 0;
g_lyr_state = 0;
pthread_mutex_unlock(&g_lyrmu);
last_id[0] = 0;
continue;
}
const char *id = g_st.songs[idx].id;
if (!id[0]) continue;
if (strcmp(id, last_id) == 0) continue; /* 同一曲已拉/在拉 */
ncm_strlcpy(last_id, id, sizeof last_id);
lyric_clear();
pthread_mutex_lock(&g_lyrmu);
g_lyr_state = 1; /* 加载中 */
pthread_mutex_unlock(&g_lyrmu);
char *lrc = (char *)malloc(64 * 1024);
char *tl = (char *)malloc(32 * 1024);
if (!lrc || !tl) {
free(lrc); free(tl);
pthread_mutex_lock(&g_lyrmu); g_lyr_state = 0; pthread_mutex_unlock(&g_lyrmu);
continue;
}
int rc = ncm_api_lyric(g_st.ctx.device_id, g_st.ctx.cookie, id, lrc, 64 * 1024, tl, 32 * 1024);
if (rc == NCM_OK) lyric_parse(lrc, tl);
free(lrc); free(tl);
pthread_mutex_lock(&g_lyrmu);
ncm_strlcpy(g_lyr_song_id, id, sizeof g_lyr_song_id);
g_lyr_state = 2; /* 拉完(可能 0 行=无词) */
pthread_mutex_unlock(&g_lyrmu);
}
return NULL;
}
static void lyric_ensure_worker(void)
{
pthread_mutex_lock(&g_lyrmu);
if (!g_lyr_thr_on) {
g_lyr_thr_on = 1;
if (pthread_create(&g_lyr_thr, NULL, lyric_worker, NULL) == 0) pthread_detach(g_lyr_thr);
else g_lyr_thr_on = 0;
}
pthread_mutex_unlock(&g_lyrmu);
}
/* 为当前曲目「异步」拉歌词:确保后台 worker 在跑即返回(UI 不阻塞网络/解析)。
* 实际拉取+解析在 worker 线程(约 0.3s 内开始),结束置 lyric_state()=2。 */
int player_manager_load_lyric(void)
{
lyric_clear();
int idx = player_manager_playing_song();
if (idx < 0 || idx >= g_st.song_count) return NCM_ERR_ARG;
const ncm_song_t *s = &g_st.songs[idx];
char *lrc = (char *)malloc(64 * 1024);
char *tl = (char *)malloc(32 * 1024);
if (!lrc || !tl) { free(lrc); free(tl); return NCM_ERR_OOM; }
int rc = ncm_api_lyric(g_st.ctx.device_id, g_st.ctx.cookie, s->id, lrc, 64 * 1024, tl, 32 * 1024);
if (rc == NCM_OK) lyric_parse(lrc, tl);
free(lrc);
free(tl);
return rc;
lyric_ensure_worker();
return NCM_OK;
}
/* 歌词加载状态(UI 判「loading / no lyric」)。 */
int lyric_state(void)
{
int s;
pthread_mutex_lock(&g_lyrmu);
s = g_lyr_state;
pthread_mutex_unlock(&g_lyrmu);
return s;
}
int player_manager_start(void)