tmus

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

commit faee8e9c6db45c6adacfc5113d55927f92e8bf29
parent 4b0b3da65906ae892fa3f46a3482dd36b32c816c
Author: Louis Burda <quent.burda@gmail.com>
Date:   Mon, 20 Dec 2021 15:24:31 +0100

Made main.c symbols static, added autoplay

Diffstat:
M.gitignore | 1+
Mmain.c | 211++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Mplayer.c | 6+++---
3 files changed, 149 insertions(+), 69 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -2,3 +2,4 @@ vgcore* tmus env.sh *.o +todo diff --git a/main.c b/main.c @@ -55,7 +55,8 @@ struct pane; typedef int (*pane_handler)(wint_t c); typedef void (*pane_updater)(struct pane *pane, int sel); -typedef wchar_t *(*completion_generator)(const wchar_t *text, int fwd, int state); +typedef wchar_t *(*completion_generator)(const wchar_t *text, + int fwd, int state); typedef int (*cmd_handler)(const char *args); struct pane { @@ -73,81 +74,92 @@ struct cmd { cmd_handler func; }; -int style_attrs[STYLE_COUNT]; +struct autoplay { + int enabled; + int shuffle; +}; + +static const char player_state_chars[] = { + [PLAYER_STATE_PAUSED] = '|', + [PLAYER_STATE_PLAYING] = '>', + [PLAYER_STATE_STOPPED] = '#' +}; + +static int style_attrs[STYLE_COUNT]; -const char *datadir; -int scrw, scrh; -int quit; +static const char *datadir; +static int scrw, scrh; +static int quit; -struct pane *pane_sel, *pane_top_sel; -struct pane pane_left, pane_right, pane_bot; -struct pane *const panes[] = { +static struct pane *pane_sel, *pane_top_sel; +static struct pane pane_left, pane_right, pane_bot; +static struct pane *const panes[] = { &pane_left, &pane_right, &pane_bot }; -struct inputln completion_query = { 0 }; -int completion_reset = 1; -completion_generator completion; +static struct inputln completion_query = { 0 }; +static int completion_reset = 1; +static completion_generator completion; -struct pane *cmd_pane; -struct history search_history, command_history; -struct history *history; -int cmd_show, cmd_mode; +static struct pane *cmd_pane; +static struct history search_history, command_history; +static struct history *history; +static int cmd_show, cmd_mode; -const char player_state_chars[] = { - [PLAYER_STATE_PAUSED] = '|', - [PLAYER_STATE_PLAYING] = '>', - [PLAYER_STATE_STOPPED] = '#' -}; +static struct autoplay autoplay; -struct pane *tag_pane; -struct listnav tag_nav; -struct link tags; -struct link tags_sel; +static struct pane *tag_pane; +static struct listnav tag_nav; +static struct link tags; +static struct link tags_sel; -struct pane *track_pane; -struct listnav track_nav; -struct link playlist; -struct link tracks; +static struct pane *track_pane; +static struct listnav track_nav; +static struct link playlist; +static struct link tracks; -void init(void); -void cleanup(void); +static void init(void); +static void cleanup(void *arg, int code); -void data_load(void); -void tracks_load(struct tag *tag); +static void data_load(void); +static void tracks_load(struct tag *tag); -void data_save(void); -void tracks_save(struct tag *tag); +static void data_save(void); +static void tracks_save(struct tag *tag); -void resize(void); -void pane_resize(struct pane *pane, +static void resize(void); +static void pane_resize(struct pane *pane, int sx, int sy, int ex, int ey); -void pane_init(struct pane *p, pane_handler handle, pane_updater update); -void pane_title(struct pane *pane, const char *title, int highlight); +static void pane_init(struct pane *p, pane_handler handle, pane_updater update); +static void pane_title(struct pane *pane, const char *title, int highlight); + +static void style_init(int style, int fg, int bg, int attr); +static void style_on(WINDOW *win, int style); +static void style_off(WINDOW *win, int style); -void style_init(int style, int fg, int bg, int attr); -void style_on(WINDOW *win, int style); -void style_off(WINDOW *win, int style); +static wchar_t *command_name_generator(const wchar_t *text, int fwd, int state); +static wchar_t *track_name_generator(const wchar_t *text, int fwd, int state); -wchar_t *command_name_generator(const wchar_t *text, int fwd, int state); -wchar_t *track_name_generator(const wchar_t *text, int fwd, int state); +static void select_current_tag(void); +static int tag_input(wint_t c); +static void tag_vis(struct pane *pane, int sel); -int tag_input(wint_t c); -void tag_vis(struct pane *pane, int sel); +static int track_input(wint_t c); +static void track_vis(struct pane *pane, int sel); -int track_input(wint_t c); -void track_vis(struct pane *pane, int sel); +static int cmd_input(wint_t c); +static void cmd_vis(struct pane *pane, int sel); -int cmd_input(wint_t c); -void cmd_vis(struct pane *pane, int sel); +static void queue_hover(void); +static void main_input(wint_t c); +static void main_vis(void); -void main_input(wint_t c); -void main_vis(void); +static int usercmd_save(const char *args); -int usercmd_save(const char *args); +static void update_player(void); const struct cmd cmds[] = { { L"save", usercmd_save }, @@ -162,7 +174,7 @@ init(void) /* TODO handle as character intead of signal */ signal(SIGINT, exit); - atexit(cleanup); + atexit((void*) cleanup); /* this works */ history = &command_history; history_init(&search_history); @@ -203,13 +215,18 @@ init(void) playlist = LIST_HEAD; tags_sel = LIST_HEAD; + autoplay.enabled = 0; + autoplay.shuffle = 0; + listnav_init(&tag_nav); listnav_init(&track_nav); } void -cleanup(void) +cleanup(void* arg, int code) { + if (code) return; + delwin(pane_left.win); delwin(pane_right.win); delwin(pane_bot.win); @@ -444,7 +461,8 @@ select_current_tag(void) tag = UPCAST(link, struct ref)->data; for (iter = tracks.next; iter; iter = iter->next) { track = UPCAST(iter, struct track); - if (refs_incl(&track->tags, tag) && !refs_incl(&playlist, track)) { + if (refs_incl(&track->tags, tag) + && !refs_incl(&playlist, track)) { ref = ref_init(track); list_push_back(&playlist, LINK(ref)); } @@ -466,10 +484,12 @@ tag_input(wint_t c) select_current_tag(); return 1; case KEY_NPAGE: - listnav_update_sel(&track_nav, track_nav.sel - track_nav.wlen / 2); + listnav_update_sel(&track_nav, + track_nav.sel - track_nav.wlen / 2); return 1; case KEY_PPAGE: - listnav_update_sel(&track_nav, track_nav.sel + track_nav.wlen / 2); + listnav_update_sel(&track_nav, + track_nav.sel + track_nav.wlen / 2); return 1; } @@ -535,10 +555,12 @@ track_input(wint_t c) player_play_track(track); return 1; case KEY_PPAGE: - listnav_update_sel(&track_nav, track_nav.sel - track_nav.wlen / 2); + listnav_update_sel(&track_nav, + track_nav.sel - track_nav.wlen / 2); return 1; case KEY_NPAGE: - listnav_update_sel(&track_nav, track_nav.sel + track_nav.wlen / 2); + listnav_update_sel(&track_nav, + track_nav.sel + track_nav.wlen / 2); return 1; } @@ -558,9 +580,6 @@ track_vis(struct pane *pane, int sel) listnav_update_bounds(&track_nav, 0, list_len(&playlist)); listnav_update_wlen(&track_nav, pane->h - 1); - wmove(pane->win, 0, 50); - wprintw(pane->win, "%i", list_len(&playlist)); - index = 0; for (iter = playlist.next; iter; iter = iter->next, index++) { track = UPCAST(iter, struct ref)->data; @@ -714,14 +733,22 @@ cmd_vis(struct pane *pane, int sel) line = appendstrf(NULL, "%c ", player_state_chars[player->state]); line = appendstrf(line, "%s / ", timestr(player->time_pos)); line = appendstrf(line, "%s", timestr(player->time_end)); + if (player->volume >= 0) line = appendstrf(line, " - vol: %u%%", player->volume); + if (player->msg) line = appendstrf(line, " | [PLAYER] %s", player->msg); + if (!list_empty(&player->queue)) line = appendstrf(line, " | [QUEUE] %i tracks", list_len(&player->queue)); + if (autoplay.enabled && !autoplay.shuffle) + line = appendstrf(line, " | AUTOPLAY"); + else if (autoplay.enabled && autoplay.shuffle) + line = appendstrf(line, " | AUTOPLAY [S]"); + wmove(pane->win, 1, 0); ATTR_ON(pane->win, A_REVERSE); wprintw(pane->win, "%-*.*s\n", pane->w, pane->w, line); @@ -741,12 +768,14 @@ cmd_vis(struct pane *pane, int sel) cmd = history->cmd; if (cmd != history->query) { index = 0; - for (iter = history->list.next; iter; iter = iter->next, index++) + iter = history->list.next; + for (; iter; iter = iter->next, index++) if (UPCAST(iter, struct inputln) == cmd) break; line = appendstrf(NULL, "[%i] ", iter ? index : -1); } else { - line = appendstrf(NULL, "%c", cmd_mode == IMODE_SEARCH ? '/' : ':'); + line = appendstrf(NULL, "%c", + cmd_mode == IMODE_SEARCH ? '/' : ':'); } offset = strlen(line); line = appendstrf(line, "%ls", cmd->buf); @@ -755,7 +784,8 @@ cmd_vis(struct pane *pane, int sel) if (sel) { /* cursor */ ATTR_ON(pane->win, A_REVERSE); wmove(pane->win, 2, offset + cmd->cur); - waddch(pane->win, cmd->cur < cmd->len ? cmd->buf[cmd->cur] : ' '); + waddch(pane->win, cmd->cur < cmd->len + ? cmd->buf[cmd->cur] : ' '); ATTR_OFF(pane->win, A_REVERSE); } } @@ -801,6 +831,9 @@ main_input(wint_t c) case L'y': queue_hover(); break; + case L'o': + player_queue_clear(); + break; case L'c': player_toggle_pause(); break; @@ -812,6 +845,12 @@ main_input(wint_t c) case L'<': player_prev(); break; + case L'w': + autoplay.enabled ^= 1; + break; + case KEY_CTRL('s'): + autoplay.shuffle ^= 1; + break; case L'b': player_seek(0); break; @@ -869,6 +908,46 @@ usercmd_save(const char *args) return 1; } +void +update_player(void) +{ + static struct track *last = NULL; + struct track *track; + struct link *iter; + int index; + + player_update(); + + if (!player->loaded && autoplay.enabled && playlist.next) { + if (autoplay.shuffle) { + /* TODO better algorithm for random sequence */ + index = rand() % list_len(&playlist); + iter = link_iter(&playlist, index); + ASSERT(iter != NULL); + } else { + if (last) { + iter = playlist.next; + for (; iter; iter = iter->next) { + track = UPCAST(iter, struct ref)->data; + if (track == last) + break; + } + iter = iter->next; + if (!iter) { + last = NULL; + return; + } + } else { + iter = playlist.next; + } + } + track = UPCAST(iter, struct ref)->data; + player_play_track(track); + } else if (player->track) { + last = player->track; + } +} + int main(int argc, const char **argv) { @@ -879,7 +958,7 @@ main(int argc, const char **argv) c = KEY_RESIZE; do { - player_update(); + update_player(); if (c == KEY_RESIZE) { resize(); diff --git a/player.c b/player.c @@ -44,8 +44,8 @@ player_init(void) player->msg = NULL; player->msglvl = PLAYER_MSG_INFO; - mpd_run_stop(player->conn); - mpd_run_clear(player->conn); + // mpd_run_stop(player->conn); + // mpd_run_clear(player->conn); } void @@ -53,7 +53,7 @@ player_free(void) { if (!player->conn) return; mpd_run_stop(player->conn); - mpd_run_clear(player->conn); + // mpd_run_clear(player->conn); mpd_connection_free(player->conn); }