feat(ncm): 底部mini播放栏(替代顶栏图标) — 异Activity常驻,非播放页+有活动播放时显示:封面缩略+歌名/歌手+播放暂停+进度带+点击进播放页,宿主barhit/plsplay/home/player PASS

This commit is contained in:
AskaEth committed 2026-09-03 18:07:57 +08:00
1 parent 26a140e00f
commit 671f0d1835
6 files changed
+279 -3

No files matched your search

+42 -1
View File
@@ -95,6 +95,9 @@ static int page_id(const char *name)
if (strcmp(name, "grid") == 0) return ACT_PLAYER; /* 保留:旧横屏(重做后恒竖屏) */
if (strcmp(name, "playerbuf") == 0) return ACT_PLAYER; /* §18 缓冲态 */
if (strcmp(name, "playererr") == 0) return ACT_PLAYER; /* §18 错误态 */
if (strcmp(name, "plsplay") == 0) return ACT_PLAYLIST; /* mini 栏目检(非播放页+播放态) */
if (strcmp(name, "homeplay") == 0) return ACT_HOME; /* mini 栏目检(首页+播放态) */
if (strcmp(name, "barhit") == 0) return ACT_PLAYLIST; /* mini 栏命中自检 */
if (strcmp(name, "settings") == 0) return ACT_SETTINGS;
if (strcmp(name, "search") == 0) return ACT_SEARCH;
if (strcmp(name, "searchhist") == 0) return ACT_SEARCH; /* §23 空态=历史列表 */
@@ -123,6 +126,7 @@ int main(int argc, char **argv)
g_dark = dark;
meow_theme_add_listener(ncm_on_theme);
ncm_on_theme(dark ? MEOW_THEME_DARK : MEOW_THEME_LIGHT); /* 同步初始 g_dark */
mini_bar_init(); /* mini 播放栏:登记跨 Activity 绘制物(真实页面 + 真实 SDK 绘制物注册表) */
/* mock 状态 */
if (g_st.cache_dir[0] == 0) {
@@ -229,6 +233,18 @@ 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, "plsplay") == 0 || strcmp(name, "homeplay") == 0 ||
strcmp(name, "barhit") == 0) {
/* mini 播放栏目检/命中自检:非播放页(歌单/首页)+ 播放态 → 底部显示 mini 栏 */
mock_playlists(); mock_songs();
pthread_mutex_lock(&g_play.mu);
g_play.state = NCM_PC_PLAYING;
g_play.cur_song = 0;
g_play.pos_ms = 94000;
g_play.dur_ms = 180000;
g_play.play_song = g_st.songs[0]; /* 播放快照(§17) */
g_play.play_song_valid = 1;
pthread_mutex_unlock(&g_play.mu);
} else {
mock_playlists();
}
@@ -236,7 +252,8 @@ int main(int argc, char **argv)
meow_view *v = NULL;
if (strcmp(name, "login") == 0 || strcmp(name, "loginlive") == 0) v = login_view_create();
else if (strcmp(name, "home") == 0) v = home_view_create();
else if (strcmp(name, "playlist") == 0) v = playlist_view_create();
else if (strcmp(name, "playlist") == 0 || strcmp(name, "plsplay") == 0 ||
strcmp(name, "barhit") == 0) v = playlist_view_create();
else if (page_id(name) == ACT_PLAYER) v = player_view_create(); /* player/lands/playerbuf/playererr */
else if (strcmp(name, "settings") == 0) v = settings_view_create();
else if (strcmp(name, "search") == 0 || strcmp(name, "searchhist") == 0 ||
@@ -277,6 +294,8 @@ int main(int argc, char **argv)
p0, p1, p2, latched_change, ok ? "PASS" : "FAIL");
if (!ok) return 1;
}
/* 任意页先喂一次 mini 栏 tick:可见性/歌曲/进度变化 → 失效栏带,随后整帧重画包含 mini 栏 */
mini_bar_tick(meow_ui_time_ms());
/* player 页:其 on_tick 通常驱动进度;这里直接再画一次确保状态就绪 */
meow_ui_paint_full();
if (page_id(name) == ACT_PLAYER) {
@@ -316,6 +335,28 @@ int main(int argc, char **argv)
(ok1 && ok2) ? "PASS" : "FAIL");
if (!(ok1 && ok2)) return 1;
}
if (strcmp(name, "barhit") == 0) {
/* mini 播放栏命中自检(几何与 minibar.c 同口径:W=480 H=720 → 栏带 (0,656,480,64),
* 播放钮中心 (446,688),命中半径 22;栏体外 (100,600) 不消费):
* ① 播放态下点播放钮 → 暂停;再点 → 恢复(toggle);
* ② 点栏体 → 消费并 push(ACT_PLAYER)(进播放页);进播放页后 active=ACT_PLAYER → 栏隐藏(不消费);
* ③ 点播放钮回到非播放页后,栏体外点按不消费(0,落页面 on_tap)。 */
int w = APP_W, h = APP_H, bh = 64, by = h - bh;
int bx = w - 12 - 32 / 2 - 12 / 2, bcy = by + 32; /* 与 minibar.c MINI_* 一致 */
pthread_mutex_lock(&g_play.mu); int s0 = g_play.state; pthread_mutex_unlock(&g_play.mu);
int h1 = mini_bar_hit(bx, bcy); /* 播放钮:toggle */
pthread_mutex_lock(&g_play.mu); int s1 = g_play.state; pthread_mutex_unlock(&g_play.mu);
int h2 = mini_bar_hit(bx, bcy); /* 再点:toggle 回 */
pthread_mutex_lock(&g_play.mu); int s2 = g_play.state; pthread_mutex_unlock(&g_play.mu);
int ok_tg = (h1 == 1 && s1 == NCM_PC_PAUSED) && (h2 == 1 && s2 == NCM_PC_PLAYING);
int h3 = mini_bar_hit(100, bcy); /* 栏体 → 进播放页 */
int act_after = meow_ui_activity_active(); /* 应为 ACT_PLAYER */
int h4 = mini_bar_hit(100, bcy); /* 已在播放页 → 栏隐藏 → 不消费 */
printf("barhit: toggle %d->%d->%d=%s consume-body=%d act=%d(PLAYER) hidden=%d -> %s\n",
s0, s1, s2, ok_tg ? "PASS" : "FAIL", h3, act_after, h4,
(ok_tg && h3 == 1 && act_after == ACT_PLAYER && h4 == 0) ? "PASS" : "FAIL");
if (!ok_tg) return 1;
}
meow_ui_shutdown();
printf("dumped %s -> %s\n", name, dump);