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
@@ -72,6 +72,37 @@ static void mock_lyric(void)
|
||||
lyric_parse(lrc, tl);
|
||||
}
|
||||
|
||||
/* M5:已缓存列表页 mock —— 造 3 条 songs/ 缓存(mp3 帧 + 嵌入 ID3v2.3),再同步扫描进快照。 */
|
||||
static void mock_cache(void)
|
||||
{
|
||||
static const char *names[] = { "Song Cached One", "Song Cached Two", "Song Cached Three" };
|
||||
static const char *arts[] = { "Artist X", "Artist Y", "Artist Z" };
|
||||
static const char *lvks[] = { "exhigh", "hires", "lossless" };
|
||||
ncm_cache_init(&g_st.ctx.cache, g_st.cache_dir);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
char id[24], key[48];
|
||||
unsigned char fr[4096];
|
||||
ncm_cache_writer_t *w;
|
||||
snprintf(id, sizeof id, "%ld", 5000L + i);
|
||||
snprintf(key, sizeof key, "%s_%s", id, lvks[i]);
|
||||
for (size_t k = 0; k < sizeof fr; k++) fr[k] = (unsigned char)(0x20 + (k * 7));
|
||||
fr[0] = 0xFF; fr[1] = 0xFB; fr[2] = 0xE0; fr[3] = 0x00; /* 320kbps / 44.1kHz */
|
||||
if (ncm_cache_open(&g_st.ctx.cache, key, "mp3", &w) != NCM_OK) continue;
|
||||
ncm_cache_write(w, fr, sizeof fr);
|
||||
if (ncm_cache_commit(w) != NCM_OK) continue;
|
||||
char path[NCM_CACHE_DIR_MAX + 64];
|
||||
if (ncm_cache_lookup(&g_st.ctx.cache, key, "mp3", path, sizeof path) == NCM_OK) {
|
||||
ncm_tag_meta_t t;
|
||||
memset(&t, 0, sizeof t);
|
||||
snprintf(t.title, sizeof t.title, "%s", names[i]);
|
||||
snprintf(t.artist, sizeof t.artist, "%s", arts[i]);
|
||||
snprintf(t.album, sizeof t.album, "Album %d", i + 1);
|
||||
ncm_tag_embed_file(path, "mp3", &t);
|
||||
}
|
||||
}
|
||||
appstate_cache_list_load();
|
||||
}
|
||||
|
||||
static void mock_qr(void)
|
||||
{
|
||||
g_st.qr_size = 29;
|
||||
@@ -137,6 +168,7 @@ static int page_id(const char *name)
|
||||
if (strcmp(name, "searchtap") == 0) return ACT_SEARCH; /* §23 误触抑制自检 */
|
||||
if (strcmp(name, "modetest") == 0) return ACT_PLAYER; /* §NEW 播放模式三态逻辑自检 */
|
||||
if (strcmp(name, "queuetest") == 0) return ACT_QUEUE; /* §NEW 播放队列页/点播语义自检 */
|
||||
if (strcmp(name, "cache") == 0 || strcmp(name, "cachetest") == 0) return ACT_CACHE; /* M5 */
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -268,8 +300,7 @@ int main(int argc, char **argv)
|
||||
appstate_search_history_add("Jay \u5553\u8868");
|
||||
appstate_search_history_add("lofi beat");
|
||||
appstate_search_history_add("Jay \u5553\u8868"); /* 去重 → 仍 3 条 */
|
||||
} else if (strcmp(name, "modetest") == 0 || strcmp(name, "queuetest") == 0) {
|
||||
/* §NEW 播放模式 / 播放队列自检:歌单滑窗队列(6 首)+ 播放态 */
|
||||
} else if (strcmp(name, "modetest") == 0 || strcmp(name, "queuetest") == 0) { /* §NEW 播放模式 / 播放队列自检:歌单滑窗队列(6 首)+ 播放态 */
|
||||
mock_playlists(); mock_songs();
|
||||
pthread_mutex_lock(&g_play.mu);
|
||||
g_play.state = NCM_PC_PLAYING;
|
||||
@@ -290,6 +321,8 @@ int main(int argc, char **argv)
|
||||
g_play.play_song = g_st.songs[0]; /* 播放快照(§17) */
|
||||
g_play.play_song_valid = 1;
|
||||
pthread_mutex_unlock(&g_play.mu);
|
||||
} else if (strcmp(name, "cache") == 0 || strcmp(name, "cachetest") == 0) {
|
||||
mock_cache(); /* M5:假缓存池 + 文件内 tag + 快照扫描 */
|
||||
} else {
|
||||
mock_playlists();
|
||||
}
|
||||
@@ -301,6 +334,7 @@ int main(int argc, char **argv)
|
||||
strcmp(name, "barhit") == 0 || strcmp(name, "covswitch") == 0) v = playlist_view_create();
|
||||
else if (page_id(name) == ACT_PLAYER) v = player_view_create(); /* player/lands/playerbuf/playererr/modetest */
|
||||
else if (page_id(name) == ACT_QUEUE) v = queue_view_create(); /* §NEW 播放队列页 */
|
||||
else if (page_id(name) == ACT_CACHE) v = cache_view_create(); /* M5 已缓存列表页 */
|
||||
else if (strcmp(name, "settings") == 0) v = settings_view_create();
|
||||
else if (strcmp(name, "search") == 0 || strcmp(name, "searchhist") == 0 ||
|
||||
strcmp(name, "searchpl") == 0 || strcmp(name, "searchtap") == 0) v = search_view_create();
|
||||
|
||||
Reference in new issue
Block a user