feat(ncm): 播放模式三态(随机/列表循环/单曲循环,播放页三键左)+当前实时播放列表(三键右,歌单滑窗/meow_listview虚拟化分页至5194首,当前曲高亮,点播切歌) — 模式持久化,宿主modetest/queuetest全过
This commit is contained in:
1 parent
29e13b2b5e
commit
7ca3e5bd84
8 files changed
+707
-28
No files matched your search
@@ -89,7 +89,11 @@ static ncm_rect_t g_cover_r; /* 封面页静态带(方形大图
|
||||
static ncm_rect_t g_dyn_r; /* 封面页动态带(元信息/进度/控制/指示点) */
|
||||
static int g_title_y, g_artist_y, g_qual_y, g_times_y;
|
||||
static ncm_rect_t g_bar;
|
||||
static int g_ctl_y, g_prev_x, g_play_x, g_next_x, g_r_side, g_r_play, g_dots_y;
|
||||
static int g_ctl_y, g_prev_x, g_play_x, g_next_x, g_mode_x, g_queue_x, g_r_side, g_r_play, g_dots_y;
|
||||
/* §NEW 模式/队列钮:三键左(mode,prev 更左)/ 三键右(queue,next 更右)。间距 60 保不遮挡。 */
|
||||
#define GAP_SIDE 60
|
||||
#define MODE_BTN_R (g_r_side) /* 与侧钮同半径(命中取 CTL_RR) */
|
||||
#define MODE_LBL_SZ 14 /* 模式/队列钮文字字号(两字,居中) */
|
||||
|
||||
/* ---- 歌词页几何 ---- */
|
||||
static int g_lyr_cx; /* 歌词垂直中心(屏中线) */
|
||||
@@ -284,6 +288,18 @@ static void draw_ctrl_btn(int icon, int cx, int cy, int r, uint32_t circle, uint
|
||||
draw_md3_icon(icon, cx, cy, (r * 4) / 3, fg);
|
||||
}
|
||||
|
||||
/* 文字钮:圆形底 + 居中两字文案(§NEW 模式/队列钮)。无逐帧三角行扫,纯圆形填充。 */
|
||||
static void draw_text_btn(const char *label, int cx, int cy, int r, uint32_t circle, uint32_t fg)
|
||||
{
|
||||
for (int dy = -r; dy <= r; dy++) {
|
||||
int half = (int)sqrt((double)(r * r - dy * dy));
|
||||
if (half <= 0) continue;
|
||||
meow_ui_fill_rect(cx - half, cy + dy, 2 * half, 1, circle);
|
||||
}
|
||||
if (label && label[0])
|
||||
meow_ui_text_center(cx, cy - MODE_LBL_SZ / 2, label, MODE_LBL_SZ, fg);
|
||||
}
|
||||
|
||||
/* 圆角封面四角裁掉:把方形图四角(圆角外-方形内)盖回背景色(廉价圆角,无 GPU 裁剪)。 */
|
||||
static void round_corners_bg(int x, int y, int w, int h, int r, uint32_t bg)
|
||||
{
|
||||
@@ -335,6 +351,8 @@ static void player_compute_geom(void)
|
||||
g_times_y = g_bar.y + g_bar.h + 12; /* 500 */
|
||||
g_ctl_y = g_times_y + 64; /* 564 */
|
||||
g_prev_x = W / 2 - 92; g_play_x = W / 2; g_next_x = W / 2 + 92;
|
||||
g_mode_x = g_prev_x - GAP_SIDE; /* 播放模式三态钮(prev 更左) */
|
||||
g_queue_x = g_next_x + GAP_SIDE; /* 当前播放队列钮(next 更右) */
|
||||
g_r_side = 24; g_r_play = 34;
|
||||
g_dots_y = g_ctl_y + 62; /* 626 */
|
||||
|
||||
@@ -449,6 +467,12 @@ static void plr_draw_cover_dyn(void *ctx)
|
||||
g_play_x, g_ctl_y, g_r_play, pa->red, pa->on_red);
|
||||
draw_ctrl_btn(NCM_I_NEXT, g_next_x, g_ctl_y, g_r_side, PLR_CTRL_BG, PLR_CTRL_FG);
|
||||
|
||||
/* §NEW 播放模式三态钮(三键左,prev 更左)+ 当前播放队列钮(三键右,next 更右):
|
||||
* 文案反映当前模式(随机/列表/单曲);队列钮进入实时播放列表。 */
|
||||
draw_text_btn(ncm_mode_name(player_manager_play_mode()), g_mode_x, g_ctl_y,
|
||||
MODE_BTN_R, PLR_CTRL_BG, PLR_CTRL_FG);
|
||||
draw_text_btn("\u961f\u5217", g_queue_x, g_ctl_y, MODE_BTN_R, PLR_CTRL_BG, PLR_CTRL_FG); /* 队列 */
|
||||
|
||||
/* 页面指示点 */
|
||||
draw_page_dots(g_dots_y);
|
||||
}
|
||||
@@ -604,7 +628,9 @@ void player_touch_down(int x, int y)
|
||||
interactive = 1;
|
||||
if (in_circle(g_prev_x, g_ctl_y, CTL_RR, x, y) ||
|
||||
in_circle(g_play_x, g_ctl_y, g_r_play + 6, x, y) ||
|
||||
in_circle(g_next_x, g_ctl_y, CTL_RR, x, y))
|
||||
in_circle(g_next_x, g_ctl_y, CTL_RR, x, y) ||
|
||||
in_circle(g_mode_x, g_ctl_y, CTL_RR, x, y) ||
|
||||
in_circle(g_queue_x, g_ctl_y, CTL_RR, x, y))
|
||||
interactive = 1;
|
||||
}
|
||||
g_touch_on = (x > PLR_EDGE_W) && (y >= meow_ui_statusbar_hotzone()) && !interactive;
|
||||
@@ -675,6 +701,19 @@ void player_on_tap(int x, int y)
|
||||
}
|
||||
if (in_circle(g_prev_x, g_ctl_y, CTL_RR, x, y)) { player_manager_next(-1); return; }
|
||||
if (in_circle(g_next_x, g_ctl_y, CTL_RR, x, y)) { player_manager_next(1); return; }
|
||||
|
||||
/* §NEW 播放模式三态钮:点击循环切换(SHUFFLE→LISTLOOP→SINGLE→SHUFFLE)+ 持久化 */
|
||||
if (in_circle(g_mode_x, g_ctl_y, CTL_RR, x, y)) {
|
||||
int m = player_manager_play_mode();
|
||||
int nxt = (m + 1) % NCM_MODE_COUNT;
|
||||
player_manager_set_play_mode(nxt);
|
||||
appstate_apply_play_mode(nxt); /* 记住模式(退出后保留) */
|
||||
player_dyn_invalidate();
|
||||
return;
|
||||
}
|
||||
/* §NEW 当前播放队列钮:进实时播放列表页 */
|
||||
if (in_circle(g_queue_x, g_ctl_y, CTL_RR, x, y)) { queue_open(); return; }
|
||||
|
||||
if (y >= g_bar.y - 10 && y <= g_bar.y + g_bar.h + 10 && x >= g_bar.x && x <= g_bar.x + g_bar.w) {
|
||||
int64_t dur = player_manager_dur_ms();
|
||||
if (dur > 0) player_seek((int64_t)(x - g_bar.x) * dur / g_bar.w);
|
||||
@@ -731,6 +770,28 @@ void player_play_search_song(int i)
|
||||
meow_view_page_push(ACT_PLAYER);
|
||||
}
|
||||
|
||||
/* 从「当前实时播放队列」第 idx 首播放(§NEW 队列页点播):保持当前 queue_src 不变
|
||||
* (不把队列切回歌单/不覆写歌单窗口)——上/下一首仍在该队列内循环。封面用窗口/搜索数组
|
||||
* 内的元数据(不触发网络),占位行由播放线程物化后快照接管。 */
|
||||
void player_play_queue_song(int idx)
|
||||
{
|
||||
int cnt = appstate_queue_count();
|
||||
if (idx < 0 || idx >= cnt) return;
|
||||
ncm_song_t s;
|
||||
int have = 0;
|
||||
if (appstate_get_queue() == NCM_QUEUE_SEARCH) {
|
||||
if (appstate_search_song(idx, &s) == 0) have = 1;
|
||||
} else if (appstate_song_copy(idx, &s) == 0) {
|
||||
have = 1;
|
||||
}
|
||||
const char *cover = have ? (s.al_pic[0] ? s.al_pic : g_st.cover_url) : g_st.cover_url;
|
||||
player_manager_play(idx);
|
||||
appstate_set_playing_song(idx, NULL);
|
||||
if (have) cover_request(cover, s.id);
|
||||
g_ppage = 0;
|
||||
meow_view_page_push(ACT_PLAYER);
|
||||
}
|
||||
|
||||
void player_pause_toggle(int on)
|
||||
{
|
||||
if (player_manager_state() == NCM_PC_PAUSED) player_manager_pause(0);
|
||||
|
||||
Reference in new issue
Block a user