General cleanup and license handling

This commit is contained in:
2025-10-22 13:07:40 +10:00
parent a97b822fd8
commit e028b77ac0
11 changed files with 159 additions and 65 deletions

View File

@@ -1,3 +1,10 @@
/*
* OpenSubsonicPlayer
* Goldenkrew3000 2025
* License: GNU General Public License 3.0
* Info: Configuration Handler
*/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -19,7 +26,7 @@ static int rc = 0;
int configHandler_Read(configHandler_config_t** configObj) { int configHandler_Read(configHandler_config_t** configObj) {
// Allocate config object on heap // Allocate config object on heap
*configObj = malloc(sizeof(configHandler_config_t)); *configObj = malloc(sizeof(configHandler_config_t));
// Initialize struct variables // Initialize struct variables
(*configObj)->opensubsonic_protocol = NULL; (*configObj)->opensubsonic_protocol = NULL;
(*configObj)->opensubsonic_server = NULL; (*configObj)->opensubsonic_server = NULL;
@@ -59,11 +66,11 @@ int configHandler_Read(configHandler_config_t** configObj) {
(*configObj)->lv2_parax32_frequency_left = NULL; (*configObj)->lv2_parax32_frequency_left = NULL;
(*configObj)->lv2_parax32_frequency_right = NULL; (*configObj)->lv2_parax32_frequency_right = NULL;
(*configObj)->lv2_reverb_filter_name = NULL; (*configObj)->lv2_reverb_filter_name = NULL;
// Set internal configuration values // Set internal configuration values
(*configObj)->internal_opensubsonic_version = strdup("1.8.0"); (*configObj)->internal_opensubsonic_version = strdup("1.8.0");
(*configObj)->internal_opensubsonic_clientName = strdup("Hojuix_OSSP"); (*configObj)->internal_opensubsonic_clientName = strdup("Hojuix_OSSP");
// Form the path to the config JSON // Form the path to the config JSON
char* config_path = NULL; char* config_path = NULL;
#if defined(__APPLE__) && defined(__MACH__) && defined(XCODE) #if defined(__APPLE__) && defined(__MACH__) && defined(XCODE)
@@ -82,22 +89,24 @@ int configHandler_Read(configHandler_config_t** configObj) {
free(config_path); free(config_path);
return 1; return 1;
} }
// Read config file // Read config file
FILE* config_fd = NULL; FILE* config_fd = NULL;
char* config_buf = NULL; char* config_buf = NULL;
long config_fsize = 0; long config_fsize = 0;
long config_fread_rc = 0; // Needs to be separate from 'rc' as fread() returns bytes read long config_fread_rc = 0; // Needs to be separate from 'rc' as fread() returns bytes read
// Check if the config file exists, and fetch it's size // Check if the config file exists, and fetch it's size
struct stat st; struct stat st;
if (stat(config_path, &st) == 0) { if (stat(config_path, &st) == 0) {
config_fsize = st.st_size; config_fsize = st.st_size;
} else { } else {
logger_log_error(__func__, "stat() failed (Config file does not exist)."); logger_log_error(__func__, "stat() failed (Config file does not exist).");
logger_log_error(__func__, "This is most likely because your config file does not exist.");
logger_log_error(__func__, "Config file should be located at ~/.config/ossp/config.json");
return 1; return 1;
} }
// Actually open and read in the contents of the config file // Actually open and read in the contents of the config file
config_fd = fopen(config_path, "rb"); config_fd = fopen(config_path, "rb");
if (config_fd == NULL) { if (config_fd == NULL) {
@@ -106,14 +115,14 @@ int configHandler_Read(configHandler_config_t** configObj) {
return 1; return 1;
} }
free(config_path); free(config_path);
config_buf = (char*)malloc(config_fsize + 1); config_buf = (char*)malloc(config_fsize + 1);
if (config_buf == NULL) { if (config_buf == NULL) {
logger_log_error(__func__, "malloc() failed (Could not allocate enough memory for the config file)."); logger_log_error(__func__, "malloc() failed (Could not allocate enough memory for the config file).");
fclose(config_fd); fclose(config_fd);
return 1; return 1;
} }
config_fread_rc = fread(config_buf, 1, config_fsize, config_fd); config_fread_rc = fread(config_buf, 1, config_fsize, config_fd);
if (config_fread_rc != config_fsize) { if (config_fread_rc != config_fsize) {
logger_log_error(__func__, "fread() failed (Could not read the config file)."); logger_log_error(__func__, "fread() failed (Could not read the config file).");
@@ -121,11 +130,11 @@ int configHandler_Read(configHandler_config_t** configObj) {
free(config_buf); free(config_buf);
return 1; return 1;
} }
// Null terminate the buffer // Null terminate the buffer
config_buf[config_fsize] = '\0'; config_buf[config_fsize] = '\0';
fclose(config_fd); fclose(config_fd);
// Parse config JSON // Parse config JSON
cJSON* root = cJSON_Parse(config_buf); cJSON* root = cJSON_Parse(config_buf);
free(config_buf); free(config_buf);
@@ -133,7 +142,7 @@ int configHandler_Read(configHandler_config_t** configObj) {
logger_log_error(__func__, "cJSON_Parse() failed (Could not parse the configuration JSON)."); logger_log_error(__func__, "cJSON_Parse() failed (Could not parse the configuration JSON).");
return 1; return 1;
} }
// Make an object from opensubsonic_server // Make an object from opensubsonic_server
// TODO - Use the new OSS_P*oj functions? // TODO - Use the new OSS_P*oj functions?
cJSON* opensubsonic_server_root = cJSON_GetObjectItemCaseSensitive(root, "opensubsonic_server"); cJSON* opensubsonic_server_root = cJSON_GetObjectItemCaseSensitive(root, "opensubsonic_server");
@@ -142,27 +151,27 @@ int configHandler_Read(configHandler_config_t** configObj) {
cJSON_Delete(root); cJSON_Delete(root);
return 1; return 1;
} }
cJSON* opensubsonic_server_protocol = cJSON_GetObjectItemCaseSensitive(opensubsonic_server_root, "protocol"); cJSON* opensubsonic_server_protocol = cJSON_GetObjectItemCaseSensitive(opensubsonic_server_root, "protocol");
if (cJSON_IsString(opensubsonic_server_protocol) && opensubsonic_server_protocol->valuestring != NULL) { if (cJSON_IsString(opensubsonic_server_protocol) && opensubsonic_server_protocol->valuestring != NULL) {
(*configObj)->opensubsonic_protocol = strdup(opensubsonic_server_protocol->valuestring); (*configObj)->opensubsonic_protocol = strdup(opensubsonic_server_protocol->valuestring);
} }
cJSON* opensubsonic_server_server = cJSON_GetObjectItemCaseSensitive(opensubsonic_server_root, "server"); cJSON* opensubsonic_server_server = cJSON_GetObjectItemCaseSensitive(opensubsonic_server_root, "server");
if (cJSON_IsString(opensubsonic_server_server) && opensubsonic_server_server->valuestring != NULL) { if (cJSON_IsString(opensubsonic_server_server) && opensubsonic_server_server->valuestring != NULL) {
(*configObj)->opensubsonic_server = strdup(opensubsonic_server_server->valuestring); (*configObj)->opensubsonic_server = strdup(opensubsonic_server_server->valuestring);
} }
cJSON* opensubsonic_server_username = cJSON_GetObjectItemCaseSensitive(opensubsonic_server_root, "username"); cJSON* opensubsonic_server_username = cJSON_GetObjectItemCaseSensitive(opensubsonic_server_root, "username");
if (cJSON_IsString(opensubsonic_server_username) && opensubsonic_server_username->valuestring != NULL) { if (cJSON_IsString(opensubsonic_server_username) && opensubsonic_server_username->valuestring != NULL) {
(*configObj)->opensubsonic_username = strdup(opensubsonic_server_username->valuestring); (*configObj)->opensubsonic_username = strdup(opensubsonic_server_username->valuestring);
} }
cJSON* opensubsonic_server_password = cJSON_GetObjectItemCaseSensitive(opensubsonic_server_root, "password"); cJSON* opensubsonic_server_password = cJSON_GetObjectItemCaseSensitive(opensubsonic_server_root, "password");
if (cJSON_IsString(opensubsonic_server_password) && opensubsonic_server_password->valuestring != NULL) { if (cJSON_IsString(opensubsonic_server_password) && opensubsonic_server_password->valuestring != NULL) {
(*configObj)->opensubsonic_password = strdup(opensubsonic_server_password->valuestring); (*configObj)->opensubsonic_password = strdup(opensubsonic_server_password->valuestring);
} }
// Make an object from scrobbler // Make an object from scrobbler
cJSON* scrobbler_root = cJSON_GetObjectItemCaseSensitive(root, "scrobbler"); cJSON* scrobbler_root = cJSON_GetObjectItemCaseSensitive(root, "scrobbler");
if (scrobbler_root == NULL) { if (scrobbler_root == NULL) {
@@ -170,46 +179,46 @@ int configHandler_Read(configHandler_config_t** configObj) {
cJSON_Delete(root); cJSON_Delete(root);
return 1; return 1;
} }
cJSON* scrobbler_listenbrainz_enable = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "listenbrainz_enable"); cJSON* scrobbler_listenbrainz_enable = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "listenbrainz_enable");
if (cJSON_IsBool(scrobbler_listenbrainz_enable)) { if (cJSON_IsBool(scrobbler_listenbrainz_enable)) {
if (cJSON_IsTrue(scrobbler_listenbrainz_enable)) { if (cJSON_IsTrue(scrobbler_listenbrainz_enable)) {
(*configObj)->listenbrainz_enable = true; (*configObj)->listenbrainz_enable = true;
} }
} }
cJSON* scrobbler_listenbrainz_token = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "listenbrainz_token"); cJSON* scrobbler_listenbrainz_token = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "listenbrainz_token");
if (cJSON_IsString(scrobbler_listenbrainz_token) && scrobbler_listenbrainz_token->valuestring != NULL) { if (cJSON_IsString(scrobbler_listenbrainz_token) && scrobbler_listenbrainz_token->valuestring != NULL) {
(*configObj)->listenbrainz_token = strdup(scrobbler_listenbrainz_token->valuestring); (*configObj)->listenbrainz_token = strdup(scrobbler_listenbrainz_token->valuestring);
} }
cJSON* scrobbler_lastfm_enable = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "lastfm_enable"); cJSON* scrobbler_lastfm_enable = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "lastfm_enable");
if (cJSON_IsBool(scrobbler_lastfm_enable)) { if (cJSON_IsBool(scrobbler_lastfm_enable)) {
if (cJSON_IsTrue(scrobbler_lastfm_enable)) { if (cJSON_IsTrue(scrobbler_lastfm_enable)) {
(*configObj)->lastfm_enable = true; (*configObj)->lastfm_enable = true;
} }
} }
cJSON* scrobbler_lastfm_username = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "lastfm_username"); cJSON* scrobbler_lastfm_username = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "lastfm_username");
if (cJSON_IsString(scrobbler_lastfm_username) && scrobbler_lastfm_username->valuestring != NULL) { if (cJSON_IsString(scrobbler_lastfm_username) && scrobbler_lastfm_username->valuestring != NULL) {
(*configObj)->lastfm_username = strdup(scrobbler_lastfm_username->valuestring); (*configObj)->lastfm_username = strdup(scrobbler_lastfm_username->valuestring);
} }
cJSON* scrobbler_lastfm_password = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "lastfm_password"); cJSON* scrobbler_lastfm_password = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "lastfm_password");
if (cJSON_IsString(scrobbler_lastfm_password) && scrobbler_lastfm_password->valuestring != NULL) { if (cJSON_IsString(scrobbler_lastfm_password) && scrobbler_lastfm_password->valuestring != NULL) {
(*configObj)->lastfm_password = strdup(scrobbler_lastfm_password->valuestring); (*configObj)->lastfm_password = strdup(scrobbler_lastfm_password->valuestring);
} }
cJSON* scrobbler_lastfm_api_key = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "lastfm_api_key"); cJSON* scrobbler_lastfm_api_key = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "lastfm_api_key");
if (cJSON_IsString(scrobbler_lastfm_api_key) && scrobbler_lastfm_api_key->valuestring != NULL) { if (cJSON_IsString(scrobbler_lastfm_api_key) && scrobbler_lastfm_api_key->valuestring != NULL) {
(*configObj)->lastfm_api_key = strdup(scrobbler_lastfm_api_key->valuestring); (*configObj)->lastfm_api_key = strdup(scrobbler_lastfm_api_key->valuestring);
} }
cJSON* scrobbler_lastfm_api_secret = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "lastfm_api_secret"); cJSON* scrobbler_lastfm_api_secret = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "lastfm_api_secret");
if (cJSON_IsString(scrobbler_lastfm_api_secret) && scrobbler_lastfm_api_secret->valuestring != NULL) { if (cJSON_IsString(scrobbler_lastfm_api_secret) && scrobbler_lastfm_api_secret->valuestring != NULL) {
(*configObj)->lastfm_api_secret = strdup(scrobbler_lastfm_api_secret->valuestring); (*configObj)->lastfm_api_secret = strdup(scrobbler_lastfm_api_secret->valuestring);
} }
cJSON* scrobbler_lastfm_api_session_key = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "lastfm_session_key"); cJSON* scrobbler_lastfm_api_session_key = cJSON_GetObjectItemCaseSensitive(scrobbler_root, "lastfm_session_key");
if (cJSON_IsString(scrobbler_lastfm_api_session_key) && scrobbler_lastfm_api_session_key->valuestring != NULL) { if (cJSON_IsString(scrobbler_lastfm_api_session_key) && scrobbler_lastfm_api_session_key->valuestring != NULL) {
(*configObj)->lastfm_api_session_key = strdup(scrobbler_lastfm_api_session_key->valuestring); (*configObj)->lastfm_api_session_key = strdup(scrobbler_lastfm_api_session_key->valuestring);
@@ -249,7 +258,7 @@ int configHandler_Read(configHandler_config_t** configObj) {
cJSON_Delete(root); cJSON_Delete(root);
return 1; return 1;
} }
// Make an object from equalizer // Make an object from equalizer
cJSON* equalizer_root = cJSON_GetObjectItemCaseSensitive(audio_root, "equalizer"); cJSON* equalizer_root = cJSON_GetObjectItemCaseSensitive(audio_root, "equalizer");
if (equalizer_root == NULL) { if (equalizer_root == NULL) {
@@ -257,21 +266,21 @@ int configHandler_Read(configHandler_config_t** configObj) {
cJSON_Delete(root); cJSON_Delete(root);
return 1; return 1;
} }
cJSON* audio_equalizer_enable = cJSON_GetObjectItemCaseSensitive(equalizer_root, "enable"); cJSON* audio_equalizer_enable = cJSON_GetObjectItemCaseSensitive(equalizer_root, "enable");
if (cJSON_IsBool(audio_equalizer_enable)) { if (cJSON_IsBool(audio_equalizer_enable)) {
if (cJSON_IsTrue(audio_equalizer_enable)) { if (cJSON_IsTrue(audio_equalizer_enable)) {
(*configObj)->audio_equalizer_enable = true; (*configObj)->audio_equalizer_enable = true;
} }
} }
cJSON* audio_equalizer_followPitch = cJSON_GetObjectItemCaseSensitive(equalizer_root, "followPitch"); cJSON* audio_equalizer_followPitch = cJSON_GetObjectItemCaseSensitive(equalizer_root, "followPitch");
if (cJSON_IsBool(audio_equalizer_followPitch)) { if (cJSON_IsBool(audio_equalizer_followPitch)) {
if (cJSON_IsTrue(audio_equalizer_followPitch)) { if (cJSON_IsTrue(audio_equalizer_followPitch)) {
(*configObj)->audio_equalizer_followPitch = true; (*configObj)->audio_equalizer_followPitch = true;
} }
} }
// Fetch the equalizer graph array, and allocate memory for it // Fetch the equalizer graph array, and allocate memory for it
cJSON* equalizer_graph_array = cJSON_GetObjectItemCaseSensitive(equalizer_root, "graph"); cJSON* equalizer_graph_array = cJSON_GetObjectItemCaseSensitive(equalizer_root, "graph");
if (equalizer_graph_array == NULL) { if (equalizer_graph_array == NULL) {
@@ -279,7 +288,7 @@ int configHandler_Read(configHandler_config_t** configObj) {
cJSON_Delete(root); cJSON_Delete(root);
return 1; return 1;
} }
(*configObj)->audio_equalizer_graphCount = cJSON_GetArraySize(equalizer_graph_array); (*configObj)->audio_equalizer_graphCount = cJSON_GetArraySize(equalizer_graph_array);
(*configObj)->audio_equalizer_graph = (configHandler_eqGraph_t*)malloc((*configObj)->audio_equalizer_graphCount * sizeof(configHandler_eqGraph_t)); (*configObj)->audio_equalizer_graph = (configHandler_eqGraph_t*)malloc((*configObj)->audio_equalizer_graphCount * sizeof(configHandler_eqGraph_t));
if ((*configObj)->audio_equalizer_graph == NULL) { if ((*configObj)->audio_equalizer_graph == NULL) {
@@ -287,7 +296,7 @@ int configHandler_Read(configHandler_config_t** configObj) {
cJSON_Delete(root); cJSON_Delete(root);
return 1; return 1;
} }
// Initialize more struct variables // Initialize more struct variables
for (size_t i = 0; i < (*configObj)->audio_equalizer_graphCount; i++) { for (size_t i = 0; i < (*configObj)->audio_equalizer_graphCount; i++) {
(*configObj)->audio_equalizer_graph[i].bandwidth = 0.00; (*configObj)->audio_equalizer_graph[i].bandwidth = 0.00;
@@ -295,7 +304,7 @@ int configHandler_Read(configHandler_config_t** configObj) {
(*configObj)->audio_equalizer_graph[i].gain = 0.00; (*configObj)->audio_equalizer_graph[i].gain = 0.00;
(*configObj)->audio_equalizer_graph[i].bypass = false; (*configObj)->audio_equalizer_graph[i].bypass = false;
} }
for (size_t i = 0; i < (*configObj)->audio_equalizer_graphCount; i++) { for (size_t i = 0; i < (*configObj)->audio_equalizer_graphCount; i++) {
cJSON* array_equalizer_graph_root = cJSON_GetArrayItem(equalizer_graph_array, (int)i); cJSON* array_equalizer_graph_root = cJSON_GetArrayItem(equalizer_graph_array, (int)i);
if (array_equalizer_graph_root == NULL) { if (array_equalizer_graph_root == NULL) {
@@ -303,22 +312,22 @@ int configHandler_Read(configHandler_config_t** configObj) {
cJSON_Delete(root); cJSON_Delete(root);
return 1; return 1;
} }
cJSON* audio_equalizer_graph_bandwidth = cJSON_GetObjectItemCaseSensitive(array_equalizer_graph_root, "bandwidth"); cJSON* audio_equalizer_graph_bandwidth = cJSON_GetObjectItemCaseSensitive(array_equalizer_graph_root, "bandwidth");
if (cJSON_IsNumber(audio_equalizer_graph_bandwidth)) { if (cJSON_IsNumber(audio_equalizer_graph_bandwidth)) {
(*configObj)->audio_equalizer_graph[i].bandwidth = audio_equalizer_graph_bandwidth->valuedouble; (*configObj)->audio_equalizer_graph[i].bandwidth = audio_equalizer_graph_bandwidth->valuedouble;
} }
cJSON* audio_equalizer_graph_frequency = cJSON_GetObjectItemCaseSensitive(array_equalizer_graph_root, "frequency"); cJSON* audio_equalizer_graph_frequency = cJSON_GetObjectItemCaseSensitive(array_equalizer_graph_root, "frequency");
if (cJSON_IsNumber(audio_equalizer_graph_frequency)) { if (cJSON_IsNumber(audio_equalizer_graph_frequency)) {
(*configObj)->audio_equalizer_graph[i].frequency = audio_equalizer_graph_frequency->valueint; (*configObj)->audio_equalizer_graph[i].frequency = audio_equalizer_graph_frequency->valueint;
} }
cJSON* audio_equalizer_graph_gain = cJSON_GetObjectItemCaseSensitive(array_equalizer_graph_root, "gain"); cJSON* audio_equalizer_graph_gain = cJSON_GetObjectItemCaseSensitive(array_equalizer_graph_root, "gain");
if (cJSON_IsNumber(audio_equalizer_graph_gain)) { if (cJSON_IsNumber(audio_equalizer_graph_gain)) {
(*configObj)->audio_equalizer_graph[i].gain = audio_equalizer_graph_gain->valuedouble; (*configObj)->audio_equalizer_graph[i].gain = audio_equalizer_graph_gain->valuedouble;
} }
cJSON* audio_equalizer_graph_bypass = cJSON_GetObjectItemCaseSensitive(array_equalizer_graph_root, "bypass"); cJSON* audio_equalizer_graph_bypass = cJSON_GetObjectItemCaseSensitive(array_equalizer_graph_root, "bypass");
if (cJSON_IsBool(audio_equalizer_graph_bypass)) { if (cJSON_IsBool(audio_equalizer_graph_bypass)) {
if (cJSON_IsTrue(audio_equalizer_graph_bypass)) { if (cJSON_IsTrue(audio_equalizer_graph_bypass)) {
@@ -326,7 +335,7 @@ int configHandler_Read(configHandler_config_t** configObj) {
} }
} }
} }
// Make an object from pitch // Make an object from pitch
cJSON* pitch_root = cJSON_GetObjectItemCaseSensitive(audio_root, "pitch"); cJSON* pitch_root = cJSON_GetObjectItemCaseSensitive(audio_root, "pitch");
if (pitch_root == NULL) { if (pitch_root == NULL) {
@@ -334,24 +343,24 @@ int configHandler_Read(configHandler_config_t** configObj) {
cJSON_Delete(root); cJSON_Delete(root);
return 1; return 1;
} }
cJSON* audio_pitch_enable = cJSON_GetObjectItemCaseSensitive(pitch_root, "enable"); cJSON* audio_pitch_enable = cJSON_GetObjectItemCaseSensitive(pitch_root, "enable");
if (cJSON_IsBool(audio_pitch_enable)) { if (cJSON_IsBool(audio_pitch_enable)) {
if (cJSON_IsTrue(audio_pitch_enable)) { if (cJSON_IsTrue(audio_pitch_enable)) {
(*configObj)->audio_pitch_enable = true; (*configObj)->audio_pitch_enable = true;
} }
} }
cJSON* audio_pitch_cents = cJSON_GetObjectItemCaseSensitive(pitch_root, "cents"); cJSON* audio_pitch_cents = cJSON_GetObjectItemCaseSensitive(pitch_root, "cents");
if (cJSON_IsNumber(audio_pitch_cents)) { if (cJSON_IsNumber(audio_pitch_cents)) {
(*configObj)->audio_pitch_cents = audio_pitch_cents->valuedouble; (*configObj)->audio_pitch_cents = audio_pitch_cents->valuedouble;
} }
cJSON* audio_pitch_rate = cJSON_GetObjectItemCaseSensitive(pitch_root, "rate"); cJSON* audio_pitch_rate = cJSON_GetObjectItemCaseSensitive(pitch_root, "rate");
if (cJSON_IsNumber(audio_pitch_rate)) { if (cJSON_IsNumber(audio_pitch_rate)) {
(*configObj)->audio_pitch_rate = audio_pitch_rate->valuedouble; (*configObj)->audio_pitch_rate = audio_pitch_rate->valuedouble;
} }
// Make an object from reverb // Make an object from reverb
cJSON* reverb_root = cJSON_GetObjectItemCaseSensitive(audio_root, "reverb"); cJSON* reverb_root = cJSON_GetObjectItemCaseSensitive(audio_root, "reverb");
if (reverb_root == NULL) { if (reverb_root == NULL) {
@@ -359,14 +368,14 @@ int configHandler_Read(configHandler_config_t** configObj) {
cJSON_Delete(root); cJSON_Delete(root);
return 1; return 1;
} }
cJSON* audio_reverb_enable = cJSON_GetObjectItemCaseSensitive(reverb_root, "enable"); cJSON* audio_reverb_enable = cJSON_GetObjectItemCaseSensitive(reverb_root, "enable");
if (cJSON_IsBool(audio_reverb_enable)) { if (cJSON_IsBool(audio_reverb_enable)) {
if (cJSON_IsTrue(audio_reverb_enable)) { if (cJSON_IsTrue(audio_reverb_enable)) {
(*configObj)->audio_reverb_enable = true; (*configObj)->audio_reverb_enable = true;
} }
} }
cJSON* audio_reverb_wetDryMix = cJSON_GetObjectItemCaseSensitive(reverb_root, "wetDryMix"); cJSON* audio_reverb_wetDryMix = cJSON_GetObjectItemCaseSensitive(reverb_root, "wetDryMix");
if (cJSON_IsNumber(audio_reverb_wetDryMix)) { if (cJSON_IsNumber(audio_reverb_wetDryMix)) {
(*configObj)->audio_reverb_wetDryMix = audio_reverb_wetDryMix->valuedouble; (*configObj)->audio_reverb_wetDryMix = audio_reverb_wetDryMix->valuedouble;

View File

@@ -1,3 +1,9 @@
/*
* OpenSubsonicPlayer
* Goldenkrew3000 2025
* License: GNU General Public License 3.0
*/
#ifndef _CONFIG_HANDLER_H #ifndef _CONFIG_HANDLER_H
#define _CONFIG_HANDLER_H #define _CONFIG_HANDLER_H
#include <stdbool.h> #include <stdbool.h>
@@ -19,7 +25,7 @@ typedef struct {
char* internal_opensubsonic_clientName; // (Internal) Opensubsonic Client Name char* internal_opensubsonic_clientName; // (Internal) Opensubsonic Client Name
char* internal_opensubsonic_loginSalt; // (Internal) Opensubsonic Login Salt char* internal_opensubsonic_loginSalt; // (Internal) Opensubsonic Login Salt
char* internal_opensubsonic_loginToken; // (Internal) Opensubsonic Login Token char* internal_opensubsonic_loginToken; // (Internal) Opensubsonic Login Token
// Scrobbler Settings // Scrobbler Settings
bool listenbrainz_enable; // Enable ListenBrainz Scrobbling bool listenbrainz_enable; // Enable ListenBrainz Scrobbling
char* listenbrainz_token; // ListenBrainz Token char* listenbrainz_token; // ListenBrainz Token
@@ -29,12 +35,12 @@ typedef struct {
char* lastfm_api_key; // LastFM API Key char* lastfm_api_key; // LastFM API Key
char* lastfm_api_secret; // LastFM API Secret char* lastfm_api_secret; // LastFM API Secret
char* lastfm_api_session_key; // LastFM API Session Key (Generated from authorization endpoint) char* lastfm_api_session_key; // LastFM API Session Key (Generated from authorization endpoint)
// Discord RPC Settings // Discord RPC Settings
bool discordrpc_enable; // Enable Discord RPC bool discordrpc_enable; // Enable Discord RPC
int discordrpc_method; // Discord RPC Method (0 = Regular, 1 = DscrdRPC) int discordrpc_method; // Discord RPC Method (0 = Regular, 1 = DscrdRPC)
bool discordrpc_showSysDetails; // Show 'on OS ARCH VERSION' in RPC bool discordrpc_showSysDetails; // Show 'on OS ARCH VERSION' in RPC
// Audio Settings // Audio Settings
bool audio_equalizer_enable; bool audio_equalizer_enable;
bool audio_equalizer_followPitch; // Have equalizer align to pitch adjustment bool audio_equalizer_followPitch; // Have equalizer align to pitch adjustment

View File

@@ -1,7 +1,7 @@
/* /*
* OpenSubSonicPlayer * OpenSubSonicPlayer
* Goldenkrew3000 2025 * Goldenkrew3000 2025
* GPL-3.0 * License: GNU General Public License 3.0
* Discord Local RPC Handler * Discord Local RPC Handler
* Note: This provides server auth creds (encoded) directly to Discord, could use Spotify's API instead?? * Note: This provides server auth creds (encoded) directly to Discord, could use Spotify's API instead??
*/ */

View File

@@ -1,3 +1,9 @@
/*
* OpenSubsonicPlayer
* Goldenkrew3000 2025
* License: GNU General Public License 3.0
*/
#ifndef _DISCORDRPC_H #ifndef _DISCORDRPC_H
#define _DISCORDRPC_H #define _DISCORDRPC_H

View File

@@ -1,3 +1,10 @@
/*
* OpenSubsonicPlayer
* Goldenkrew3000 2025
* License: GNU General Public License 3.0
* Info: Debug / Prototype graphical interface
*/
#include "../external/imgui/imgui.h" #include "../external/imgui/imgui.h"
#include "../external/imgui/backends/imgui_impl_sdl2.h" #include "../external/imgui/backends/imgui_impl_sdl2.h"
#include "../external/imgui/backends/imgui_impl_opengl2.h" #include "../external/imgui/backends/imgui_impl_opengl2.h"
@@ -41,7 +48,7 @@ int qt_gui_entry(int argc, char** argv) {
SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GLContext gl_context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, gl_context); SDL_GL_MakeCurrent(window, gl_context);
SDL_GL_SetSwapInterval(1); // Vsync SDL_GL_SetSwapInterval(1); // Vsync
// Create ImGui context // Create ImGui context
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
ImGui::CreateContext(); ImGui::CreateContext();
@@ -116,7 +123,7 @@ int qt_gui_entry(int argc, char** argv) {
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
SDL_GL_SwapWindow(window); SDL_GL_SwapWindow(window);
} }
// Cleanup // Cleanup
ImGui_ImplOpenGL2_Shutdown(); ImGui_ImplOpenGL2_Shutdown();
ImGui_ImplSDL2_Shutdown(); ImGui_ImplSDL2_Shutdown();
@@ -155,7 +162,7 @@ void showLikedSongs() {
ImGui::Begin("Liked Songs"); ImGui::Begin("Liked Songs");
ImGui::Text("Liked Songs"); ImGui::Text("Liked Songs");
if (ImGui::Button("Close")) { if (ImGui::Button("Close")) {
bLikedSongsShow = false; bLikedSongsShow = false;
} }

View File

@@ -1,3 +1,8 @@
/*
* OpenSubsonicPlayer
* Goldenkrew3000 2025
* License: GNU General Public License 3.0
*/
#ifndef _GUI_ENTRY_HPP #ifndef _GUI_ENTRY_HPP
#define _GUI_ENTRY_HPP #define _GUI_ENTRY_HPP

View File

@@ -1,9 +1,15 @@
/*
* OpenSubsonicPlayer
* Goldenkrew3000 2025
* License: GNU General Public License 3.0
* Info: OSSP Entry Point
*/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <pthread.h> #include <pthread.h>
#include "gui/gui_entry.hpp" #include "gui/gui_entry.hpp"
#include "libopensubsonic/logger.h"
#include "libopensubsonic/crypto.h" #include "libopensubsonic/crypto.h"
#include "libopensubsonic/httpclient.h" #include "libopensubsonic/httpclient.h"
#include "libopensubsonic/endpoint_ping.h" #include "libopensubsonic/endpoint_ping.h"

View File

@@ -1,18 +1,18 @@
/*
* OpenSubsonicPlayer
* Goldenkrew3000 2025
* License: GNU General Public License 3.0
* Info: Gstreamer Queue Handler
*/
#include <string.h> #include <string.h>
#include <string> #include <string>
#include <deque> #include <deque>
#include "playQueue.hpp" #include "playQueue.hpp"
#include <iostream> // debug
// NOTE: Acronym is OpenSubsonicPlayerQueue // NOTE: Acronym is OpenSubsonicPlayerQueue
std::deque<std::string> OSSPQ_Items; std::deque<std::string> OSSPQ_Items;
int internal_OSSPQ_Init() {
//
}
int internal_OSSPQ_AppendToEnd(char* id) { int internal_OSSPQ_AppendToEnd(char* id) {
std::string cpp_id(id); std::string cpp_id(id);
OSSPQ_Items.push_back(cpp_id); OSSPQ_Items.push_back(cpp_id);

View File

@@ -1,3 +1,9 @@
/*
* OpenSubsonicPlayer
* Goldenkrew3000 2025
* License: GNU General Public License 3.0
*/
#ifndef _PLAYQUEUE_H #ifndef _PLAYQUEUE_H
#define _PLAYQUEUE_H #define _PLAYQUEUE_H

View File

@@ -1,7 +1,8 @@
/* /*
* OpenSubsonicPlayer * OpenSubsonicPlayer
* Goldenkrew3000 2025 * Goldenkrew3000 2025
* License: AGPL-3.0 * License: GNU General Public License 3.0
* Info: Gstreamer Handler
*/ */
#include <stdio.h> #include <stdio.h>
@@ -37,16 +38,56 @@ static gboolean gst_bus_call(GstBus* bus, GstMessage* message, gpointer data) {
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: case GST_MESSAGE_BUFFERING: {
gint percent = 0; gint percent = 0;
gst_message_parse_buffering(message, &percent); gst_message_parse_buffering(message, &percent);
printf("Buffering (%d%%)...\n", (int)percent); printf("Buffering (%d%%)...\n", (int)percent);
break; break;
case GST_MESSAGE_ERROR: }
printf("Error\n"); case GST_MESSAGE_ERROR: {
gchar* debug;
GError* error;
gst_message_parse_error(message, &error, &debug);
printf("Gstreamer Error: %s\n", error);
g_error_free(error);
g_free(debug);
break;
}
case GST_MESSAGE_STATE_CHANGED:
printf("State changed\n");
break;
case GST_MESSAGE_NEW_CLOCK:
//
break;
case GST_MESSAGE_LATENCY:
//
break;
case GST_MESSAGE_STREAM_START:
//
break;
case GST_MESSAGE_ELEMENT:
//
break;
case GST_MESSAGE_ASYNC_DONE:
//
break;
case GST_MESSAGE_STREAM_STATUS:
//
break;
case GST_MESSAGE_STREAMS_SELECTED:
//
break;
case GST_MESSAGE_STREAM_COLLECTION:
//
break;
case GST_MESSAGE_DURATION_CHANGED:
//
break;
case GST_MESSAGE_TAG:
// Unused
break; break;
default: default:
printf("Unknown\n"); printf("Unknown Message. Type %ld\n", GST_MESSAGE_TYPE(message));
break; break;
} }
@@ -202,10 +243,10 @@ int OSSPlayer_GstInit() {
// Initialize in-volume // Initialize in-volume
g_object_set(in_volume, "volume", 0.175, NULL); g_object_set(in_volume, "volume", 0.175, NULL);
// Initialize equalizer // Initialize equalizer
if (configObj->audio_equalizer_enable) { if (configObj->audio_equalizer_enable) {
printf("Initializing equalizer...\n"); 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++) {
@@ -235,7 +276,7 @@ int OSSPlayer_GstInit() {
gain = OSSPlayer_DbLinMul(gain); gain = OSSPlayer_DbLinMul(gain);
g_object_set(equalizer, gl_name, gain, NULL); g_object_set(equalizer, gl_name, gain, NULL);
g_object_set(equalizer, gr_name, gain, NULL); g_object_set(equalizer, gr_name, gain, NULL);
g_object_set(equalizer, ql_name, 4.36, NULL); g_object_set(equalizer, ql_name, 4.36, NULL);
g_object_set(equalizer, qr_name, 4.36, NULL); g_object_set(equalizer, qr_name, 4.36, NULL);
@@ -247,9 +288,11 @@ int OSSPlayer_GstInit() {
float freq = (float)configObj->audio_equalizer_graph[i].frequency; float freq = (float)configObj->audio_equalizer_graph[i].frequency;
float semitone = (float)configObj->audio_pitch_cents / 100.0; float semitone = (float)configObj->audio_pitch_cents / 100.0;
freq = OSSPlayer_PitchFollow(freq, semitone); freq = OSSPlayer_PitchFollow(freq, semitone);
printf("EQ band %d - F: %.2f(Fp) / G: %.2f / Q: 4.36\n", i + 1, freq, gain);
g_object_set(equalizer, fl_name, freq, NULL); g_object_set(equalizer, fl_name, freq, NULL);
g_object_set(equalizer, fr_name, freq, NULL); g_object_set(equalizer, fr_name, freq, NULL);
} else { } else {
printf("EQ band %d - F: %.2f / G: %.2f / Q: 4.36\n", i + 1, (float)configObj->audio_equalizer_graph[i].frequency, gain);
g_object_set(equalizer, fl_name, (float)configObj->audio_equalizer_graph[i].frequency, NULL); g_object_set(equalizer, fl_name, (float)configObj->audio_equalizer_graph[i].frequency, NULL);
g_object_set(equalizer, fr_name, (float)configObj->audio_equalizer_graph[i].frequency, NULL); g_object_set(equalizer, fr_name, (float)configObj->audio_equalizer_graph[i].frequency, NULL);
} }

View File

@@ -1,3 +1,9 @@
/*
* OpenSubsonicPlayer
* Goldenkrew3000 2025
* License: GNU General Public License 3.0
*/
#ifndef _PLAYER_H #ifndef _PLAYER_H
#define _PLAYER_H #define _PLAYER_H