From b4351b8f48aa877ba69218eb2db24af5032b1add Mon Sep 17 00:00:00 2001 From: Goldenkrew3000 Date: Sat, 21 Mar 2026 09:45:09 +1000 Subject: [PATCH] Reworked GStreamer play queue system, now actually works --- src/player/playQueue.cpp | 56 ++++++++++++++++++++++++++++++++++++++++ src/player/playQueue.hpp | 9 ++++++- src/player/player.c | 27 +++++++++++++++++-- src/player/player.h | 3 +++ 4 files changed, 92 insertions(+), 3 deletions(-) diff --git a/src/player/playQueue.cpp b/src/player/playQueue.cpp index cca946d..2f1ef25 100644 --- a/src/player/playQueue.cpp +++ b/src/player/playQueue.cpp @@ -19,6 +19,8 @@ #include #include "playQueue.hpp" +int OSSPQ_currentPos = 0; + // C++ interface for storing song queue data (C interface is in the header) class OSSPQ_SongObject { public: @@ -66,6 +68,7 @@ int OSSPQ_AppendToEnd(char* title, char* album, char* artist, char* id, char* st return 0; } +/* OSSPQ_SongStruct* OSSPQ_PopFromFront() { // Check if song queue is empty, if not, then pop oldest if (OSSPQ_SongQueue.empty()) { @@ -102,6 +105,59 @@ OSSPQ_SongStruct* OSSPQ_PopFromFront() { return songObjectC; } +*/ + +int OSSPQ_getCurrentPos() { + return OSSPQ_currentPos; +} + +int OSSPQ_getTotalPos() { + return OSSPQ_SongQueue.size(); +} + +int OSSPQ_advancePos() { + OSSPQ_currentPos += 1; +} + +int OSSPQ_backtrackPos() { + OSSPQ_currentPos -= 1; +} + +OSSPQ_SongStruct* OSSPQ_getAtPos(int pos) { + // Check if song queue is empty, if not, then pop oldest + if (OSSPQ_SongQueue.empty()) { + return NULL; + } + OSSPQ_SongObject songObject = OSSPQ_SongQueue[pos]; + + // Allocate, initialize, and fill C compatible song object + OSSPQ_SongStruct* songObjectC = (OSSPQ_SongStruct*)malloc(sizeof(OSSPQ_SongStruct)); + songObjectC->title = NULL; + songObjectC->album = NULL; + songObjectC->artist = NULL; + songObjectC->id = NULL; + songObjectC->streamUrl = NULL; + songObjectC->coverArtUrl = NULL; + songObjectC->duration = 0; + songObjectC->mode = 0; + + if (songObject.mode == OSSPQ_MODE_OPENSUBSONIC || songObject.mode == OSSPQ_MODE_LOCALFILE) { + songObjectC->title = strdup(songObject.title.c_str()); + songObjectC->album = strdup(songObject.album.c_str()); + songObjectC->artist = strdup(songObject.artist.c_str()); + songObjectC->id = strdup(songObject.id.c_str()); + songObjectC->streamUrl = strdup(songObject.streamUrl.c_str()); + songObjectC->coverArtUrl = strdup(songObject.coverArtUrl.c_str()); + songObjectC->duration = songObject.duration; + songObjectC->mode = songObject.mode; + } else if (songObject.mode == OSSPQ_MODE_INTERNETRADIO) { + songObjectC->title = strdup(songObject.title.c_str()); + songObjectC->id = strdup(songObject.id.c_str()); + songObjectC->streamUrl = strdup(songObject.streamUrl.c_str()); + } + + return songObjectC; +} void OSSPQ_FreeSongObjectC(OSSPQ_SongStruct* songObjectC) { printf("[OSSPQ] Freeing SongObjectC.\n"); diff --git a/src/player/playQueue.hpp b/src/player/playQueue.hpp index dca6165..ac01698 100644 --- a/src/player/playQueue.hpp +++ b/src/player/playQueue.hpp @@ -28,13 +28,20 @@ typedef struct { } OSSPQ_SongStruct; int OSSPQ_AppendToEnd(char* title, char* album, char* artist, char* id, char* streamUrl, char* coverArtUrl, long duration, int mode); -OSSPQ_SongStruct* OSSPQ_PopFromFront(); +//OSSPQ_SongStruct* OSSPQ_PopFromFront(); void OSSPQ_FreeSongObjectC(OSSPQ_SongStruct* songObjectC); // TODO char* internal_OSSPQ_GetTitleAtIndex(int idx); int internal_OSSPQ_GetItemCount(); +// Testing +int OSSPQ_getCurrentPos(); +int OSSPQ_getTotalPos(); +int OSSPQ_advancePos(); +int OSSPQ_backtrackPos(); +OSSPQ_SongStruct* OSSPQ_getAtPos(int pos); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/src/player/player.c b/src/player/player.c index 2994f2f..159d363 100644 --- a/src/player/player.c +++ b/src/player/player.c @@ -38,6 +38,7 @@ static gboolean gst_bus_call(GstBus* bus, GstMessage* message, gpointer data) { switch (GST_MESSAGE_TYPE(message)) { case GST_MESSAGE_EOS: logger_log_important(__func__, "[GBus] End of stream"); + OSSPQ_advancePos(); // Move to next song in queue gst_element_set_state(pipeline, GST_STATE_NULL); isPlaying = false; break; @@ -122,7 +123,7 @@ void* OSSPlayer_ThrdInit(void* arg) { // Player is not playing and a song is in the song queue // Pull new song from the song queue - OSSPQ_SongStruct* songObject = OSSPQ_PopFromFront(); + OSSPQ_SongStruct* songObject = OSSPQ_getAtPos(OSSPQ_getCurrentPos()); if (songObject == NULL) { // Severe error - There was an item in the queue, but fetching it didn't work printf("[OSSPlayer]\n"); @@ -189,7 +190,8 @@ void* OSSPlayer_ThrdInit(void* arg) { } } - if (internal_OSSPQ_GetItemCount() == 0 && !isPlaying) { + //if (internal_OSSPQ_GetItemCount() == 0 && !isPlaying) { + if (OSSPQ_getCurrentPos() != OSSPQ_getTotalPos() && !isPlaying) { // No song currently playing, and the queue is empty // Only send idle Discord RPC if needed to avoid spamming @@ -430,10 +432,15 @@ void OSSPlayer_GstECont_Pitch_Set(float cents) { } void OSSPlayer_GstECont_Playbin3_Stop() { + OSSPQ_advancePos(); gst_element_set_state(pipeline, GST_STATE_NULL); // Stop playbin3 isPlaying = false; // Notify player thread to attempt to load next song } + + + + void OSSPlayer_GstECont_Playbin3_PlayPause() { GstState state; gst_element_get_state (pipeline, &state, NULL, 0); @@ -447,6 +454,22 @@ void OSSPlayer_GstECont_Playbin3_PlayPause() { } } +void OSSPlayer_GstECont_Playbin3_Prev() { + // Move queue back by one, then stop playbin3 and notify player thread + printf("[OSSPP] Moving the player queue back by one.\n"); + OSSPQ_backtrackPos(); + gst_element_set_state(pipeline, GST_STATE_NULL); + isPlaying = false; +} + +void OSSPlayer_GstECont_Playbin3_Next() { + // Same as *Playbin3_Prev(), but advance queue by one + printf("[OSSPP] Moving the player forward back by one.\n"); + OSSPQ_advancePos(); + gst_element_set_state(pipeline, GST_STATE_NULL); + isPlaying = false; +} + /* * Utility Functions */ diff --git a/src/player/player.h b/src/player/player.h index 4aa59e7..f367ec6 100644 --- a/src/player/player.h +++ b/src/player/player.h @@ -29,6 +29,9 @@ void OSSPlayer_GstECont_Pitch_Set(float cents); void OSSPlayer_GstECont_Playbin3_Stop(); void OSSPlayer_GstECont_Playbin3_PlayPause(); +void OSSPlayer_GstECont_Playbin3_Prev(); +void OSSPlayer_GstECont_Playbin3_Next(); + float OSSPlayer_DbLinMul(float db); float OSSPlayer_PitchFollow(float freq, float semitone); float OSSPlayer_CentsToPSF(float cents);