fix(ncm §33): 流媒专项批六项——流式SIGSEGV防御日志/档位保真(无损级必须flac+显示档按实际)/封面4xx不重试/收藏显隐/缓存命名迁移/topbar位图图标
- §2① ncm_api.c level_attempt: 无损级(hires/lossless及以上)命中必须 type=flac,返回 mp3 视为该档不可用续降 (修「hires 档静默给 mp3 被当命中」) - §2② player_manager.c eff_level_for_resp: 显示档按响应实际格式/码率——mp3 绝不显示 Hi-Res(≤128k→标准, 否则极高), flac 采信链 eff; br 未知钳 ≤EXHIGH - §1 流式 SIGSEGV(《十面埋伏》sig=11) 审计+UBSAN 探针未复现 → 落地防御日志(dl start/done/interrupt + play done fin/exp/fail/underrun) - §3 cover.c: download_cover 回填 rc/status; 确定性 4xx(404等)不重试立即跳下一张, 仅瞬时错误退避(rc=%d status=%d 日志) - §4 playlist.c: pl_show_fav 我创建(is_collected==0)隐藏收藏钮, 我收藏保留, 搜索歌单保守显示(评论槽并入无空洞) - §5 ncm_cache.c 双点→单点迁移 + player_manager song_local_file 旧键→当前档位键(不重下) - §6 home.c: topbar 动作 ⚙↻⌕ 迁移 sb_icons 位图(meow_topappbar_set_item_icon, 修 4k 字库豆腐) - 测试: test_ncm_core 新 test_grade_flac_gate + test_cache 双点迁移断言; degrade_sim/player_flow_sim 桩 flac 化 - 验证: stream/player_flow/window/search/cache_evict/degrade sim 全 PASS + test_ncm_core host+mipsel(qemu) + mem_sim + build_ncm.sh 0 warning - 新 ncm md5 cb818786 (text 1017110/bss 1362500), 未部署留主会话; 0 真实 NCM 业务请求
This commit is contained in:
1 parent
68ce46a5d8
commit
44a790dc1d
13 files changed
+425
-24
No files matched your search
@@ -329,11 +329,17 @@ static int level_attempt(const char *device_id, const char *cookie, const char *
|
||||
if (rc != NCM_OK) return 0;
|
||||
int ok = ncm_streq(p.type, "mp3") || ncm_streq(p.type, "flac");
|
||||
if (!p.type[0]) {
|
||||
ok = 1;
|
||||
const char *dot = strrchr(p.url, '.');
|
||||
if (dot && ncm_streq(dot, ".flac")) ncm_strlcpy(p.type, "flac", sizeof p.type);
|
||||
else ncm_strlcpy(p.type, "mp3", sizeof p.type); /* 默认 mp3(原语义),供格式门槛判定 */
|
||||
ok = 1;
|
||||
}
|
||||
if (!(p.url[0] && ok)) return 0; /* url 为 null 或未知格式:继续降级 */
|
||||
/* §档位保真(REPORT §NEW 任务2①):SQ 及以上(lossless/hires/母带/全景声)
|
||||
* 命中判定必须 type=flac——无损/Hi-Res 等档返回 mp3 一律视为「该档不可用」继续降级
|
||||
* (服务端静默降档场景,修「hires 档静默给 mp3 被当命中」);mp3 只在
|
||||
* <lossless(standard/higher/exhigh)接受(mp3 码率上限即极高,不可能达无损档)。 */
|
||||
if (lv >= NCM_LEVEL_LOSSLESS && ncm_streq(p.type, "mp3")) return 0;
|
||||
*out = p;
|
||||
if (out_level) {
|
||||
int rl = level_from_str(p.level);
|
||||
|
||||
@@ -88,12 +88,26 @@ int ncm_cache_lookup(const ncm_cache_t *c, const char *id, const char *ext,
|
||||
struct stat st;
|
||||
if (stat(path, &st) != 0 || !S_ISREG(st.st_mode)) {
|
||||
/* §19 温和兼容:历史双点名 `song_<id>..<ext>`(旧版 ext 带前导点所致)。
|
||||
* 命中照常刷新 LRU;不主动改名/删除,由 LRU 自然淘汰。 */
|
||||
* REPORT §NEW 任务5:命中即**迁移重命名**到单点名(同 id+ext,不重下)——
|
||||
* 之后本条目走单点主路径,双点存量自然消亡(lookup/evict 定期见到)。 */
|
||||
const char *e = ext;
|
||||
if (e && e[0] == '.') e++;
|
||||
int n = snprintf(path, sizeof path, "%s/song_%s..%s", c->dir, id, e ? e : "bin");
|
||||
const char *ee = e ? e : "bin";
|
||||
int n = snprintf(path, sizeof path, "%s/song_%s..%s", c->dir, id, ee);
|
||||
if (n < 0 || (size_t)n >= sizeof path) return NCM_ERR_FULL;
|
||||
if (stat(path, &st) != 0 || !S_ISREG(st.st_mode)) return NCM_ERR_NOENT;
|
||||
char fixed[NCM_CACHE_DIR_MAX + 32];
|
||||
if (ncm_cache_path(c, id, ee, fixed, sizeof fixed) == NCM_OK) {
|
||||
struct stat fst;
|
||||
if (stat(fixed, &fst) == 0) unlink(path); /* 目标已(在/被并发建):删旧双点 */
|
||||
else rename(path, fixed);
|
||||
if (stat(fixed, &st) == 0 && S_ISREG(st.st_mode)) {
|
||||
ncm_strlcpy(path, fixed, sizeof path);
|
||||
} else {
|
||||
ncm_strlcpy(path, fixed, sizeof path); /* 迁移失败(权限等):回到固定路径 */
|
||||
return NCM_ERR_NOENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
utime(path, NULL); /* 刷新最后访问(按 mtime LRU) */
|
||||
ncm_strlcpy(out, path, out_sz);
|
||||
|
||||
Reference in new issue
Block a user