feat(ncm §20): 音质体系全量——八档UI/VIP检测缓存/逐级降级下首恢复/fee门禁/默认极高HQ
- core: 9档枚举(顺序=降级链, DOLBY映射保留不进UI/链) + level_key(sky/sky_c51)
+ level_gate(CVIP/SVIP门槛) + song_url surround档附加immerseType=c51
+ song_url_auto全档表降级(out_level回填/响应level静默降档采信/try_fn可注入)
+ vip_info(weapi v2优先v1兜底) + parse_vip_info离线可测 + NCM_ERR_VIP(-15)
- app/logic/account.c(新): account.json会员态缓存(uid/nick/vip/双expire/checked_at)
刷新=登录后/超1天/到期后各一次不轮询; account_vip本地到期降档视图
- player_manager: 用户档按会员钳顶后逐级降级(不硬拒,缓存键仍用户档),
fee∈{1,4}且非会员→NCM_ERR_VIP零请求(缓存命中优先), eff_level回填
- UI: 设置页八档(规格+门槛+未解锁标注,允许选定), 播放页时间行中央
生效档/已降级至xx小字, VIP专享文案; 默认档Hi-Res→极高HQ(存量设置保留)
- 验证(0真实请求): degrade_sim 90例矩阵全PASS; player_flow_sim P1-P8全PASS;
test_ncm_core vip解析9例宿主+qemu全PASS; 窗口/分页/缓存/封面/audiod sim全PASS;
mipsel -Wall -Wextra 0 warning; 6页离屏rc=0。未部署真机(留主会话)
This commit is contained in:
1 parent
ab4dfb4f9c
commit
bdd9e898f4
23 files changed
+1026
-70
No files matched your search
@@ -35,6 +35,8 @@ int appstate_init(void)
|
||||
meow_config_get("ncm.uid", g_st.uid, sizeof g_st.uid);
|
||||
meow_config_get("ncm.nickname", g_st.nickname, sizeof g_st.nickname);
|
||||
|
||||
account_load(); /* §20:恢复会员态缓存(account.json;无文件则 NCM_VIP_NONE) */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -44,9 +46,11 @@ void appstate_load_settings(void)
|
||||
if (g_st.cache_limit_gb < 1) g_st.cache_limit_gb = 1;
|
||||
if (g_st.cache_limit_gb > 100) g_st.cache_limit_gb = 100;
|
||||
|
||||
g_st.level = meow_config_int("ncm.level", NCM_LEVEL_HIRES);
|
||||
if (g_st.level < NCM_LEVEL_STANDARD || g_st.level > NCM_LEVEL_HIRES)
|
||||
g_st.level = NCM_LEVEL_HIRES;
|
||||
/* §20 默认档 = 极高 HQ(EXHIGH,用户定案 NCM_CACHE_DESIGN §3;旧默认 Hi-Res 改掉)。
|
||||
* 已持久化的合法旧值(含 HIRES 等)原样保留;越界值回落默认档。 */
|
||||
g_st.level = meow_config_int("ncm.level", NCM_LEVEL_EXHIGH);
|
||||
if (g_st.level < NCM_LEVEL_STANDARD || g_st.level > NCM_LEVEL_UI_MAX)
|
||||
g_st.level = NCM_LEVEL_EXHIGH;
|
||||
|
||||
ncm_cache_set_limit_gb(&g_st.ctx.cache, g_st.cache_limit_gb);
|
||||
g_st.ctx.default_level = g_st.level;
|
||||
@@ -81,6 +85,14 @@ void appstate_logout(void)
|
||||
g_st.logged_in = 0;
|
||||
g_st.uid[0] = 0;
|
||||
g_st.nickname[0] = 0;
|
||||
g_st.vip = NCM_VIP_NONE; /* §20:登出清会员态(下一账号不继承) */
|
||||
g_st.vip_expire_ms = 0;
|
||||
g_st.vip_checked_at = 0;
|
||||
{
|
||||
char ap[600];
|
||||
snprintf(ap, sizeof ap, "%s/account.json", g_st.data_dir);
|
||||
remove(ap);
|
||||
}
|
||||
g_st.active_playlist = -1;
|
||||
g_st.playing_song = -1;
|
||||
pthread_mutex_lock(&g_song_mu);
|
||||
@@ -435,9 +447,10 @@ static int autoplay_try_playlist(int pl)
|
||||
for (int i = 0; i < g_st.track_ids_count; i++) { /* 滑窗模型:锁内拷贝窗内有效槽 */
|
||||
ncm_song_t s;
|
||||
if (appstate_song_copy(i, &s) != 0) break; /* 出窗即停(首页之后未物化) */
|
||||
/* §19 缓存键 = id+档位:先试当前档位键(flac/mp3),再回退旧无档位键(存量 mp3) */
|
||||
/* §19 缓存键 = id+档位(§20 起用 level_key:sky 与 sky_c51 可区分):
|
||||
* 先试当前档位键(flac/mp3),再回退旧无档位键(存量 mp3) */
|
||||
char key[64];
|
||||
snprintf(key, sizeof key, "%s_%s", s.id, ncm_api_level_str(g_st.level));
|
||||
snprintf(key, sizeof key, "%s_%s", s.id, ncm_api_level_key(g_st.level));
|
||||
if (ncm_cache_lookup(&g_st.ctx.cache, key, "flac", cpath, sizeof cpath) == NCM_OK ||
|
||||
ncm_cache_lookup(&g_st.ctx.cache, key, "mp3", cpath, sizeof cpath) == NCM_OK ||
|
||||
ncm_cache_lookup(&g_st.ctx.cache, s.id, "mp3", cpath, sizeof cpath) == NCM_OK) {
|
||||
|
||||
Reference in new issue
Block a user