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

+35 -9
View File
@@ -156,20 +156,46 @@ void player_manager_set_quality(int level, int cache_gb)
pthread_mutex_unlock(&g_play.mu);
}
/* 同曲重入护栏的「同曲」判据(任务:跨歌单切换后,同一队列下标指向的是**另一首歌**)。
* 裸下标(song_idx==cur_song)在换歌单(播放队列内容变化)后不再成立——实测真机日志
* 「play: re-enter current idx=0 state=2 -> no restart」:A 停在 idx=0,切到 B 后点 idx=0
* 被当「点正在播的曲」吞掉 → 新歌永不起播、播放页停在上首+暂停;恢复播放(旧曲播完自动顺延
* 到不同下标)后才正常切换。故改以「候选曲 id == 正在播快照 id」判同曲:确证同曲才免重播
* 聚焦;候选未物化/队列已换(id 不符)→ 非确证,按新播放意图起播(正确方向)。
* 候选经 appstate_song_copy/appstate_search_song 做**廉价窗/数组拷贝**,绝不触网络
* (占位行未物化即返回 0,交下方正常起播)。不持 g_play.mu 调用(内部自锁读快照 id)。 */
static int play_is_same_song(int song_idx)
{
ncm_song_t cand;
int have = (appstate_get_queue() == NCM_QUEUE_SEARCH)
? (appstate_search_song(song_idx, &cand) == NCM_OK)
: (appstate_song_copy(song_idx, &cand) == NCM_OK);
if (!have || !cand.id[0]) return 0; /* 未物化:不能确证同曲 → 交下方正常起播 */
pthread_mutex_lock(&g_play.mu);
int same = g_play.play_song_valid && g_play.play_song.id[0] &&
strcmp(cand.id, g_play.play_song.id) == 0;
pthread_mutex_unlock(&g_play.mu);
return same;
}
void player_manager_play(int song_idx)
{
pthread_mutex_lock(&g_play.mu);
/* 任务3:点「正在播的曲」(同 idx 且 PLAYING/PAUSED,非切档重播)→ 只聚焦不重播:
* 不 seq++、不置 BUFFER——旧曲继续出声/停原状态,UI 由调用方 nav 到播放页。
* 注意:set_quality 已置 g_pending_replay=1(切音质后重播同曲须换档,P12),此护栏放行。
* 非 PLAYING/PAUSED(STOPPED/另一曲)不受影响,照旧起播。 */
if (song_idx == g_play.cur_song && !g_pending_replay &&
(g_play.state == NCM_PC_PLAYING || g_play.state == NCM_PC_PAUSED)) {
pthread_mutex_unlock(&g_play.mu);
meow_log(MEOW_LOG_INFO, "play: re-enter current idx=%d state=%d -> no restart",
song_idx, g_play.state);
int is_cur = (song_idx == g_play.cur_song);
int pending = g_pending_replay;
int st = g_play.state;
pthread_mutex_unlock(&g_play.mu);
/* 任务3:点「正在播的曲」→ 只聚焦不重播;**但以曲目身份(id)而非裸下标判定**——跨歌单
* 切换后同一队列下标已指向另一首歌(真实日志 `play: re-enter current idx=0` 误吞跨歌单
* 点歌),故在 PLAYING/PAUSED 且同下标时再校验候选曲 == 正在播快照:同曲才免重播,
* 不同曲(队列已换)/未物化 → 照常起播。注意:set_quality 已置 g_pending_replay=1
* (切音质后重播同曲须换档,P12),此护栏放行。非 PLAYING/PAUSED 不受影响,照旧起播。 */
if (is_cur && !pending && (st == NCM_PC_PLAYING || st == NCM_PC_PAUSED) &&
play_is_same_song(song_idx)) {
meow_log(MEOW_LOG_INFO, "play: re-enter current idx=%d -> no restart", song_idx);
return;
}
pthread_mutex_lock(&g_play.mu);
g_pending_replay = 0; /* 消费掉(新播放意图落地,后续同曲 tap 恢复「只聚焦」) */
g_play.cur_song = song_idx;
g_play.cmd = 0;