tmus

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

commit 16449e8a72c7d9282647823d1747ae5696619d4f
parent f07580d31d1148c4a1811c36b09ca0ad50d9576b
Author: Louis Burda <quent.burda@gmail.com>
Date:   Mon, 27 Dec 2021 17:53:13 +0100

refactored autoplay and prev/next functionality

Diffstat:
M.gitignore | 1+
Msrc/list.c | 60+++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/list.h | 16++++++++--------
Msrc/main.c | 40+++++++++++++++++++---------------------
Msrc/player.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Msrc/player.h | 9+++++++++
Msrc/ref.c | 9++-------
Msrc/ref.h | 2+-
8 files changed, 146 insertions(+), 75 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -4,3 +4,4 @@ env.sh *.o todo build +*.gch diff --git a/src/list.c b/src/list.c @@ -1,9 +1,21 @@ #include "list.h" #include "util.h" +void +list_free(struct link *head, void (*free_item)(void *), int offset) +{ + struct link *item; + + while (head->next) { + item = link_pop(head->next); + free_item(((void *) item) - offset); + } +} + int list_empty(struct link *head) { + ASSERT(head != NULL); return head->next == NULL; } @@ -28,20 +40,37 @@ list_ffind(struct link *head, struct link *link) struct link *iter; ASSERT(head != NULL); - for (iter = head->next; iter && iter != link; iter = iter->next); - return (iter == link); } struct link * -link_back(struct link *link) +list_at(struct link *head, int n) { - ASSERT(link != NULL); + ASSERT(head != NULL); + return link_iter(head->next, n); +} - for (; link->next; link = link->next); +void +list_push_front(struct link *head, struct link *link) +{ + link_append(head, link); +} - return link; +void +list_push_back(struct link *cur, struct link *link) +{ + struct link *back; + + back = link_back(cur); + link_append(back, link); +} + +struct link * +list_pop_front(struct link *head) +{ + ASSERT(head != NULL); + return link_pop(head->next); } void @@ -73,6 +102,16 @@ link_append(struct link *cur, struct link *link) } struct link * +link_back(struct link *link) +{ + ASSERT(link != NULL); + + for (; link->next; link = link->next); + + return link; +} + +struct link * link_pop(struct link *link) { ASSERT(link != NULL); @@ -97,12 +136,3 @@ link_iter(struct link *link, int n) return link; } - -void -list_push_back(struct link *cur, struct link *link) -{ - struct link *back; - - back = link_back(cur); - link_append(back, link); -} diff --git a/src/list.h b/src/list.h @@ -2,10 +2,10 @@ #include <stdlib.h> -#define OFFSET(type, attr) ((size_t) &((type *)0)->attr) +#define LINK_OFFSET(type) ((size_t) &((type *)0)->link) #define UPCAST(ptr, type) ({ \ const typeof( ((type *)0)->link ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - OFFSET(type, link) ); }) + (type *)( (char *)__mptr - LINK_OFFSET(type) ); }) #define LIST_HEAD ((struct link) { .prev = NULL, .next = NULL }) #define LINK_EMPTY ((struct link) { 0 }) @@ -19,17 +19,17 @@ struct link { /* list_XXX functions operate on the list head */ +void list_free(struct link *head, void (*free_item)(void *), int offset); int list_empty(struct link *head); int list_len(struct link *head); int list_ffind(struct link *head, struct link *link); +struct link *list_at(struct link *head, int n); +void list_push_front(struct link *head, struct link *link); +void list_push_back(struct link *head, struct link *link); +struct link *list_pop_front(struct link *head); -struct link *link_back(struct link *list); void link_prepend(struct link *list, struct link *link); void link_append(struct link *list, struct link *link); +struct link *link_back(struct link *list); struct link *link_pop(struct link *link); - struct link *link_iter(struct link *link, int n); - -void list_push_back(struct link *list, struct link *link); - -//rstrrrstrssiimmrsrsssts diff --git a/src/main.c b/src/main.c @@ -548,9 +548,9 @@ track_input(wint_t c) listnav_update_sel(&track_nav, track_nav.sel + 1); return 1; case KEY_ENTER: - link = link_iter(tracks.next, track_nav.sel); + link = link_iter(playlist.next, track_nav.sel); ASSERT(link != NULL); - track = UPCAST(link, struct track); + track = UPCAST(link, struct ref)->data; player->track = track; player_play_track(track); return 1; @@ -848,7 +848,7 @@ main_input(wint_t c) case L'w': autoplay.enabled ^= 1; break; - case KEY_CTRL('s'): + case KEY_CTRL('w'): autoplay.shuffle ^= 1; break; case L'b': @@ -918,32 +918,30 @@ update_player(void) player_update(); - if (!player->loaded && autoplay.enabled && playlist.next) { + if (list_empty(&playlist)) last = NULL; + + /* dont start autoplay before the first song was chosen */ + if (!player->loaded && autoplay.enabled && last) { + iter = NULL; if (autoplay.shuffle) { /* TODO better algorithm for random sequence */ index = rand() % list_len(&playlist); - iter = link_iter(&playlist, index); + iter = link_iter(playlist.next, 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; + } 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) iter = playlist.next; + track = UPCAST(iter, struct ref)->data; player_play_track(track); - } else if (player->track) { + } else { last = player->track; } } diff --git a/src/player.c b/src/player.c @@ -32,6 +32,7 @@ player_init(void) ASSERT(player->conn != NULL); player->queue = LIST_HEAD; + player->history = LIST_HEAD; player->track = NULL; player->state = PLAYER_STATE_PAUSED; @@ -44,16 +45,20 @@ player_init(void) player->msg = NULL; player->msglvl = PLAYER_MSG_INFO; - // mpd_run_stop(player->conn); // mpd_run_clear(player->conn); } void player_free(void) { + struct link *iter; + if (!player->conn) return; - mpd_run_stop(player->conn); - // mpd_run_clear(player->conn); + + refs_free(&player->history); + refs_free(&player->queue); + + mpd_run_clear(player->conn); mpd_connection_free(player->conn); } @@ -62,9 +67,36 @@ player_update(void) { struct mpd_status *status; struct mpd_song *song; - struct ref *track; + struct ref *ref; const char *tmp; + if (player->action != PLAYER_ACTION_NONE) { + mpd_run_clear(player->conn); + + ref = NULL; + switch (player->action) { + case PLAYER_ACTION_PLAY_PREV: + if (!list_empty(&player->history)) + break; + ref = UPCAST(list_pop_front(&player->history), + struct ref); + player_play_track(ref->data); + ref_free(ref); + break; + case PLAYER_ACTION_PLAY_NEXT: + if (list_empty(&player->queue)) + break; + ref = UPCAST(list_pop_front(&player->queue), + struct ref); + player_play_track(ref->data); + ref_free(ref); + break; + default: + ASSERT(0); + } + player->action = PLAYER_ACTION_NONE; + } + status = mpd_run_status(player->conn); ASSERT(status != NULL); @@ -84,19 +116,11 @@ player_update(void) player->volume = mpd_status_get_volume(status); if (player->seek_delay) { - player->seek_delay -= 1; + player->seek_delay--; if (!player->seek_delay) player_play(); } - if (!mpd_run_current_song(player->conn) - && !list_empty(&player->queue)) { - track = UPCAST(link_pop(player->queue.next), - struct ref); - player_play_track(track->data); - ref_free(track); - } - song = mpd_run_current_song(player->conn); if (song) { player->loaded = true; @@ -104,6 +128,10 @@ player_update(void) player->time_end = mpd_song_get_duration(song); mpd_song_free(song); } else { + if (player->track) { + list_push_front(&player->history, + LINK(ref_init(player->track))); + } player->track = NULL; player->loaded = false; player->time_pos = 0; @@ -203,13 +231,15 @@ player_resume(void) int player_next(void) { - if (!player->loaded) return PLAYER_ERR; + player_clear_msg(); - if (!mpd_run_next(player->conn)) { - PLAYER_STATUS(PLAYER_MSG_ERR, "Playing next track failed"); - mpd_run_clearerror(player->conn); + if (!player->loaded) return PLAYER_ERR; - } + + if (!mpd_run_clear(player->conn)) + return PLAYER_ERR; + + player->action = PLAYER_ACTION_PLAY_NEXT; return PLAYER_OK; } @@ -218,13 +248,13 @@ int player_prev(void) { /* TODO prevent mpd from dying on error, how to use properly */ - if (!player->loaded) return PLAYER_ERR; + if (!player->loaded) + return PLAYER_ERR; - if (!mpd_run_previous(player->conn)) { - PLAYER_STATUS(PLAYER_MSG_ERR, "Playing prev track failed"); - mpd_run_clearerror(player->conn); + if (!mpd_run_clear(player->conn)) return PLAYER_ERR; - } + + player->action = PLAYER_ACTION_PLAY_PREV; return PLAYER_OK; } @@ -232,6 +262,8 @@ player_prev(void) int player_play(void) { + player_clear_msg(); + if (!mpd_run_play(player->conn)) { PLAYER_STATUS(PLAYER_MSG_ERR, "Playing track failed"); mpd_run_clearerror(player->conn); @@ -244,6 +276,8 @@ player_play(void) int player_stop(void) { + player_clear_msg(); + if (!mpd_run_stop(player->conn)) { PLAYER_STATUS(PLAYER_MSG_ERR, "Stopping track failed"); mpd_run_clearerror(player->conn); @@ -256,6 +290,8 @@ player_stop(void) int player_seek(int sec) { + player_clear_msg(); + if (!player->loaded || player->state == PLAYER_STATE_STOPPED) { PLAYER_STATUS(PLAYER_MSG_ERR, "No track loaded"); return PLAYER_ERR; @@ -276,6 +312,8 @@ player_seek(int sec) int player_set_volume(unsigned int vol) { + player_clear_msg(); + if (player->volume == -1) { PLAYER_STATUS(PLAYER_MSG_INFO, "Setting volume not supported"); mpd_run_clearerror(player->conn); diff --git a/src/player.h b/src/player.h @@ -20,18 +20,27 @@ enum { }; enum { + PLAYER_STATE_NONE, PLAYER_STATE_PAUSED, PLAYER_STATE_PLAYING, PLAYER_STATE_STOPPED }; +enum { + PLAYER_ACTION_NONE, + PLAYER_ACTION_PLAY_PREV, + PLAYER_ACTION_PLAY_NEXT +}; + struct player { struct mpd_connection *conn; struct link queue; + struct link history; struct track *track; int state; + int action; int seek_delay; int loaded; diff --git a/src/ref.c b/src/ref.c @@ -14,7 +14,7 @@ ref_init(void *data) } void -ref_free(struct ref *ref) +ref_free(void *ref) { free(ref); } @@ -22,12 +22,7 @@ ref_free(struct ref *ref) void refs_free(struct link *head) { - struct link *cur; - - while (head->next) { - cur = link_pop(head->next); - ref_free(UPCAST(cur, struct ref)); - } + list_free(head, ref_free, LINK_OFFSET(struct ref)); } static struct link * diff --git a/src/ref.h b/src/ref.h @@ -9,7 +9,7 @@ struct ref { }; struct ref *ref_init(void *data); -void ref_free(struct ref *ref); +void ref_free(void *ref); void refs_free(struct link *head); int refs_incl(struct link *head, void *data);