feat(ncm): 首页顶栏「已缓存」入口 + 已缓存列表页(歌名/歌手/实际档位/大小,点播/单曲删除/清空)
入口:首页 topbar 新增动作 3(MEOW_ICON_DOWNLOAD 位图,原「回播放页」顺延动作 4)→ push ACT_CACHE;左缘返回弹回首页(app.c 路由补齐 tap/swipe/touch/tick)。 列表页 app/ui/cache.c(对齐 queue.c 惯例:圆角卡/红 mini-vinyl/按压红条/当前播放行高亮): - 行 = 歌名 / 歌手 · 实际档位 · 大小;空态/页脚(N 首 · 合计 X MB)。 - 点行 = 点播(NCM_QUEUE_CACHE 队列,上/下一首在缓存列表内循环);行右「删除」=单曲删除; 顶栏「清空」=确认框 + ncm_cache_clear(与设置页「清理缓存」同语义)。 - 数据全在 worker:cache_reload → appstate_cache_list_load → ncm_cache_scan(读目录 + 文件内 tag + 音频头探测)→ 快照;UI 线程零磁盘 IO。快照上限 512 条(最近访问优先, ≈116KB bss),更多条目按 mtime 保留最近的。 core: - ncm_cache_scan / ncm_cache_remove(songs/ 池,song_<id>_<请求档>.<实际格式> 解析, 跳过 .tmp/.part 与非数字 id;按 mtime 降序;历史双点名删除兜底)。 - ncm_api_level_from_key(缓存键后缀 ↔ 档位枚举,与 ncm_api_level_key 互逆)。 - **档位显示实际档而非请求档**:真机存在 song_171650_hires.mp3(无损请求被降级链落到 exhigh mp3),故 scan 用 ncm_audio_probe_file 读实际容器参数后只降不升地推断 (FLAC 16bit→无损 / 24bit→Hi-Res+,MP3 ≤128k→标准 / >128k→极高)。 播放:player_manager 对 NCM_QUEUE_CACHE 用条目真实键(id+请求档+实际扩展名)直读缓存 文件,不按用户当前档键重下;song_local_file/play_is_same_song/queue 页均支持第三种队列。 宿主 mock(NCM_PAGE=cache)造 3 条缓存 + 嵌入 tag + 同步扫描。
This commit is contained in:
1 parent
184ebd0ac9
commit
f392ee5c48
16 files changed
+829
-18
No files matched your search
@@ -31,6 +31,7 @@
|
||||
#define ACT_SETTINGS 4 /* 设置页 */
|
||||
#define ACT_SEARCH 5 /* 搜索页(顶栏搜索按钮进入) */
|
||||
#define ACT_QUEUE 6 /* 当前播放队列页(播放页「队列」钮进入,展示实时播放列表) */
|
||||
#define ACT_CACHE 7 /* 已缓存列表页(首页顶栏「已缓存」入口,NCM_CACHE_DESIGN §2.5) */
|
||||
|
||||
/* ---- 播放模式三态(REPORT §NEW:随机 / 列表循环 / 单曲循环)----
|
||||
* 默认=列表循环(延续既有「顺序下一首」语义;列表循环下自动顺延会在队尾回绕)。
|
||||
@@ -115,6 +116,11 @@ static inline int ncm_row_card_h(int item) { return item - NCM_ROW_GAP; }
|
||||
/* 播放队列来源(§23:搜索单曲起播建立「搜索队列」上下文,不覆写歌单窗口) */
|
||||
#define NCM_QUEUE_PLAYLIST 0 /* 默认:歌单滑动窗口 */
|
||||
#define NCM_QUEUE_SEARCH 1 /* 搜索单曲结果队列 */
|
||||
#define NCM_QUEUE_CACHE 2 /* 已缓存列表队列(点播缓存页条目;上/下一首在缓存列表内循环) */
|
||||
|
||||
/* 已缓存列表条目上限(NCM_CACHE_LIST_MAX 条 × sizeof(ncm_cache_item_t)≈232B ≈ 116KB bss)。
|
||||
* 缓存池条目更多时只展示最近访问的 max 条(scan 按 mtime 降序保留最近的)。 */
|
||||
#define NCM_CACHE_LIST_MAX 512
|
||||
|
||||
/* active_playlist 哨兵:搜索歌单详情(复用 playlist_open 链路,读 g_st.search_pl_open) */
|
||||
#define NCM_PL_SEARCH (-2)
|
||||
@@ -269,6 +275,10 @@ typedef struct ncm_app_state {
|
||||
|
||||
/* 播放队列来源(§23):默认 NCM_QUEUE_PLAYLIST;搜索单曲起播切 NCM_QUEUE_SEARCH */
|
||||
int queue_src;
|
||||
|
||||
/* 已缓存列表(ACT_CACHE 页 + NCM_QUEUE_CACHE 队列;worker 扫描磁盘填充,UI 只读) */
|
||||
ncm_cache_item_t cache_items[NCM_CACHE_LIST_MAX];
|
||||
int cache_item_count;
|
||||
} ncm_app_state_t;
|
||||
|
||||
extern ncm_app_state_t g_st; /* 全局状态(app.c 定义) */
|
||||
@@ -353,6 +363,7 @@ void player_tick(uint64_t now); /* 播放进度/歌词滚动 */
|
||||
void player_play_song(int idx); /* 从歌单窗口第 idx 首开始播放(queue=PLAYLIST) */
|
||||
void player_play_search_song(int i); /* 从搜索单曲第 i 首开始播放(queue=SEARCH,§23) */
|
||||
void player_play_queue_song(int idx);/* 从「当前实时播放队列」第 idx 首播放(保持当前 queue_src,§NEW) */
|
||||
void player_play_cache_song(int i); /* 从已缓存列表第 i 首点播(切 NCM_QUEUE_CACHE 队列) */
|
||||
void player_pause_toggle(int on);
|
||||
void player_next(int dir); /* dir=+1 下一首 / -1 上一首 */
|
||||
void player_seek(int64_t ms);
|
||||
@@ -390,6 +401,19 @@ void queue_touch_move(int x, int y);
|
||||
void queue_open(void); /* 进当前播放队列页 */
|
||||
void queue_tick(uint64_t now); /* UI tick:检查队列 worker 完成并刷新 */
|
||||
|
||||
/* cache(已缓存列表页,ACT_CACHE:首页顶栏「已缓存」钮进入,NCM_CACHE_DESIGN §2.5)
|
||||
* 列表 = songs/ 池扫描(worker 读盘,UI 零 IO);行显示 歌名/歌手/实际档位/大小;
|
||||
* 点行=点播(NCM_QUEUE_CACHE),行右「删除」=单曲删除,顶栏「清空」=清空缓存池。 */
|
||||
meow_view *cache_view_create(void);
|
||||
int cache_is_active(void);
|
||||
int cache_on_tap(int x, int y);
|
||||
void cache_swipe(int dir, int dist);
|
||||
void cache_touch_down(int x, int y);
|
||||
void cache_touch_move(int x, int y);
|
||||
void cache_open(void); /* 进已缓存列表页(push ACT_CACHE) */
|
||||
void cache_reload(void); /* 起 worker 重扫缓存池(非阻塞) */
|
||||
void cache_tick(uint64_t now); /* UI tick:检查扫描 worker 完成并刷新 */
|
||||
|
||||
/* search */
|
||||
meow_view *search_view_create(void);
|
||||
int search_is_active(void);
|
||||
@@ -470,6 +494,16 @@ int appstate_queue_count(void); /* 当前播放队列长度(
|
||||
int appstate_queue_song(int idx, ncm_song_t *out); /* 队列第 idx 首;0=ok(按 queue_src) */
|
||||
void appstate_apply_play_mode(int m); /* 设 g_st.play_mode + 落盘(持久化「记住模式」,§NEW) */
|
||||
|
||||
/* ---- 已缓存列表(NCM_CACHE_LIST_MAX;磁盘扫描/删除只在 worker 或 UI 单次小 IO)----
|
||||
* queue_src==NCM_QUEUE_CACHE 时,appstate_queue_count/song 走本数组(播放页上/下一首同源)。
|
||||
* 名称/歌手优先取文件内 tag(与外部播放器同源),空则回退旁路元数据 <cache_dir>/meta/<id>.bin。 */
|
||||
int appstate_cache_list_load(void); /* worker:ncm_cache_scan + 旁路补名;返回条数或负错误码 */
|
||||
int appstate_cache_count(void);
|
||||
int appstate_cache_item(int i, ncm_cache_item_t *out); /* 0=ok */
|
||||
int appstate_cache_song(int i, ncm_song_t *out); /* 合成 ncm_song_t(时长/封面/fee 取旁路) */
|
||||
int appstate_cache_remove(int i); /* 删文件 + 摘除条目;0=成功 */
|
||||
void appstate_cache_clear(void); /* 清空缓存池(含封面池,同设置页语义)+ 清列表 */
|
||||
|
||||
/* ---- 搜索结果独立数组(§23;g_search_mu 保护,UI/worker 经此访问)---- */
|
||||
int appstate_search_count(int tab); /* tab: 0=单曲 1=歌单 */
|
||||
int appstate_search_offset(int tab); /* 下次 offset(=已加载条数) */
|
||||
|
||||
Reference in new issue
Block a user