fix(ncm): 启动卡顿+大歌单+No tracks 三连修 (agent-209) — ①home/playlist 加载改后台 worker ②大歌单 detail n=1(tracks瘦身)+响应cap 2MB ③song_detail c数组引号转义 ④P0: MIPS32 long=32位歌曲id溢出→int64 ⑤eapi批缓冲2048→4096

ncm→f6bd765a 已部署; 真机验证(风控合规): 小歌单✓ 大歌单256首✓ 启动不卡✓; 已知: 大歌单首屏~30s(二期改分页端点)
This commit is contained in:
MeowOS committed 2026-08-31 09:43:35 +08:00
1 parent a651df0e9b
commit 4cec476dd9
16 files changed
+344 -36

No files matched your search

+66 -10
View File
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
typedef struct { meow_view *view; int active; } home_ctrl;
static home_ctrl g_hc;
@@ -18,9 +19,19 @@ static meow_widget *g_list;
static ncm_rect_t r_cont, r_list;
static int g_empty_id, g_footer_id;
static char g_title[128];
static int g_load_err; /* 0=ok;负=错误码 */
static volatile int g_load_err; /* 0=ok;负=错误码(worker 写,UI draw 读) */
static int g_press_row, g_press_delta, g_dragging, g_drag_last_y;
/* 歌单加载后台 worker:网络(ensure_uid + user_playlist)从 UI 线程挪出,
* 使冷启动/进 home 立即出界面,再异步填列表。gen 代际作“完成”信号(对齐 cover.c)。
* 单核 MIPS,gen 在数据写完后置位,UI 见 gen 变化才重建列表,避免半成品。 */
static pthread_mutex_t g_home_mu = PTHREAD_MUTEX_INITIALIZER;
static pthread_t g_home_thr;
static int g_home_thr_on; /* 1=worker 在跑(防重复 spawn) */
static volatile int g_home_gen; /* worker 完成代数 */
static int g_home_acked; /* UI 已消费的代数 */
static volatile int g_home_loading; /* 1=加载中(draw 显示 LOADING) */
static void home_drag_reset(void)
{
g_press_row = -1;
@@ -52,6 +63,10 @@ static void home_draw_empty(void *ctx)
(void)ctx;
if (meow_ui_activity_active() != ACT_HOME) return;
if (g_load_err == 0 && g_st.playlist_count != 0) return;
if (g_home_loading) {
ncm_draw_empty(r_list, "LOADING", "fetching playlists...");
return;
}
if (g_st.logged_in == 0)
ncm_draw_empty(r_list, "NOT SIGNED IN", "sign in first");
else if (g_load_err == NCM_ERR_AUTH)
@@ -76,16 +91,9 @@ static void home_draw_footer(void *ctx)
ncm_draw_footer(r_cont, foot);
}
void home_reload(void)
/* 把当前 playlist_count/昵称刷进列表 + 标题,并整帧重绘(UI 线程)。 */
static void home_apply(void)
{
g_load_err = 0;
int rc = 0;
if (g_host_mock) { /* 宿主/测试:跳过网络,用预置数据 */
rc = 0;
} else if (!g_st.logged_in) rc = NCM_ERR_AUTH;
else rc = appstate_load_playlists();
g_load_err = rc;
if (g_load_err != 0) g_st.playlist_count = 0;
if (g_list) {
meow_listview_set_count(g_list, g_st.playlist_count);
meow_listview_set_scroll(g_list, 0);
@@ -99,6 +107,54 @@ void home_reload(void)
meow_ui_paint_full();
}
/* 后台 worker:唯一走网络的地方(ensure_uid + user_playlist),UI 线程不阻塞。 */
static void *home_worker(void *arg)
{
(void)arg;
int rc;
if (!g_st.logged_in) rc = NCM_ERR_AUTH;
else rc = appstate_load_playlists();
pthread_mutex_lock(&g_home_mu);
g_load_err = rc;
g_home_loading = 0;
g_home_gen++;
pthread_mutex_unlock(&g_home_mu);
return NULL;
}
void home_reload(void)
{
if (g_host_mock) { /* 宿主/测试:跳过网络,用预置数据(同步) */
g_load_err = 0;
if (g_load_err != 0) g_st.playlist_count = 0;
home_apply();
return;
}
if (g_home_thr_on) return; /* 已有 worker 在跑,忽略重复触发 */
g_load_err = 0;
g_st.playlist_count = 0; /* 清旧数据,先画 LOADING,worker 完成后回填 */
g_home_loading = 1;
g_home_thr_on = 1;
if (pthread_create(&g_home_thr, NULL, home_worker, NULL) != 0) {
g_home_thr_on = 0;
g_home_loading = 0;
g_load_err = NCM_ERR_IO;
}
home_apply(); /* 先画(LOADING/空态),不等网络 */
}
/* UI tick:worker 完成(gen 变化)后重建列表并重绘。 */
void home_tick(uint64_t now)
{
(void)now;
if (!g_home_thr_on) return;
if (g_home_gen == g_home_acked) return;
g_home_acked = g_home_gen; /* 消费本次完成 */
g_home_thr_on = 0; /* worker 已结束,可再次 reload */
g_home_loading = 0;
home_apply();
}
int home_is_active(void) { return g_hc.active; }
int home_on_tap(int x, int y)