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:
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);