fix(ncm): 三连修 — 封面切歌不更新/缓冲无反馈失败无声/暂停切歌边界 (REPORT §18)

- cover worker 忙等死循环(成功后不清目标,每圈解码+换入+gen++,CPU 100%+每帧整盘重绘)
  → 成功清目标转怠速; 失败指数退避 0.5-4s 连 8 次放弃+WARN 日志; 去重加在拉目标;
  cover_get 持锁+cover_put 修绘制期 UAF; g_host_mock 防真网守卫
- 封面兜底污染修复: 不再把单曲 al_pic 写进 g_st.cover_url(否则 al_pic 缺失曲回落成
  上一首封面且撞去重 → 封面永停); plr_page_enter 强制重估自愈; pl_page_enter 回填歌单封面
- 缓冲 UI: BUFFER 态「缓冲中… N%」(g_play.dl_done/total, 下载回调累加); 播放错误中文
  错误条+snack(旧版 err 无 UI 消费者=无声死等); STOPPED 态播放键=重试; play/next 清 err
- 写失败 set_err 修连环跳歌(旧版静默 break 被外层当自然播完,流死时跳完歌单+狂发 song_url);
  still_current 护栏修下载途中切歌的状态/快照过期覆盖
- 验证(0 真实请求): cover_chain_sim 7 组+player_flow_sim P1-P5 全 PASS, 旧代码对照
  T2/P2/P4 必败坐实根因; audiod_chain_sim 14/14; pagination/window/core+qemu 回归 PASS;
  宿主+mipsel 自有代码 0 warning; 9 页离屏渲染 rc=0 (含新 mock 页 playerbuf/playererr)
- ncm md5 50d41bbf4a379e925699ba013b997ffd (未部署真机, 留主会话)
This commit is contained in:
MeowOS committed 2026-09-01 05:29:09 +08:00
1 parent 614694ad4a
commit 6200a41b71
13 files changed
+820 -20

No files matched your search

+23 -2
View File
@@ -90,6 +90,8 @@ static int page_id(const char *name)
if (strcmp(name, "playlist") == 0) return ACT_PLAYLIST;
if (strcmp(name, "player") == 0) return ACT_PLAYER;
if (strcmp(name, "lands") == 0) return ACT_PLAYER; /* 横屏布局 */
if (strcmp(name, "playerbuf") == 0) return ACT_PLAYER; /* §18 缓冲态 */
if (strcmp(name, "playererr") == 0) return ACT_PLAYER; /* §18 错误态 */
if (strcmp(name, "settings") == 0) return ACT_SETTINGS;
if (strcmp(name, "search") == 0) return ACT_SEARCH;
return -1;
@@ -146,6 +148,25 @@ int main(int argc, char **argv)
g_play.play_song = g_st.songs[0]; /* 播放快照(§17) */
g_play.play_song_valid = 1;
pthread_mutex_unlock(&g_play.mu);
} else if (strcmp(name, "playerbuf") == 0) { /* §18:缓冲态(25% 下载进度) */
mock_playlists(); mock_songs();
pthread_mutex_lock(&g_play.mu);
g_play.state = NCM_PC_BUFFER;
g_play.cur_song = 0;
g_play.play_song = g_st.songs[0];
g_play.play_song_valid = 1;
g_play.dl_done = 1048576;
g_play.dl_total = 4194304;
pthread_mutex_unlock(&g_play.mu);
} else if (strcmp(name, "playererr") == 0) { /* §18:错误态(无音源) */
mock_playlists(); mock_songs();
pthread_mutex_lock(&g_play.mu);
g_play.state = NCM_PC_STOPPED;
g_play.cur_song = 0;
g_play.play_song = g_st.songs[0];
g_play.play_song_valid = 1;
g_play.err = NCM_ERR_NOTFOUND;
pthread_mutex_unlock(&g_play.mu);
} else if (strcmp(name, "settings") == 0) {
g_st.logged_in = 1;
ncm_strlcpy(g_st.nickname, "Tester", sizeof g_st.nickname);
@@ -181,7 +202,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) v = playlist_view_create();
else if (strcmp(name, "player") == 0 || strcmp(name, "lands") == 0) v = player_view_create();
else if (page_id(name) == ACT_PLAYER) v = player_view_create(); /* player/lands/playerbuf/playererr */
else if (strcmp(name, "settings") == 0) v = settings_view_create();
else if (strcmp(name, "search") == 0) v = search_view_create();
if (!v) { fprintf(stderr, "bad page\n"); return 1; }
@@ -192,7 +213,7 @@ int main(int argc, char **argv)
meow_view_page_push(pid);
/* player 页:其 on_tick 通常驱动进度;这里直接再画一次确保状态就绪 */
meow_ui_paint_full();
if (strcmp(name, "player") == 0 || strcmp(name, "lands") == 0) {
if (page_id(name) == ACT_PLAYER) {
player_tick(meow_ui_time_ms());
}
if (strcmp(name, "search") == 0) {