Added example audio setting control from the interface, and drafted some configuration documentation

This commit is contained in:
2025-10-11 23:29:11 +10:00
parent 1808c80479
commit eca4db0b40
5 changed files with 121 additions and 23 deletions

27
ConfigDrafting.txt Normal file
View File

@@ -0,0 +1,27 @@
Opensubsonic Server Settings:
Protocol ('protocol') - Really it's either 'http' or 'https'
Server ('server') - The Opensubsonic server address, examples:
- 'server.com'
- 'music.server.com'
- 'music.server.com:4533'
- '192.168.1.5:8080'
'protocol' and 'server' are used to form the URL as 'protocol://server'
Username ('username') - Your Opensubsonic username
Password ('password') - Your Opensubsonic password
Scrobbler Settings:
TODO
Discord RPC Settings:
Enable ('enable') - 'true' to enable Discord RPC or 'false' to disable it
Method ('method'):
- Method '0' is the official local Discord RPC method, local application to local discord client
- Method '1' is a VERY buggy and in-development RPC method that uses a client-server model
to allow Discord RPC from a mobile device securely
Show System Details ('showSystemDetails') - 'true' or 'false'
- Want to show off / Got bragging rights on your _unique_ system?? Well this is perfect for you!
Setting this to 'true' shows the details of the operating system that OSSP is running on.
Example: 'on Linux x86_64 6.17.1-arch1-1' will be shown in the RPC dialog
Go on, don't be shy, show everyone you somehow have Discord and OSSP running on fucking s390x!!!
- Setting this to 'false' will simply instead show what playlist you are playing.

View File

@@ -67,8 +67,6 @@ void discordrpc_init() {
discordrpc_osString = discordrpc_getOS(); discordrpc_osString = discordrpc_getOS();
} }
#include <stdbool.h>
void discordrpc_update(discordrpc_data** discordrpc_struct) { void discordrpc_update(discordrpc_data** discordrpc_struct) {
printf("[DiscordRPC] Updating...\n"); printf("[DiscordRPC] Updating...\n");
DiscordRichPresence presence; DiscordRichPresence presence;

View File

@@ -12,7 +12,9 @@
extern configHandler_config_t* configObj; extern configHandler_config_t* configObj;
bool bLikedSongsShow = false; bool bLikedSongsShow = false;
bool bAudioSettingsShow = false;
void showLikedSongs(); void showLikedSongs();
void showAudioSettings();
int qt_gui_entry(int argc, char** argv) { int qt_gui_entry(int argc, char** argv) {
// Initialize SDL // Initialize SDL
@@ -89,6 +91,12 @@ int qt_gui_entry(int argc, char** argv) {
bLikedSongsShow = true; bLikedSongsShow = true;
} }
ImGui::SameLine();
if (ImGui::Button("Audio Settings")) {
bAudioSettingsShow = true;
}
ImGui::End(); ImGui::End();
} }
@@ -96,6 +104,10 @@ int qt_gui_entry(int argc, char** argv) {
showLikedSongs(); showLikedSongs();
} }
if (bAudioSettingsShow) {
showAudioSettings();
}
// 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);
@@ -155,6 +167,7 @@ void showLikedSongs() {
} }
static int selectedSong = -1; static int selectedSong = -1;
if (haveLikedSongsInfo) {
if (ImGui::BeginChild("Liked Songs", ImVec2(0, 200), ImGuiChildFlags_Border)) { if (ImGui::BeginChild("Liked Songs", ImVec2(0, 200), ImGuiChildFlags_Border)) {
for (int i = 0; i < starredStruct->songCount; i++) { for (int i = 0; i < starredStruct->songCount; i++) {
if (ImGui::Selectable(starredStruct->songs[i].title, selectedSong == i)) { if (ImGui::Selectable(starredStruct->songs[i].title, selectedSong == i)) {
@@ -163,6 +176,7 @@ void showLikedSongs() {
} }
ImGui::EndChild(); ImGui::EndChild();
} }
}
if (selectedSong != -1) { if (selectedSong != -1) {
printf("Song: %s (%s)\n", starredStruct->songs[selectedSong].title, printf("Song: %s (%s)\n", starredStruct->songs[selectedSong].title,
@@ -173,3 +187,22 @@ void showLikedSongs() {
ImGui::End(); ImGui::End();
} }
float in_volume_val = 0;
bool hasInVolumeFirstRun = false;
void showAudioSettings() {
ImGui::Begin("Audio Settings");
if (!hasInVolumeFirstRun) {
in_volume_val = OSSPlayer_GstECont_InVolume_Get();
hasInVolumeFirstRun = true;
}
// Idk what that field is, styling?, Size, Storage, Low, High
if (ImGui::VSliderFloat("##v", ImVec2(35, 160), &in_volume_val, 0.0f, 1.0f)) {
// Data has changed
OSSPlayer_GstECont_InVolume_set(in_volume_val);
}
ImGui::End();
}

View File

@@ -10,6 +10,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <pthread.h> #include <pthread.h>
#include "../configHandler.h" #include "../configHandler.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"
@@ -28,17 +29,22 @@ GMainLoop* loop;
bool isPlaying = false; bool isPlaying = false;
static gboolean gst_bus_call(GstBus* bus, GstMessage* message, gpointer data) { static gboolean gst_bus_call(GstBus* bus, GstMessage* message, gpointer data) {
printf("BUSCALL\n");
GMainLoop* loop = (GMainLoop*)data; GMainLoop* loop = (GMainLoop*)data;
switch (GST_MESSAGE_TYPE(message)) { switch (GST_MESSAGE_TYPE(message)) {
case GST_MESSAGE_EOS: case GST_MESSAGE_EOS:
printf("End of stream\n"); logger_log_important(__func__, "[GBus] End of stream");
gst_element_set_state(pipeline, GST_STATE_NULL); gst_element_set_state(pipeline, GST_STATE_NULL);
isPlaying = false; isPlaying = false;
break; break;
case GST_MESSAGE_BUFFERING:
gint percent = 0;
gst_message_parse_buffering(message, &percent);
printf("Buffering (%d%%)...\n", (int)percent);
break;
case GST_MESSAGE_ERROR: case GST_MESSAGE_ERROR:
printf("Error\n"); printf("Error\n");
break;
default: default:
printf("Unknown\n"); printf("Unknown\n");
break; break;
@@ -47,18 +53,20 @@ static gboolean gst_bus_call(GstBus* bus, GstMessage* message, gpointer data) {
return TRUE; return TRUE;
} }
void* OSSPlayer_GstMainLoop(void*) { void* OSSPlayer_GMainLoop(void*) {
printf("GstMainLoop running\n"); logger_log_important(__func__, "GMainLoop thread running.");
// This is needed for the Gstreamer bus to work, but it hangs the thread
g_main_loop_run(loop); g_main_loop_run(loop);
} }
void* OSSPlayer_ThrdInit(void*) { void* OSSPlayer_ThrdInit(void*) {
// Player init function for pthread entry // Player init function for pthread entry
printf("Player thread running.\n"); logger_log_important(__func__, "Player thread running.");
OSSPlayer_GstInit(); OSSPlayer_GstInit();
pthread_t pthr_gst; // Launch GMainLoop thread
pthread_create(&pthr_gst, NULL, OSSPlayer_GstMainLoop, NULL); pthread_t pthr_gml;
pthread_create(&pthr_gml, NULL, OSSPlayer_GMainLoop, NULL);
// Poll play queue for new items to play // Poll play queue for new items to play
while (true) { // TODO use global bool instead while (true) { // TODO use global bool instead
@@ -71,12 +79,29 @@ void* OSSPlayer_ThrdInit(void*) {
// TODO: this // TODO: this
} }
//opensubsonic_httpClient_URL_t* song_url = malloc(sizeof(opensubsonic_httpClient_URL_t)); // Fetch song information
//opensubsonic_httpClient_URL_prepare(&song_url); opensubsonic_httpClient_URL_t* song_url = malloc(sizeof(opensubsonic_httpClient_URL_t));
//song_url->endpoint = OPENSUBSONIC_ENDPOINT_GETSONG; opensubsonic_httpClient_URL_prepare(&song_url);
//song_url->id = id; song_url->endpoint = OPENSUBSONIC_ENDPOINT_GETSONG;
//opensubsonic_httpClient_formUrl(&song_url); song_url->id = strdup(id);
opensubsonic_httpClient_formUrl(&song_url);
opensubsonic_getSong_struct* songStruct;
opensubsonic_httpClient_fetchResponse(&song_url, (void**)&songStruct);
// Update Discord RPC
discordrpc_data* discordrpc = NULL;
discordrpc_struct_init(&discordrpc);
discordrpc->state = DISCORDRPC_STATE_PLAYING;
discordrpc->songTitle = strdup(songStruct->title);
discordrpc->songArtist = strdup(songStruct->artist);
//discordrpc->coverArtUrl = "https://pbs.twimg.com/profile_banners/2995329026/1758957365/1500x500";
discordrpc_update(&discordrpc);
discordrpc_struct_deinit(&discordrpc);
opensubsonic_getSong_struct_free(&songStruct);
opensubsonic_httpClient_URL_cleanup(&song_url);
// Create stream URL
opensubsonic_httpClient_URL_t* stream_url = malloc(sizeof(opensubsonic_httpClient_URL_t)); opensubsonic_httpClient_URL_t* stream_url = malloc(sizeof(opensubsonic_httpClient_URL_t));
opensubsonic_httpClient_URL_prepare(&stream_url); opensubsonic_httpClient_URL_prepare(&stream_url);
stream_url->endpoint = OPENSUBSONIC_ENDPOINT_STREAM; stream_url->endpoint = OPENSUBSONIC_ENDPOINT_STREAM;
@@ -87,7 +112,6 @@ void* OSSPlayer_ThrdInit(void*) {
isPlaying = true; isPlaying = true;
gst_element_set_state(pipeline, GST_STATE_PLAYING); gst_element_set_state(pipeline, GST_STATE_PLAYING);
} }
printf("Sleeping\n");
usleep(200 * 1000); // Use futex and signals instead of this TODO usleep(200 * 1000); // Use futex and signals instead of this TODO
} }
} }
@@ -230,9 +254,6 @@ int OSSPlayer_GstInit() {
g_object_set(equalizer, "enabled", true, NULL); g_object_set(equalizer, "enabled", true, NULL);
} }
//g_main_loop_run(loop);
} }
int OSSPlayer_GstDeInit() { int OSSPlayer_GstDeInit() {
@@ -249,6 +270,7 @@ int OSSPlayer_QueueAppend(char* id) {
char* OSSPlayer_QueuePopFront() { char* OSSPlayer_QueuePopFront() {
// Call to C++ function // Call to C++ function
// NOTE: 'id' is heap-allocated from C++
char* id = internal_OSSPQ_PopFromFront(); char* id = internal_OSSPQ_PopFromFront();
if (id == NULL) { if (id == NULL) {
// Queue is empty TODO // Queue is empty TODO
@@ -257,6 +279,19 @@ char* OSSPlayer_QueuePopFront() {
return id; return id;
} }
/*
* Gstreamer Element Control Functions
*/
float OSSPlayer_GstECont_InVolume_Get() {
gdouble vol;
g_object_get(in_volume, "volume", &vol, NULL);
return (float)vol;
}
void OSSPlayer_GstECont_InVolume_set(float val) {
g_object_set(in_volume, "volume", val, NULL);
}
/* /*
* Utility Functions * Utility Functions
*/ */

View File

@@ -5,10 +5,15 @@
extern "C" { extern "C" {
#endif #endif
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* id);
char* OSSPlayer_QueuePopFront(); char* OSSPlayer_QueuePopFront();
float OSSPlayer_GstECont_InVolume_Get();
void OSSPlayer_GstECont_InVolume_set(float val);
float OSSPlayer_DbLinMul(float db); float OSSPlayer_DbLinMul(float db);
float OSSPlayer_PitchFollow(float freq, float semitone); float OSSPlayer_PitchFollow(float freq, float semitone);