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
@@ -26,6 +26,7 @@ static int g_custom_disc, g_custom_dyn;
|
||||
static int g_landscape;
|
||||
static int g_last_pos_ms, g_last_state, g_last_line, g_last_song;
|
||||
static int g_last_dl, g_last_err; /* 缓冲进度粒度值 / 错误沿(§18) */
|
||||
static int g_last_eff; /* 生效档沿(§20:降级标注出现/消失刷动态带) */
|
||||
static char g_last_meta_id[24]; /* 已上封面的元数据 id(快照滞后 settle 时纠正封面/歌名) */
|
||||
|
||||
/* 运行期几何(player_compute_geom 填充;各带绘制物/命中共用)。 */
|
||||
@@ -232,6 +233,22 @@ static void plr_draw_dyn(void *ctx)
|
||||
meow_ui_fill_rect(g_bar.x, g_bar.y, g_bar.w, g_bar.h, th->surfaceVariant);
|
||||
meow_ui_fill_rect(g_bar.x, g_bar.y, (int)((int64_t)g_bar.w * frac / 1000), g_bar.h, pa->red);
|
||||
|
||||
/* §20:实际生效音质档(与用户档不同时小字标注「已降级至 xx」;缓冲期未定不显示)。
|
||||
* 位置:时间行中部(左右是时间戳,中央留白),竖/横屏同一条带。 */
|
||||
{
|
||||
int eff = player_manager_eff_level();
|
||||
if (have && eff >= 0 && player_manager_state() != NCM_PC_STOPPED) {
|
||||
char qb[72];
|
||||
if (eff != g_st.level)
|
||||
snprintf(qb, sizeof qb, "已降级至 %s", ncm_level_name(eff));
|
||||
else
|
||||
snprintf(qb, sizeof qb, "%s", ncm_level_name(eff));
|
||||
int qcx = g_landscape ? (g_bar.x + g_bar.w / 2) : (r_cont.x + r_cont.w / 2);
|
||||
uint32_t qc = (eff != g_st.level) ? pa->red : th->onSurfaceVariant;
|
||||
meow_ui_text_center(qcx, g_times_y, qb, 18, qc);
|
||||
}
|
||||
}
|
||||
|
||||
int st = player_manager_state();
|
||||
draw_ctl(g_cprev_x, g_ctl_y, g_cr - 6, 0, th->surfaceContainer, th->onSurface);
|
||||
/* 暂停/停止(出错待重试)都画「播放」三角;播放/缓冲画暂停符 */
|
||||
@@ -248,7 +265,8 @@ static void plr_draw_dyn(void *ctx)
|
||||
int perr = player_manager_error();
|
||||
if (perr != 0) {
|
||||
/* §18:播放错误明示(旧版 err 无 UI 消费者 → 失败无声死等) */
|
||||
const char *em = (perr == NCM_ERR_NOTFOUND) ? "无法播放:无音源(VIP/版权)"
|
||||
const char *em = (perr == NCM_ERR_VIP) ? "VIP 专享,开通会员后可播放"
|
||||
: (perr == NCM_ERR_NOTFOUND) ? "无法播放:无音源(VIP/版权)"
|
||||
: (perr == NCM_ERR_AUTH) ? "登录已过期,请重新登录"
|
||||
: "加载失败,请检查网络";
|
||||
meow_ui_text_center(lcx, center_y - 20, em, 20, pa->red);
|
||||
@@ -423,7 +441,14 @@ void player_tick(uint64_t now)
|
||||
if (perr != g_last_err) {
|
||||
g_last_err = perr;
|
||||
meow_ui_invalidate(g_dyn_r.x, g_dyn_r.y, g_dyn_r.w, g_dyn_r.h);
|
||||
if (perr) ncm_snack("播放失败");
|
||||
if (perr == NCM_ERR_VIP) ncm_snack("VIP 专享歌曲");
|
||||
else if (perr) ncm_snack("播放失败");
|
||||
}
|
||||
/* §20:生效档变化(降级判定完成/切歌重置)刷动态带。 */
|
||||
int eff = player_manager_eff_level();
|
||||
if (eff != g_last_eff) {
|
||||
g_last_eff = eff;
|
||||
meow_ui_invalidate(g_dyn_r.x, g_dyn_r.y, g_dyn_r.w, g_dyn_r.h);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,7 +465,7 @@ static void plr_page_create(meow_view *v, void *ctx)
|
||||
g_custom_dyn = meow_draw_custom_register(11, g_dyn_r.x, g_dyn_r.y, g_dyn_r.w, g_dyn_r.h,
|
||||
plr_draw_dyn, NULL);
|
||||
g_last_pos_ms = -1; g_last_state = -1; g_last_line = -1; g_last_song = -1;
|
||||
g_last_dl = -1; g_last_err = 0;
|
||||
g_last_dl = -1; g_last_err = 0; g_last_eff = -2; /* -2: 与 eff=-1(未定) 区分,首 tick 必刷 */
|
||||
g_last_meta_id[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user