tmus

TUI Music Player
git clone https://git.sinitax.com/sinitax/tmus
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

commit a001039548e2df4ba88b5ad0396eac4980959ab0
parent 019761cb13674f85468188b193e2fa7ff959f47f
Author: Louis Burda <quent.burda@gmail.com>
Date:   Sat,  8 Jan 2022 17:20:46 +0100

Allow switch between playlist and tracks in hovered tag

Diffstat:
Msrc/listnav.c | 18+++++++++++-------
Msrc/main.c | 45++++++++++++++++++++++++++++++++++++++-------
Msrc/player.c | 10++++++----
3 files changed, 55 insertions(+), 18 deletions(-)

diff --git a/src/listnav.c b/src/listnav.c @@ -12,26 +12,30 @@ listnav_init(struct listnav *nav) void listnav_update_bounds(struct listnav *nav, int min, int max) { + ASSERT(max >= min); nav->min = min; nav->max = max; - nav->wmin = MAX(nav->wmin, nav->min); - nav->wmax = MIN(nav->wmin + nav->wlen, nav->max); - nav->sel = MIN(MAX(nav->sel, nav->wmin), nav->wmax - 1); + listnav_update_wlen(nav, MIN(nav->wlen, nav->max - nav->min)); } void listnav_update_wlen(struct listnav *nav, int wlen) { - nav->wlen = wlen; - nav->wmax = MIN(nav->wmin + nav->wlen, nav->max); - nav->sel = MIN(MAX(nav->sel, nav->wmin), nav->wmax - 1); + ASSERT(wlen >= 0); + + nav->wlen = MIN(wlen, nav->max - nav->min); + if (nav->wmin < nav->min) + nav->wmin = nav->min; + if (nav->wmin + nav->wlen > nav->max) + nav->wmin = nav->max - nav->wlen; + nav->wmax = nav->wmin + nav->wlen; + nav->sel = MAX(MIN(nav->sel, nav->wmax - 1), nav->wmin); } void listnav_update_sel(struct listnav *nav, int sel) { nav->sel = MAX(MIN(sel, nav->max - 1), nav->min); - if (nav->sel >= nav->wmax) { nav->wmax = nav->sel + 1; nav->wmin = MAX(nav->min, nav->wmax - nav->wlen); diff --git a/src/main.c b/src/main.c @@ -87,6 +87,8 @@ static struct pane *const panes[] = { static struct link tracks; static struct link tags; static struct link tags_sel; +static struct link *tracks_vis; +static int track_show_playlist; /* bottom 'cmd' pane for search / exec */ static struct pane *cmd_pane; @@ -140,6 +142,7 @@ static int cmd_pane_input(wint_t c); static void cmd_pane_vis(struct pane *pane, int sel); static void queue_hover(void); +static void update_track_playlist(void); static void main_input(wint_t c); static void main_vis(void); @@ -173,6 +176,9 @@ init(void) listnav_init(&tag_nav); listnav_init(&track_nav); + track_show_playlist = 0; + update_track_playlist(); + on_exit(cleanup, NULL); signal(SIGINT, exit); } @@ -252,11 +258,11 @@ tui_resize(void) getmaxyx(stdscr, scrh, scrw); /* guarantee a minimum terminal size */ - if (scrw < 10 || scrh < 4) { + while (scrw < 10 || scrh < 4) { clear(); - printw("..."); refresh(); usleep(10000); + getmaxyx(stdscr, scrh, scrw); } /* adjust tag pane width to name lengths */ @@ -309,6 +315,8 @@ data_load(void) tracks_load(tag); } closedir(dir); + + ASSERT(!list_empty(&tags)); } void @@ -595,8 +603,8 @@ track_pane_input(wint_t c) listnav_update_sel(&track_nav, track_nav.sel + 1); return 1; case KEY_ENTER: - if (list_empty(&player->playlist)) return 1; - link = link_iter(player->playlist.next, track_nav.sel); + if (list_empty(tracks_vis)) return 1; + link = link_iter(tracks_vis->next, track_nav.sel); ASSERT(link != NULL); track = UPCAST(link, struct ref)->data; player_play_track(track); @@ -619,16 +627,17 @@ track_pane_vis(struct pane *pane, int sel) { struct track *track; struct link *iter; + struct tag *tag; int index; werase(pane->win); pane_title(pane, "Tracks", sel); - listnav_update_bounds(&track_nav, 0, list_len(&player->playlist)); + listnav_update_bounds(&track_nav, 0, list_len(tracks_vis)); listnav_update_wlen(&track_nav, pane->h - 1); index = 0; - for (iter = player->playlist.next; iter; iter = iter->next, index++) { + for (iter = tracks_vis->next; iter; iter = iter->next, index++) { track = UPCAST(iter, struct ref)->data; if (index < track_nav.wmin) continue; @@ -851,7 +860,8 @@ cmd_pane_vis(struct pane *pane, int sel) /* status bits on right of status line */ if (player->loaded) ATTR_ON(pane->win, A_REVERSE); - mvwaddstr(pane->win, 1, pane->w - 4, "[ ]"); + mvwaddstr(pane->win, 1, pane->w - 5, "[ ]"); + if (track_show_playlist) mvwaddstr(pane->win, 1, pane->w - 4, "P"); if (player->autoplay) mvwaddstr(pane->win, 1, pane->w - 3, "A"); if (player->shuffle) mvwaddstr(pane->win, 1, pane->w - 2, "S"); if (player->loaded) ATTR_OFF(pane->win, A_REVERSE); @@ -901,6 +911,22 @@ queue_hover(void) } void +update_track_playlist(void) +{ + struct link *iter; + struct tag *tag; + + if (track_show_playlist) { + tracks_vis = &player->playlist; + } else { + iter = link_iter(tags.next, tag_nav.sel); + ASSERT(iter != NULL); + tag = UPCAST(iter, struct tag); + tracks_vis = &tag->tracks; + } +} + +void main_input(wint_t c) { switch (c) { @@ -929,6 +955,9 @@ main_input(wint_t c) case L'c': player_toggle_pause(); break; + case L'P': + track_show_playlist ^= 1; + break; case L'n': case L'>': player_next(); @@ -1026,6 +1055,8 @@ main(int argc, const char **argv) if (!handled) main_input(c); } + update_track_playlist(); + refresh(); for (i = 0; i < ARRLEN(panes); i++) { /* only update ui for panes that are visible */ diff --git a/src/player.c b/src/player.c @@ -41,13 +41,13 @@ handle_mpd_status(int status) case MPD_ERROR_SERVER: case MPD_ERROR_ARGUMENT: if (!mpd_connection_clear_error(player->conn)) - PANIC("Player failed to recover from error"); + PANIC("PLAYER: Failed to recover from argument error"); case MPD_ERROR_SYSTEM: PLAYER_STATUS(PLAYER_MSG_ERR, "%s", mpd_connection_get_error_message(player->conn)); return 1; case MPD_ERROR_CLOSED: - PANIC("Player encountered non-recoverable error"); + PANIC("PLAYER: Connection abruptly closed"); } return 0; } @@ -67,6 +67,7 @@ player_init(void) player->playlist = LIST_HEAD; player->track = NULL; + player->loaded = 0; player->state = PLAYER_STATE_PAUSED; player->autoplay = 0; @@ -154,8 +155,9 @@ player_update(void) || !list_empty(&player->queue)) { player->action = PLAYER_ACTION_PLAY_NEXT; } + } else { + mpd_song_free(song); } - mpd_song_free(song); mpd_status_free(status); @@ -205,13 +207,13 @@ player_update(void) player->loaded = true; player->time_pos = mpd_status_get_elapsed_time(status); player->time_end = mpd_song_get_duration(song); + mpd_song_free(song); } else { player->loaded = false; player->track = NULL; player->time_pos = 0; player->time_end = 0; } - mpd_song_free(song); switch (mpd_status_get_state(status)) { case MPD_STATE_PAUSE: