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

+36 -18
View File
@@ -117,35 +117,53 @@ int appstate_load_playlists(void)
return rc;
}
int appstate_load_playlist_songs(int idx)
int appstate_load_playlist_songs_page(int idx, int offset, int limit)
{
if (idx < 0 || idx >= g_st.playlist_count) return NCM_ERR_ARG;
/* 不在此处写 g_st.active_playlist:调用方(playlist_open/UI)已在 UI 线程设定;
* 若后台 worker 在此改写,会覆盖用户已切换到的新歌单,造成“打开 B 却显示 A”。 */
const ncm_playlist_t *pl = &g_st.playlists[idx];
if (limit <= 0 || limit > NCM_SONG_BATCH) limit = NCM_SONG_BATCH;
if (offset < 0) offset = 0;
int idn = 0;
int rc = ncm_api_playlist_detail(g_st.ctx.device_id, g_st.ctx.cookie, pl->id,
NULL, 0, NULL, 0, g_st.song_ids, NCM_SONG_MAX, &idn);
if (rc != NCM_OK) { g_st.song_count = 0; return rc; }
/* 二期:改走 /api/playlist/track/all 服务端分页(REPORT §11)。
* 相对旧 /v6/playlist/detail 的「全量 trackIds(5191 首 ≈900KB)」本端点直接按页返回歌曲
* 对象(含 al.picUrl),无需 detail 瓶颈 + 二次 song_detail。 */
ncm_song_t tmp[NCM_SONG_BATCH];
int n = 0; int64_t total = 0;
int rc = ncm_api_playlist_track_all(g_st.ctx.device_id, g_st.ctx.cookie, pl->id,
offset, limit, tmp, NCM_SONG_BATCH, &n, &total);
if (rc != NCM_OK) { if (offset == 0) g_st.song_count = 0; return rc; }
memset(g_st.songs, 0, sizeof g_st.songs);
int outn = 0;
for (int off = 0; off < idn; off += NCM_SONG_BATCH) {
int batch = idn - off;
if (batch > NCM_SONG_BATCH) batch = NCM_SONG_BATCH;
int bn = 0;
rc = ncm_api_song_detail(g_st.ctx.device_id, g_st.ctx.cookie, &g_st.song_ids[off],
batch, &g_st.songs[off], NCM_SONG_MAX - off, &bn);
if (rc != NCM_OK) break;
outn += bn;
if (bn < batch) break;
}
g_st.song_count = outn;
if (offset == 0) g_st.song_count = 0; /* 重头:清空旧歌单(含此前打开的另一歌单) */
/* 追加到 g_st.songs[offset..],封顶 NCM_SONG_MAX(内存纪律) */
int cap = NCM_SONG_MAX - offset;
if (cap <= 0) return NCM_OK;
if (n > cap) n = cap;
memcpy(&g_st.songs[offset], tmp, sizeof(ncm_song_t) * (size_t)n);
int end = offset + n;
if (end > NCM_SONG_MAX) end = NCM_SONG_MAX;
g_st.song_count = end;
appstate_apply_playlist_cover(idx);
return NCM_OK;
}
int appstate_load_playlist_songs(int idx)
{
/* 兼容入口:整批载入(内部按页循环到 NCM_SONG_MAX 或歌单尾部)。 */
int rc, loaded = 0;
do {
rc = appstate_load_playlist_songs_page(idx, loaded, NCM_PLAYLIST_PAGE);
if (rc != NCM_OK) return rc;
int before = loaded;
loaded = g_st.song_count;
if (loaded - before < NCM_PLAYLIST_PAGE) break; /* 尾部:已载完 */
if (loaded >= NCM_SONG_MAX) break;
} while (1);
return NCM_OK;
}
void appstate_apply_playlist_cover(int idx)
{
if (idx < 0 || idx >= g_st.playlist_count) return;
+18 -2
View File
@@ -16,6 +16,22 @@ static char s_txt[NCM_LYRIC_LINES][LRC_MAX_TEXT];
static char s_tl[NCM_LYRIC_LINES][LRC_MAX_TEXT];
static int s_n;
/* 复制一行歌词正文 n 字节到 dst,把「字面反斜杠 n/r」序列(服务器用 \n 把多行文本塞进一行,
* 字面 \n 渲染成豆腐块/凌乱)替换为空格;顺带容忍 \r\n。有界 ≤max。 */
static void copy_lrc_text(char *dst, const char *src, size_t n, size_t max)
{
size_t oi = 0, si = 0;
while (si < n && oi < max - 1) {
if (src[si] == '\\' && si + 1 < n && (src[si + 1] == 'n' || src[si + 1] == 'r')) {
dst[oi++] = ' ';
si += 2;
} else {
dst[oi++] = src[si++];
}
}
dst[oi] = 0;
}
static void lrc_parse(const char *lrc, int is_trans)
{
if (!lrc) return;
@@ -55,14 +71,14 @@ static void lrc_parse(const char *lrc, int is_trans)
/* 翻译行:按 first_ms 匹配到已有原文行 */
for (int i = 0; i < s_n; i++) {
if (s_t[i] == first_ms) {
memcpy(s_tl[i], p, len); s_tl[i][len] = 0;
copy_lrc_text(s_tl[i], p, len, LRC_MAX_TEXT);
break;
}
}
} else {
if (s_n < NCM_LYRIC_LINES) {
s_t[s_n] = first_ms;
memcpy(s_txt[s_n], p, len); s_txt[s_n][len] = 0;
copy_lrc_text(s_txt[s_n], p, len, LRC_MAX_TEXT);
s_tl[s_n][0] = 0;
s_n++;
}