From 586e3dd03274e02ecbc05369559e7b48bd7c2022 Mon Sep 17 00:00:00 2001 From: Goldenkrew3000 Date: Fri, 20 Mar 2026 15:42:55 +1000 Subject: [PATCH] Changed architecture of the socket handling, and made http object cleanup more verbose --- src/libopensubsonic/httpclient.c | 1 + src/socket.c | 105 ++++++++++++++++++++++++++++++- src/socket.h | 7 +++ 3 files changed, 111 insertions(+), 2 deletions(-) diff --git a/src/libopensubsonic/httpclient.c b/src/libopensubsonic/httpclient.c index 5fab7ab..0d46d28 100644 --- a/src/libopensubsonic/httpclient.c +++ b/src/libopensubsonic/httpclient.c @@ -35,6 +35,7 @@ void opensubsonic_httpClient_URL_prepare(opensubsonic_httpClient_URL_t** urlObj) } void opensubsonic_httpClient_URL_cleanup(opensubsonic_httpClient_URL_t** urlObj) { + logger_log_general(__func__, "Freeing URL object with endpoint ID of %d.", (*urlObj)->endpoint); if ((*urlObj)->formedUrl != NULL) { free((*urlObj)->formedUrl); } if ((*urlObj)->id != NULL) { free((*urlObj)->id); } if (*urlObj != NULL) { free(*urlObj); } diff --git a/src/socket.c b/src/socket.c index 7cdf5d2..9e8ca7b 100644 --- a/src/socket.c +++ b/src/socket.c @@ -5,6 +5,12 @@ * Info: Socket Handler */ +/* + * Socket Policy: + * - The client shall not send a URL back to the server + * - The client shall only send back IDs + */ + #include #include #include @@ -18,9 +24,11 @@ #include "external/cJSON.h" #include "configHandler.h" #include "player/player.h" +#include "player/playQueue.hpp" #include "libopensubsonic/utils.h" #include "libopensubsonic/httpclient.h" #include "libopensubsonic/endpoint_getStarred.h" +#include "libopensubsonic/endpoint_getSong.h" #include "socket.h" static int server_fd = -1; @@ -175,7 +183,8 @@ void socketHandler_performAction(int id, char** retDataStr, cJSON** cliReqJson) cJSON_AddItemToObject(retData, "songs", songArray); for (int i = 0; i < getStarredStruct->songCount; i++) { - + // NOTE: For anything the client isn't directly accessing, only pass IDs + // Client uses cover art directly, so it needs a URL, but it only needs to pass a song ID back cJSON* song = cJSON_CreateObject(); cJSON_AddItemToObject(song, "title", cJSON_CreateString(getStarredStruct->songs[i].title)); cJSON_AddItemToObject(song, "album", cJSON_CreateString(getStarredStruct->songs[i].album)); @@ -185,7 +194,7 @@ void socketHandler_performAction(int id, char** retDataStr, cJSON** cliReqJson) cJSON_AddItemToObject(song, "duration", cJSON_CreateNumber(getStarredStruct->songs[i].duration)); cJSON_AddItemToObject(song, "albumId", cJSON_CreateString(getStarredStruct->songs[i].albumId)); cJSON_AddItemToObject(song, "artistId", cJSON_CreateString(getStarredStruct->songs[i].artistId)); - + // Convert cover art ID to URL opensubsonic_httpClient_URL_t* coverArtUrl = malloc(sizeof(opensubsonic_httpClient_URL_t)); opensubsonic_httpClient_URL_prepare(&coverArtUrl); @@ -206,6 +215,47 @@ void socketHandler_performAction(int id, char** retDataStr, cJSON** cliReqJson) + case OSSP_SOCKET_ACTION_NOW_PLAYING: + printf("[SocketHandler] Client requested Now Playing.\n"); + + cJSON* retDatab = cJSON_CreateObject(); + + int currentPos = OSSPQ_getCurrentPos(); + if (currentPos == 0) { + // No songs added to queue yet + cJSON_AddItemToObject(retDatab, "totalQueueCount", cJSON_CreateNumber(0)); + } else { + // At least a single song has been added to the queue + OSSPQ_SongStruct* nowPlaying = OSSPQ_getAtPos(currentPos); + if (nowPlaying == NULL) { + // Could not pull queue item + printf("[SocketHandler] --\n"); + } + + cJSON_AddItemToObject(retDatab, "songTitle", cJSON_CreateString(nowPlaying->title)); + cJSON_AddItemToObject(retDatab, "songAlbum", cJSON_CreateString(nowPlaying->album)); + cJSON_AddItemToObject(retDatab, "songArtist", cJSON_CreateString(nowPlaying->artist)); + //cJSON_AddItemToObject(retData, "duration", cJSON_CreateString()); + cJSON_AddItemToObject(retDatab, "coverArtUrl", cJSON_CreateString(nowPlaying->coverArtUrl)); + } + + + + + + printf("%s\n", cJSON_PrintUnformatted(retDatab)); + + + break; + + + case OSSP_SOCKET_ACTION_ADD_TO_QUEUE: + printf("[SocketHandler] Client requested OSSP_SOCKET_ACTION_ADD_TO_QUEUE.\n"); + OSSPS_SocketAction_Add_To_Queue(retDataStr, cliReqJson); + break; + + + case OSSP_SOCKET_ACTION_OSSPP_PREV: // break; @@ -241,7 +291,58 @@ void socketHandler_performAction(int id, char** retDataStr, cJSON** cliReqJson) +void OSSPS_SocketAction_Add_To_Queue(char** retDataStr, cJSON** cliReqJson) { + // Pull ID from request JSON + char* id = NULL; + OSS_Psoj(&id, *cliReqJson, "songId"); + if (id == NULL) { + printf("[SocketHandler] OSSP_SOCKET_ACTION_ADD_TO_QUEUE failed - 'id' is null.\n"); + *retDataStr = strdup("NOTOK"); + return; + } + // Create Stream URL from ID + opensubsonic_httpClient_URL_t* streamUrl = malloc(sizeof(opensubsonic_httpClient_URL_t)); + opensubsonic_httpClient_URL_prepare(&streamUrl); + streamUrl->endpoint = OPENSUBSONIC_ENDPOINT_STREAM; + streamUrl->id = strdup(id); + opensubsonic_httpClient_formUrl(&streamUrl); + + // Contact the /getSong endpoint + opensubsonic_httpClient_URL_t* songUrl = malloc(sizeof(opensubsonic_httpClient_URL_t)); + opensubsonic_httpClient_URL_prepare(&songUrl); + songUrl->endpoint = OPENSUBSONIC_ENDPOINT_GETSONG; + songUrl->id = strdup(id); + opensubsonic_httpClient_formUrl(&songUrl); + opensubsonic_getSong_struct* getSongStruct; + opensubsonic_httpClient_fetchResponse(&songUrl, (void**)&getSongStruct); + + // Create Cover Art URL from ID + opensubsonic_httpClient_URL_t* coverartUrl = (opensubsonic_httpClient_URL_t*)malloc(sizeof(opensubsonic_httpClient_URL_t)); + opensubsonic_httpClient_URL_prepare(&coverartUrl); + coverartUrl->endpoint = OPENSUBSONIC_ENDPOINT_GETCOVERART; + coverartUrl->id = strdup(id); + opensubsonic_httpClient_formUrl(&coverartUrl); + + // Append to queue + OSSPQ_AppendToEnd(getSongStruct->title, + getSongStruct->album, + getSongStruct->artist, + id, + streamUrl->formedUrl, + coverartUrl->formedUrl, + getSongStruct->duration, + OSSPQ_MODE_OPENSUBSONIC); + + // Free memory + opensubsonic_getSong_struct_free(&getSongStruct); + opensubsonic_httpClient_URL_cleanup(&songUrl); + opensubsonic_httpClient_URL_cleanup(&streamUrl); + opensubsonic_httpClient_URL_cleanup(&coverartUrl); + + *retDataStr = strdup("OK"); + return; +} diff --git a/src/socket.h b/src/socket.h index bfea028..4dd35de 100644 --- a/src/socket.h +++ b/src/socket.h @@ -1,10 +1,12 @@ #ifndef _SOCKET_H #define _SOCKET_H #include +#include "external/cJSON.h" #define OSSP_SOCKET_ACTION_GETSTARREDSONGS 101 #define OSSP_SOCKET_ACTION_NOW_PLAYING 201 #define OSSP_SOCKET_ACTION_STATS 202 +#define OSSP_SOCKET_ACTION_ADD_TO_QUEUE 203 #define OSSP_SOCKET_ACTION_OSSPP_PREV 301 // (OSSPP -> OSSP Player) #define OSSP_SOCKET_ACTION_OSSPP_PLAYPAUSE 302 @@ -41,4 +43,9 @@ int socketHandler_sendJson(char* json, int size); uint32_t socketHandlerUtil_byteArrToUint32BE(uint8_t buf[]); uint32_t socketHandlerUtil_byteArrToUint32LE(uint8_t buf[]); + + +// Testing +void OSSPS_SocketAction_Add_To_Queue(char** retDataStr, cJSON** cliReqJson); + #endif