commit aab3e1e36c8ceeea1777d0114845a66280eb494c
parent e5a55cc4cd55d33e8bfb50cda1bfbd2526108c13
Author: Louis Burda <quent.burda@gmail.com>
Date: Thu, 31 Mar 2022 20:28:02 +0200
Replaced shuffle track selection and refactored player
Diffstat:
M | src/player.c | | | 136 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/player.h | | | 10 | ++++------ |
M | src/player_mpd.c | | | 240 | +++++++++++-------------------------------------------------------------------- |
3 files changed, 171 insertions(+), 215 deletions(-)
diff --git a/src/player.c b/src/player.c
@@ -1,2 +1,138 @@
#include "player.h"
+#include "list.h"
+#include "data.h"
+
+bool
+player_history_contains(struct track *cmp, int depth)
+{
+ struct link *link;
+ struct track *track;
+
+ link = list_back(&player.history);
+ while (LIST_INNER(link) && depth-- > 0) {
+ track = UPCAST(link, struct track, link_hs);
+ if (track == cmp)
+ return true;
+ link = link->prev;
+ }
+
+ return false;
+}
+
+struct track *
+playlist_track_next_unused(struct link *start)
+{
+ struct track *track;
+ struct link *link;
+ bool in_history;
+ int len;
+
+ track = NULL;
+
+ len = list_len(&player.playlist);
+ if (!len) return NULL;
+
+ link = start;
+ while (LIST_INNER(link)) {
+ track = UPCAST(link, struct track, link_pl);
+
+ in_history = player_history_contains(track, len - 2);
+ if (track != player.track && !in_history)
+ break;
+
+ link = link->next;
+ if (!LIST_INNER(link))
+ link = list_front(&player.playlist);
+
+ if (link == start)
+ return NULL;
+ }
+
+ return track;
+}
+
+struct track *
+player_next_from_playlist(void)
+{
+ struct link *link;
+ int index;
+
+ if (list_empty(&player.playlist))
+ return NULL;
+
+ if (player.shuffle) {
+ index = rand() % list_len(&player.playlist);
+ link = list_at(&player.playlist, index);
+ return playlist_track_next_unused(link);
+ } else {
+ if (player.track && link_inuse(&player.track->link_pl)) {
+ index = list_index(&player.playlist,
+ &player.track->link_pl);
+ if (index < 0) PANIC();
+ if (++index == list_len(&player.playlist))
+ return NULL;
+ } else {
+ index = 0;
+ }
+ link = list_at(&player.playlist, index);
+ return UPCAST(link, struct track, link_pl);
+ }
+
+ return NULL;
+}
+
+int
+player_prev(void)
+{
+ struct link *next;
+ struct track *track;
+
+ if (list_empty(&player.history))
+ return PLAYER_STATUS_ERR;
+
+ if (!player.track || !link_inuse(&player.track->link_hs)) {
+ next = list_back(&player.history);
+ } else if (LIST_INNER(player.track->link_hs.prev)) {
+ next = player.track->link_hs.prev;
+ } else {
+ return PLAYER_STATUS_ERR;
+ }
+
+ track = UPCAST(next, struct track, link_hs);
+ player_play_track(track, false);
+
+ return PLAYER_STATUS_OK;
+}
+
+int
+player_next(void)
+{
+ struct track *next_track;
+ struct link *link;
+ bool new_entry;
+
+ if (player.track && link_inuse(&player.track->link_hs)
+ && LIST_INNER(player.track->link_hs.next)) {
+ next_track = UPCAST(player.track->link_hs.next,
+ struct track, link_hs);
+ new_entry = false;
+ } else if (!list_empty(&player.queue)) {
+ link = list_pop_front(&player.queue);
+ next_track = UPCAST(link, struct track, link_pq);
+ new_entry = true;
+ } else {
+ next_track = player_next_from_playlist();
+ if (!next_track) goto clear;
+ new_entry = true;
+ }
+
+ player_play_track(next_track, new_entry);
+ return PLAYER_STATUS_OK;
+
+clear:
+ player_clear_track();
+ return PLAYER_STATUS_ERR;
+}
+
+
diff --git a/src/player.h b/src/player.h
@@ -21,12 +21,6 @@ enum {
PLAYER_STATE_STOPPED
};
-enum {
- PLAYER_ACTION_NONE,
- PLAYER_ACTION_PLAY_PREV,
- PLAYER_ACTION_PLAY_NEXT
-};
-
struct player {
/* list of tracks to choose from on prev / next */
struct list playlist; /* struct track (link_pl) */
@@ -72,6 +66,7 @@ void player_deinit(void);
void player_update(void);
int player_play_track(struct track *track, bool new);
+int player_clear_track(void);
int player_toggle_pause(void);
int player_pause(void);
@@ -84,5 +79,8 @@ int player_stop(void);
int player_set_volume(unsigned int vol);
+bool player_history_contains(struct track *track, int depth);
+struct track *playlist_track_next_unused(struct link *link);
+
extern struct player player;
diff --git a/src/player_mpd.c b/src/player_mpd.c
@@ -38,15 +38,7 @@ struct mpd_player mpd;
static void player_clear_status(void);
-static int mpd_handle_status(int status);
-
-static bool history_contains(struct track *track, int depth);
-
-static struct track *playlist_track_lru(int skip);
-static struct track *playlist_track_next_unused(int index);
-
-static void player_play_prev(void);
-static void player_play_next(void);
+static bool mpd_handle_status(int status);
static void player_add_history(struct track *track);
@@ -58,7 +50,7 @@ player_clear_status(void)
player.status_lvl = PLAYER_STATUS_MSG_NONE;
}
-int
+bool
mpd_handle_status(int status)
{
const char *errstr;
@@ -73,12 +65,12 @@ mpd_handle_status(int status)
case MPD_ERROR_SYSTEM:
errstr = mpd_connection_get_error_message(mpd.conn);
PLAYER_STATUS(ERR, "ERR - %s", errstr);
- return 1;
+ return false;
case MPD_ERROR_CLOSED:
ERROR("PLAYER: Connection abruptly closed");
}
- return 0;
+ return true;
}
char *
@@ -94,161 +86,6 @@ mpd_loaded_track_name(struct mpd_song *song)
return strdup(sep + 1);
}
-bool
-history_contains(struct track *cmp, int depth)
-{
- struct link *link;
- struct track *track;
-
- link = list_back(&player.history);
- while (LIST_INNER(link) && depth-- > 0) {
- track = UPCAST(link, struct track, link_hs);
- if (track == cmp)
- return true;
- link = link->prev;
- }
-
- return false;
-}
-
-struct track *
-playlist_track_lru(int skip)
-{
- struct track *track;
- struct link *link;
- int len;
-
- track = NULL;
-
- len = list_len(&player.playlist);
- link = list_front(&player.playlist);
- while (skip >= 0 && LIST_INNER(link)) {
- track = UPCAST(link, struct track, link_pl);
-
- if (!history_contains(track, len - 1))
- skip -= 1;
-
- if (skip < 0) break;
-
- link = link->next;
- if (!LIST_INNER(link))
- link = list_front(&player.playlist);
- }
-
- return track;
-}
-
-struct track *
-playlist_track_next_unused(int index)
-{
- struct track *track;
- struct link *link, *start;
- int len;
-
- track = NULL;
-
- if (!list_len(&player.playlist))
- return NULL;
-
- len = list_len(&player.playlist);
- start = link = list_at(&player.playlist, index);
- while (LIST_INNER(link)) {
- track = UPCAST(link, struct track, link_pl);
-
- if (!history_contains(track, len - 1))
- break;
-
- link = link->next;
- if (!LIST_INNER(link))
- link = list_front(&player.playlist);
-
- if (link == start)
- return NULL;
- }
-
- return track;
-}
-
-struct track *
-player_next_from_playlist(void)
-{
- int index;
-
- if (list_empty(&player.playlist))
- return NULL;
-
- if (player.track)
- player_add_history(player.track);
-
- if (player.shuffle) {
- index = rand() % list_len(&player.playlist);
- return playlist_track_lru(index);
- } else {
- if (player.track && link_inuse(&player.track->link_pl)) {
- index = list_index(&player.playlist, &player.track->link_pl);
- if (index < 0) PANIC();
- if (index == list_len(&player.playlist))
- index = 0;
- } else {
- index = 0;
- }
- return playlist_track_next_unused(index);
- }
-
- return NULL;
-}
-
-void
-player_play_prev(void)
-{
- struct link *next;
- struct track *track;
-
- if (list_empty(&player.history))
- return;
-
- if (!player.track || !link_inuse(&player.track->link_hs)) {
- next = list_back(&player.history);
- } else if (LIST_INNER(player.track->link_hs.prev)) {
- next = player.track->link_hs.prev;
- } else {
- return;
- }
-
- track = UPCAST(next, struct track, link_hs);
- player_play_track(track, false);
-}
-
-void
-player_play_next(void)
-{
- struct track *next_track;
- struct link *link;
- bool new_entry;
-
- if (player.track && link_inuse(&player.track->link_hs)
- && LIST_INNER(player.track->link_hs.next)) {
- next_track = UPCAST(player.track->link_hs.next,
- struct track, link_hs);
- new_entry = false;
- } else if (!list_empty(&player.queue)) {
- link = list_pop_front(&player.queue);
- next_track = UPCAST(link, struct track, link_pq);
- new_entry = true;
- } else {
- next_track = player_next_from_playlist();
- if (!next_track) goto clear;
- new_entry = true;
- }
-
- player_play_track(next_track, new_entry);
- return;
-
-clear:
- player.track = NULL;
- mpd_run_clear(mpd.conn);
-}
-
void
player_add_history(struct track *new)
{
@@ -269,7 +106,6 @@ void
player_init(void)
{
mpd.conn = NULL;
- mpd.action = PLAYER_ACTION_NONE;
mpd.seek_delay = 0;
list_init(&player.playlist);
@@ -333,28 +169,15 @@ player_update(void)
queue_empty = list_empty(&player.queue);
if (player.loaded && player.autoplay || !queue_empty)
- mpd.action = PLAYER_ACTION_PLAY_NEXT;
+ player_next();
} else {
mpd_song_free(current_song);
}
mpd_status_free(status);
- if (mpd.action != PLAYER_ACTION_NONE) {
- switch (mpd.action) {
- case PLAYER_ACTION_PLAY_PREV:
- player_play_prev();
- break;
- case PLAYER_ACTION_PLAY_NEXT:
- player_play_next();
- break;
- default:
- PANIC();
- }
-
- mpd.action = PLAYER_ACTION_NONE;
- }
-
+ /* in case autoplay loaded new track,
+ * get status and track name again.. */
status = mpd_run_status(mpd.conn);
if (!status) {
PLAYER_STATUS(ERR, "Resetting MPD server connection");
@@ -412,14 +235,15 @@ player_play_track(struct track *track, bool new)
ASSERT(track != NULL);
status = mpd_run_clear(mpd.conn);
- mpd_handle_status(status);
+ if (!mpd_handle_status(status))
+ return PLAYER_STATUS_ERR;
status = mpd_run_add(mpd.conn, track->fpath);
- if (mpd_handle_status(status))
+ if (!mpd_handle_status(status))
return PLAYER_STATUS_ERR;
status = mpd_run_play(mpd.conn);
- if (mpd_handle_status(status))
+ if (!mpd_handle_status(status))
return PLAYER_STATUS_ERR;
/* add last track to history */
@@ -435,53 +259,51 @@ player_play_track(struct track *track, bool new)
}
int
-player_toggle_pause(void)
+player_clear_track(void)
{
int status;
- status = mpd_run_toggle_pause(mpd.conn);
- if (mpd_handle_status(status))
+ player.track = NULL;
+ status = mpd_run_clear(mpd.conn);
+
+ if (!mpd_handle_status(status))
return PLAYER_STATUS_ERR;
return PLAYER_STATUS_OK;
}
int
-player_pause(void)
+player_toggle_pause(void)
{
int status;
- status = mpd_run_pause(mpd.conn, true);
- if (mpd_handle_status(status))
+ status = mpd_run_toggle_pause(mpd.conn);
+ if (!mpd_handle_status(status))
return PLAYER_STATUS_ERR;
return PLAYER_STATUS_OK;
}
int
-player_resume(void)
+player_pause(void)
{
int status;
- status = mpd_run_pause(mpd.conn, false);
- if (mpd_handle_status(status))
+ status = mpd_run_pause(mpd.conn, true);
+ if (!mpd_handle_status(status))
return PLAYER_STATUS_ERR;
return PLAYER_STATUS_OK;
}
int
-player_next(void)
+player_resume(void)
{
- mpd.action = PLAYER_ACTION_PLAY_NEXT;
-
- return PLAYER_STATUS_OK;
-}
+ int status;
-int
-player_prev(void)
-{
- mpd.action = PLAYER_ACTION_PLAY_PREV;
+ status = mpd_run_pause(mpd.conn, false);
+ if (!mpd_handle_status(status))
+ return PLAYER_STATUS_ERR;
return PLAYER_STATUS_OK;
}
@@ -492,7 +314,7 @@ player_play(void)
int status;
status = mpd_run_play(mpd.conn);
- if (mpd_handle_status(status))
+ if (!mpd_handle_status(status))
return PLAYER_STATUS_ERR;
return PLAYER_STATUS_OK;
@@ -504,7 +326,7 @@ player_stop(void)
int status;
status = mpd_run_stop(mpd.conn);
- if (mpd_handle_status(status))
+ if (!mpd_handle_status(status))
return PLAYER_STATUS_ERR;
return PLAYER_STATUS_OK;
@@ -522,7 +344,7 @@ player_seek(int sec)
}
status = mpd_run_seek_current(mpd.conn, sec, false);
- if (mpd_handle_status(status))
+ if (!mpd_handle_status(status))
return PLAYER_STATUS_ERR;
mpd.seek_delay = 7;
@@ -543,7 +365,7 @@ player_set_volume(unsigned int vol)
}
status = mpd_run_set_volume(mpd.conn, vol);
- if (mpd_handle_status(status))
+ if (!mpd_handle_status(status))
return PLAYER_STATUS_ERR;
return PLAYER_STATUS_OK;