fix(ncm): 歌单切换两bug — ①暂停态跨歌单点歌旧信息(play同曲护栏改按曲目id判同曲而非裸队列下标,切歌单后同下标换歌被吞play→修play_is_same_song) ②切歌单封面残留(playlist_tick补cover_changed/ack+invalidate重画头块);附带占位行cover_request野id修复;宿主P15/covswitch PASS,热更ncm

This commit is contained in:
AskaEth committed 2026-09-04 00:14:37 +08:00
1 parent 62ec405dca
commit 6eccb17f9b
5 files changed
+150 -17

No files matched your search

+59 -2
View File
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /* unlink(covswitch PPM 清理) */
ncm_app_state_t g_st;
ncm_play_run_t g_play = { .mu = PTHREAD_MUTEX_INITIALIZER,
@@ -83,6 +84,36 @@ static void mock_qr(void)
g_st.login_state = NCM_LOGIN_PENDING;
}
/* Bug1 回归(covswitch):写一张 8x8 纯色 24-bit BMP,供 cover_host_inject 注入两张不同封面
* (stb_image 明确支持 BMP;PPM 在宿主 stb 版本回 NULL → 注入失败)。 */
static int cov_make_bmp(const char *path, unsigned char r, unsigned char g, unsigned char b)
{
FILE *f = fopen(path, "wb");
if (!f) return -1;
int w = 8, h = 8, row = w * 3, img = row * h;
unsigned char hdr[54];
memset(hdr, 0, sizeof hdr);
hdr[0] = 'B'; hdr[1] = 'M';
uint32_t fsz = (uint32_t)(54 + img);
hdr[2] = (unsigned char)(fsz & 0xFF); hdr[3] = (unsigned char)((fsz >> 8) & 0xFF);
hdr[4] = (unsigned char)((fsz >> 16) & 0xFF); hdr[5] = (unsigned char)((fsz >> 24) & 0xFF);
hdr[10] = 54; /* 像素数据偏移 */
hdr[14] = 40; /* BITMAPINFOHEADER 大小 */
uint32_t ww = (uint32_t)w, hh = (uint32_t)h;
hdr[18] = (unsigned char)(ww & 0xFF); hdr[19] = (unsigned char)((ww >> 8) & 0xFF);
hdr[20] = (unsigned char)((ww >> 16) & 0xFF); hdr[21] = (unsigned char)((ww >> 24) & 0xFF);
hdr[22] = (unsigned char)(hh & 0xFF); hdr[23] = (unsigned char)((hh >> 8) & 0xFF);
hdr[24] = (unsigned char)((hh >> 16) & 0xFF); hdr[25] = (unsigned char)((hh >> 24) & 0xFF);
hdr[26] = 1; hdr[28] = 24; /* planes=1, bpp=24 */
hdr[34] = (unsigned char)(img & 0xFF); hdr[35] = (unsigned char)((img >> 8) & 0xFF);
hdr[36] = (unsigned char)((img >> 16) & 0xFF); hdr[37] = (unsigned char)((img >> 24) & 0xFF);
if (fwrite(hdr, 1, 54, f) != 54) { fclose(f); return -1; }
for (int y = 0; y < h; y++) /* 自底向上 BGR */
for (int x = 0; x < w; x++) { fputc(b, f); fputc(g, f); fputc(r, f); }
fclose(f);
return 0;
}
static int page_id(const char *name)
{
if (strcmp(name, "login") == 0) return ACT_LOGIN;
@@ -98,6 +129,7 @@ static int page_id(const char *name)
if (strcmp(name, "plsplay") == 0) return ACT_PLAYLIST; /* mini 栏目检(非播放页+播放态) */
if (strcmp(name, "homeplay") == 0) return ACT_HOME; /* mini 栏目检(首页+播放态) */
if (strcmp(name, "barhit") == 0) return ACT_PLAYLIST; /* mini 栏命中自检 */
if (strcmp(name, "covswitch") == 0) return ACT_PLAYLIST;/* 歌单头块封面随全局封面刷新(Bug1) */
if (strcmp(name, "settings") == 0) return ACT_SETTINGS;
if (strcmp(name, "search") == 0) return ACT_SEARCH;
if (strcmp(name, "searchhist") == 0) return ACT_SEARCH; /* §23 空态=历史列表 */
@@ -149,7 +181,8 @@ int main(int argc, char **argv)
g_st.login_state = NCM_LOGIN_PENDING;
printf("live unikey=%s qr_url=%s size=%d\n", unikey, g_st.qr_url, sz);
}
else if (strcmp(name, "playlist") == 0) { mock_playlists(); mock_songs(); }
else if (strcmp(name, "playlist") == 0 || strcmp(name, "covswitch") == 0)
{ mock_playlists(); mock_songs(); }
else if (strcmp(name, "player") == 0 || strcmp(name, "plcover") == 0 ||
strcmp(name, "pllyric") == 0 || strcmp(name, "gestest") == 0 ||
strcmp(name, "grid") == 0) {
@@ -265,7 +298,7 @@ int main(int argc, char **argv)
if (strcmp(name, "login") == 0 || strcmp(name, "loginlive") == 0) v = login_view_create();
else if (strcmp(name, "home") == 0) v = home_view_create();
else if (strcmp(name, "playlist") == 0 || strcmp(name, "plsplay") == 0 ||
strcmp(name, "barhit") == 0) v = playlist_view_create();
strcmp(name, "barhit") == 0 || strcmp(name, "covswitch") == 0) v = playlist_view_create();
else if (page_id(name) == ACT_PLAYER) v = player_view_create(); /* player/lands/playerbuf/playererr/modetest */
else if (page_id(name) == ACT_QUEUE) v = queue_view_create(); /* §NEW 播放队列页 */
else if (strcmp(name, "settings") == 0) v = settings_view_create();
@@ -314,6 +347,30 @@ int main(int argc, char **argv)
if (page_id(name) == ACT_PLAYER) {
player_tick(meow_ui_time_ms());
}
if (strcmp(name, "covswitch") == 0) {
/* Bug1 回归:歌单页活跃,playlist_tick 须消费 cover_changed(头块封面随全局封面刷新)。
* 修复前 playlist_tick 不判 cover_changed/ack → 注入后 cover_changed 恒 1(头块永不重画,
* 停留上一张);修复后 tick 判变并 ack → 归 0(下次换封面再变 1,再 ack → 收敛到新封面)。 */
int ok = (cov_make_bmp("/tmp/ncm_cov_a.bmp", 220, 40, 40) == 0 &&
cov_make_bmp("/tmp/ncm_cov_b.bmp", 40, 90, 220) == 0);
if (ok) {
cover_host_inject("/tmp/ncm_cov_a.bmp");
int c1 = cover_changed(); /* 注入后:新封面待绘制(gen>acked) */
playlist_tick(0); /* 修复点:消费 */
int c2 = cover_changed(); /* 应 ack 归 0 */
cover_host_inject("/tmp/ncm_cov_b.bmp");
int c3 = cover_changed(); /* 再注入:又待绘制 */
playlist_tick(0);
int c4 = cover_changed(); /* 再 ack 归 0 */
ok = (c1 && !c2 && c3 && !c4);
printf("covswitch: A->changed=%d tick->acked=%d B->changed=%d tickB->acked=%d -> %s\n",
c1, c2, c3, c4, ok ? "PASS" : "FAIL");
} else {
printf("covswitch: init FAIL (bmp write)\n");
}
if (!ok) return 1;
unlink("/tmp/ncm_cov_a.bmp"); unlink("/tmp/ncm_cov_b.bmp");
}
if (strcmp(name, "search") == 0 || strcmp(name, "searchtap") == 0) {
search_submit(g_st.search_query); /* 宿主:应用预置搜索结果 */
}