mirror of
https://github.com/Goldenkrew3000/OSSP_OpenSource.git
synced 2025-12-19 00:04:44 +10:00
Added a basic play queue
This commit is contained in:
@@ -20,8 +20,10 @@
|
|||||||
extern configHandler_config_t* configObj;
|
extern configHandler_config_t* configObj;
|
||||||
bool bLikedSongsShow = false;
|
bool bLikedSongsShow = false;
|
||||||
bool bAudioSettingsShow = false;
|
bool bAudioSettingsShow = false;
|
||||||
|
bool bPlayQueueShow = false;
|
||||||
void showLikedSongs();
|
void showLikedSongs();
|
||||||
void showAudioSettings();
|
void showAudioSettings();
|
||||||
|
void showPlayQueue();
|
||||||
|
|
||||||
int gui_entry() {
|
int gui_entry() {
|
||||||
// Initialize SDL
|
// Initialize SDL
|
||||||
@@ -104,6 +106,12 @@ int gui_entry() {
|
|||||||
bAudioSettingsShow = true;
|
bAudioSettingsShow = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if (ImGui::Button("Play Queue")) {
|
||||||
|
bPlayQueueShow = true;
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,6 +123,10 @@ int gui_entry() {
|
|||||||
showAudioSettings();
|
showAudioSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bPlayQueueShow) {
|
||||||
|
showPlayQueue();
|
||||||
|
}
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
|
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
|
||||||
@@ -186,9 +198,10 @@ void showLikedSongs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (selectedSong != -1) {
|
if (selectedSong != -1) {
|
||||||
printf("Song: %s (%s)\n", starredStruct->songs[selectedSong].title,
|
OSSPlayer_QueueAppend(starredStruct->songs[selectedSong].title,
|
||||||
starredStruct->songs[selectedSong].id);
|
starredStruct->songs[selectedSong].artist,
|
||||||
OSSPlayer_QueueAppend(starredStruct->songs[selectedSong].id);
|
starredStruct->songs[selectedSong].id,
|
||||||
|
starredStruct->songs[selectedSong].duration);
|
||||||
selectedSong = -1;
|
selectedSong = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,3 +244,22 @@ void showAudioSettings() {
|
|||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: go through abstraction
|
||||||
|
#include "../player/playQueue.hpp"
|
||||||
|
|
||||||
|
void showPlayQueue() {
|
||||||
|
ImGui::Begin("Play Queue");
|
||||||
|
|
||||||
|
static int selectedSong = -1;
|
||||||
|
if (ImGui::BeginChild("Play Queue", ImVec2(0, 200), ImGuiChildFlags_Border)) {
|
||||||
|
for (int i = 0; i < internal_OSSPQ_GetItemCount(); i++) {
|
||||||
|
if (ImGui::Selectable(internal_OSSPQ_GetTitleAtIndex(i), selectedSong == i)) {
|
||||||
|
selectedSong = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,29 +5,82 @@
|
|||||||
* Info: Gstreamer Queue Handler
|
* Info: Gstreamer Queue Handler
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now you might ask why this even exists in this way, but I thought that it would be easier to jump to C++
|
||||||
|
* to store a song queue with objects instead of some hacked together solution in C
|
||||||
|
* And I was right.
|
||||||
|
* Like yeah, you can store an array of structs easily in C, but to dynamically be able to move those around, no,
|
||||||
|
* std::deque makes that MUCH simpler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include "playQueue.hpp"
|
#include "playQueue.hpp"
|
||||||
|
|
||||||
// NOTE: Acronym is OpenSubsonicPlayerQueue
|
// C++ interface for storing song queue data (C interface is in the header)
|
||||||
std::deque<std::string> OSSPQ_Items;
|
class SongObject {
|
||||||
|
public:
|
||||||
|
std::string title;
|
||||||
|
std::string artist;
|
||||||
|
std::string id;
|
||||||
|
long duration;
|
||||||
|
};
|
||||||
|
|
||||||
int internal_OSSPQ_AppendToEnd(char* id) {
|
// NOTE: Acronym is OpenSubsonicPlayerQueue
|
||||||
|
std::deque<SongObject> OSSPQ_Items;
|
||||||
|
|
||||||
|
int internal_OSSPQ_AppendToEnd(char* title, char* artist, char* id, long duration) {
|
||||||
|
// Append a new song to the end of the queue
|
||||||
|
printf("Title: %s\nArtist: %s\nID: %s\nDuration: %ld\n", title, artist, id, duration);
|
||||||
|
// TODO: Find a neater way of converting a C string to a C++ string??
|
||||||
|
std::string cpp_title(title);
|
||||||
|
std::string cpp_artist(artist);
|
||||||
std::string cpp_id(id);
|
std::string cpp_id(id);
|
||||||
OSSPQ_Items.push_back(cpp_id);
|
SongObject songObject;
|
||||||
|
songObject.title = cpp_title;
|
||||||
|
songObject.artist = cpp_artist;
|
||||||
|
songObject.id = cpp_id;
|
||||||
|
songObject.duration = duration;
|
||||||
|
OSSPQ_Items.push_back(songObject);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* internal_OSSPQ_PopFromFront() {
|
OSSPQ_SongStruct* internal_OSSPQ_PopFromFront() {
|
||||||
if (OSSPQ_Items.empty()) {
|
if (OSSPQ_Items.empty()) {
|
||||||
// No items in play queue
|
// No items in play queue
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* id = strdup(OSSPQ_Items.front().c_str()); // Heap allocate id
|
// Pull the first song off the song queue
|
||||||
|
SongObject songObject = OSSPQ_Items.front();
|
||||||
OSSPQ_Items.pop_front();
|
OSSPQ_Items.pop_front();
|
||||||
return id;
|
|
||||||
|
// Move song data into a C readable format
|
||||||
|
// NOTE: I am initializing the variables to a known value just in case there is missing information in songObject
|
||||||
|
OSSPQ_SongStruct* playQueueObject = (OSSPQ_SongStruct*)malloc(sizeof(OSSPQ_SongStruct));
|
||||||
|
playQueueObject->title = NULL;
|
||||||
|
playQueueObject->artist = NULL;
|
||||||
|
playQueueObject->id = NULL;
|
||||||
|
playQueueObject->duration = 0;
|
||||||
|
|
||||||
|
playQueueObject->title = strdup(songObject.title.c_str());
|
||||||
|
playQueueObject->artist = strdup(songObject.artist.c_str());
|
||||||
|
playQueueObject->id = strdup(songObject.id.c_str());
|
||||||
|
playQueueObject->duration = songObject.duration;
|
||||||
|
return playQueueObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
void internal_OSSPQ_FreeSongObject(OSSPQ_SongStruct* songObject) {
|
||||||
|
if (songObject->title != NULL) { free(songObject->title); }
|
||||||
|
if (songObject->artist != NULL) { free(songObject->artist); }
|
||||||
|
if (songObject->id != NULL) { free(songObject->id); }
|
||||||
|
if (songObject != NULL) { free(songObject); }
|
||||||
|
}
|
||||||
|
|
||||||
|
char* internal_OSSPQ_GetTitleAtIndex(int idx) {
|
||||||
|
return (char*)OSSPQ_Items[idx].title.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
int internal_OSSPQ_GetItemCount() {
|
int internal_OSSPQ_GetItemCount() {
|
||||||
|
|||||||
@@ -11,8 +11,18 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
int internal_OSSPQ_AppendToEnd(char* id);
|
// C interface for sending song queue data (C++ interface is in the C++ file)
|
||||||
char* internal_OSSPQ_PopFromFront();
|
typedef struct {
|
||||||
|
char* title;
|
||||||
|
char* artist;
|
||||||
|
char* id;
|
||||||
|
long duration;
|
||||||
|
} OSSPQ_SongStruct;
|
||||||
|
|
||||||
|
int internal_OSSPQ_AppendToEnd(char* title, char* artist, char* id, long duration);
|
||||||
|
OSSPQ_SongStruct* internal_OSSPQ_PopFromFront();
|
||||||
|
void internal_OSSPQ_FreeSongObject(OSSPQ_SongStruct* songObject);
|
||||||
|
char* internal_OSSPQ_GetTitleAtIndex(int idx);
|
||||||
int internal_OSSPQ_GetItemCount();
|
int internal_OSSPQ_GetItemCount();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -10,16 +10,14 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include "../configHandler.h"
|
#include "../configHandler.h"
|
||||||
#include "../discordrpc.h"
|
#include "../discordrpc.h"
|
||||||
#include "../libopensubsonic/logger.h"
|
#include "../libopensubsonic/logger.h"
|
||||||
#include "../libopensubsonic/endpoint_getSong.h"
|
#include "../libopensubsonic/endpoint_getSong.h"
|
||||||
#include "../libopensubsonic/httpclient.h"
|
#include "../libopensubsonic/httpclient.h"
|
||||||
#include "playQueue.hpp"
|
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
|
||||||
#include <unistd.h> // For worse sleep TODO
|
|
||||||
|
|
||||||
extern configHandler_config_t* configObj;
|
extern configHandler_config_t* configObj;
|
||||||
static int rc = 0;
|
static int rc = 0;
|
||||||
GstElement *pipeline, *playbin, *filter_bin, *conv_in, *conv_out, *in_volume, *equalizer, *pitch, *reverb, *out_volume;
|
GstElement *pipeline, *playbin, *filter_bin, *conv_in, *conv_out, *in_volume, *equalizer, *pitch, *reverb, *out_volume;
|
||||||
@@ -118,12 +116,15 @@ void* OSSPlayer_ThrdInit(void*) {
|
|||||||
if (internal_OSSPQ_GetItemCount() != 0 && isPlaying == false) {
|
if (internal_OSSPQ_GetItemCount() != 0 && isPlaying == false) {
|
||||||
printf("IS VALID\n");
|
printf("IS VALID\n");
|
||||||
// Player is not playing and a song is in the song queue
|
// Player is not playing and a song is in the song queue
|
||||||
char* id = OSSPlayer_QueuePopFront();
|
OSSPQ_SongStruct* pq = OSSPlayer_QueuePopFront();
|
||||||
if (id == NULL) {
|
if (pq == NULL) {
|
||||||
printf("FUCK\n");
|
printf("FUCK\n");
|
||||||
// TODO: this
|
// TODO: this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* id = strdup(pq->id);
|
||||||
|
//free(pq);
|
||||||
|
|
||||||
// NOTE: Using a few strdup()'s because the cleanup/deinit functions perform free's and to avoid UAFs/Double frees
|
// NOTE: Using a few strdup()'s because the cleanup/deinit functions perform free's and to avoid UAFs/Double frees
|
||||||
|
|
||||||
// Fetch song information
|
// Fetch song information
|
||||||
@@ -168,7 +169,7 @@ void* OSSPlayer_ThrdInit(void*) {
|
|||||||
isPlaying = true;
|
isPlaying = true;
|
||||||
gst_element_set_state(pipeline, GST_STATE_PLAYING);
|
gst_element_set_state(pipeline, GST_STATE_PLAYING);
|
||||||
}
|
}
|
||||||
usleep(200 * 1000); // Use futex and signals instead of this TODO
|
usleep(200 * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,8 +255,6 @@ int OSSPlayer_GstInit() {
|
|||||||
|
|
||||||
// Initialize equalizer
|
// Initialize equalizer
|
||||||
if (configObj->audio_equalizer_enable) {
|
if (configObj->audio_equalizer_enable) {
|
||||||
printf("Initializing %d equalizer bands...\n", configObj->audio_equalizer_graphCount);
|
|
||||||
|
|
||||||
// Dynamically append settings to the equalizer to match the config file
|
// Dynamically append settings to the equalizer to match the config file
|
||||||
for (int i = 0; i < configObj->audio_equalizer_graphCount; i++) {
|
for (int i = 0; i < configObj->audio_equalizer_graphCount; i++) {
|
||||||
char* ftl_name = NULL;
|
char* ftl_name = NULL;
|
||||||
@@ -335,20 +334,22 @@ int OSSPlayer_GstDeInit() {
|
|||||||
/*
|
/*
|
||||||
* Player Queue Control Functions
|
* Player Queue Control Functions
|
||||||
*/
|
*/
|
||||||
int OSSPlayer_QueueAppend(char* id) {
|
int OSSPlayer_QueueAppend(char* title, char* artist, char* id, long duration) {
|
||||||
// Call to C++ function
|
// Call to C++ function
|
||||||
internal_OSSPQ_AppendToEnd(id);
|
// Note: I would receive a song struct instead of individual elements, but it would significantly slow down the GUI
|
||||||
|
internal_OSSPQ_AppendToEnd(title, artist, id, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* OSSPlayer_QueuePopFront() {
|
OSSPQ_SongStruct* OSSPlayer_QueuePopFront() {
|
||||||
// Call to C++ function
|
// Call to C++ function
|
||||||
// NOTE: 'id' is heap-allocated from C++
|
|
||||||
char* id = internal_OSSPQ_PopFromFront();
|
OSSPQ_SongStruct* songObject = internal_OSSPQ_PopFromFront();
|
||||||
if (id == NULL) {
|
|
||||||
|
if (songObject == NULL) {
|
||||||
// Queue is empty TODO
|
// Queue is empty TODO
|
||||||
printf("FUCKFUCKFUCK\n");
|
printf("FUCKFUCKFUCK\n");
|
||||||
}
|
}
|
||||||
return id;
|
return songObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -11,11 +11,13 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "playQueue.hpp"
|
||||||
|
|
||||||
void* OSSPlayer_GMainLoop(void*);
|
void* OSSPlayer_GMainLoop(void*);
|
||||||
void* OSSPlayer_ThrdInit(void*);
|
void* OSSPlayer_ThrdInit(void*);
|
||||||
int OSSPlayer_GstInit();
|
int OSSPlayer_GstInit();
|
||||||
int OSSPlayer_QueueAppend(char* id);
|
int OSSPlayer_QueueAppend(char* title, char* artist, char* id, long duration);
|
||||||
char* OSSPlayer_QueuePopFront();
|
OSSPQ_SongStruct* OSSPlayer_QueuePopFront();
|
||||||
|
|
||||||
float OSSPlayer_GstECont_InVolume_Get();
|
float OSSPlayer_GstECont_InVolume_Get();
|
||||||
void OSSPlayer_GstECont_InVolume_set(float val);
|
void OSSPlayer_GstECont_InVolume_set(float val);
|
||||||
|
|||||||
Reference in New Issue
Block a user