#include #include #include #include "../external/cJSON.h" #include "logger.h" #include "utils.h" #include "endpoint_getStarred.h" // Returns 1 if failure occured, else 0 int opensubsonic_getStarred_parse(char* data, opensubsonic_getStarred_struct** getStarredStruct) { // Allocate and initialize *getStarredStruct = malloc(sizeof(opensubsonic_getStarred_struct)); (*getStarredStruct)->status = NULL; (*getStarredStruct)->errorMessage = NULL; (*getStarredStruct)->errorCode = 0; (*getStarredStruct)->artistCount = -1; (*getStarredStruct)->albumCount = -1; (*getStarredStruct)->songCount = -1; (*getStarredStruct)->artists = NULL; (*getStarredStruct)->albums = NULL; (*getStarredStruct)->songs = NULL; // Parse the JSON cJSON* root = cJSON_Parse(data); if (root == NULL) { logger_log_error(__func__, "Error parsing JSON."); return 1; } // Make an object from subsonic-response cJSON* subsonic_root = cJSON_GetObjectItemCaseSensitive(root, "subsonic-response"); if (subsonic_root == NULL) { logger_log_error(__func__, "Error handling JSON - subsonic-response does not exist."); cJSON_Delete(root); return 1; } // Check for error OSS_Psoj(&(*getStarredStruct)->status, subsonic_root, "status"); if (strstr((*getStarredStruct)->status, "ok") == NULL) { cJSON* subsonic_error = cJSON_GetObjectItemCaseSensitive(subsonic_root, "error"); if (subsonic_error == NULL) { logger_log_error(__func__, "API has indicated failure through status, but error does not exist."); cJSON_Delete(root); return 1; } OSS_Pioj(&(*getStarredStruct)->errorCode, subsonic_error, "code"); OSS_Psoj(&(*getStarredStruct)->errorMessage, subsonic_error, "message"); logger_log_error(__func__, "Error noted in JSON - Code %d: %s", (*getStarredStruct)->errorCode, (*getStarredStruct)->errorMessage); cJSON_Delete(root); return 1; } // Make an object from starred cJSON* starred_root = cJSON_GetObjectItemCaseSensitive(subsonic_root, "starred"); if (starred_root == NULL) { logger_log_error(__func__, "Error handling JSON - starred does not exist."); cJSON_Delete(root); return 1; } // Make an object from artist, album, and song cJSON* artist_root = cJSON_GetObjectItemCaseSensitive(starred_root, "artist"); if (artist_root == NULL) { logger_log_error(__func__, "Error handling JSON - artist does not exist."); } else { (*getStarredStruct)->artistCount = 0; } cJSON* album_root = cJSON_GetObjectItemCaseSensitive(starred_root, "album"); if (album_root == NULL) { logger_log_error(__func__, "Error handling JSON - album does not exist."); } else { (*getStarredStruct)->albumCount = 0; } cJSON* song_root = cJSON_GetObjectItemCaseSensitive(starred_root, "song"); if (song_root == NULL) { logger_log_error(__func__, "Error handling JSON - song does not exist."); } else { (*getStarredStruct)->songCount = 0; } // Extract starred artists if ((*getStarredStruct)->artistCount != -1) { // Count, allocate, initialize, and extract (*getStarredStruct)->artistCount = cJSON_GetArraySize(artist_root); (*getStarredStruct)->artists = malloc((*getStarredStruct)->artistCount * sizeof(opensubsonic_getStarred_artist_struct)); for (int i = 0; i < (*getStarredStruct)->artistCount; i++) { (*getStarredStruct)->artists[i].id = NULL; (*getStarredStruct)->artists[i].name = NULL; (*getStarredStruct)->artists[i].coverArt = NULL; (*getStarredStruct)->artists[i].starred = NULL; } for (int i = 0; i < (*getStarredStruct)->artistCount; i++) { cJSON* array_artist_root = cJSON_GetArrayItem(artist_root, i); if (array_artist_root != NULL) { OSS_Psoj(&(*getStarredStruct)->artists[i].id, array_artist_root, "id"); OSS_Psoj(&(*getStarredStruct)->artists[i].name, array_artist_root, "name"); OSS_Psoj(&(*getStarredStruct)->artists[i].coverArt, array_artist_root, "coverArt"); OSS_Psoj(&(*getStarredStruct)->artists[i].starred, array_artist_root, "starred"); } } } else { // No starred artists (*getStarredStruct)->artistCount = 0; } // Extract starred albums if ((*getStarredStruct)->albumCount != -1) { // Count, allocate, initialize, and extract (*getStarredStruct)->albumCount = cJSON_GetArraySize(album_root); (*getStarredStruct)->albums = malloc((*getStarredStruct)->albumCount * sizeof(opensubsonic_getStarred_album_struct)); for (int i = 0; i < (*getStarredStruct)->albumCount; i++) { (*getStarredStruct)->albums[i].id = NULL; (*getStarredStruct)->albums[i].parent = NULL; (*getStarredStruct)->albums[i].album = NULL; (*getStarredStruct)->albums[i].title = NULL; (*getStarredStruct)->albums[i].name = NULL; (*getStarredStruct)->albums[i].coverArt = NULL; (*getStarredStruct)->albums[i].songCount = 0; (*getStarredStruct)->albums[i].created = NULL; (*getStarredStruct)->albums[i].duration = 0; (*getStarredStruct)->albums[i].playCount = 0; (*getStarredStruct)->albums[i].artistId = NULL; (*getStarredStruct)->albums[i].artist = NULL; (*getStarredStruct)->albums[i].year = 0; (*getStarredStruct)->albums[i].genre = NULL; } for (int i = 0; i < (*getStarredStruct)->albumCount; i++) { cJSON* array_album_root = cJSON_GetArrayItem(album_root, i); if (array_album_root != NULL) { OSS_Psoj(&(*getStarredStruct)->albums[i].id, array_album_root, "id"); OSS_Psoj(&(*getStarredStruct)->albums[i].parent, array_album_root, "parent"); OSS_Psoj(&(*getStarredStruct)->albums[i].album, array_album_root, "album"); OSS_Psoj(&(*getStarredStruct)->albums[i].title, array_album_root, "title"); OSS_Psoj(&(*getStarredStruct)->albums[i].name, array_album_root, "name"); OSS_Psoj(&(*getStarredStruct)->albums[i].coverArt, array_album_root, "coverArt"); OSS_Pioj(&(*getStarredStruct)->albums[i].songCount, array_album_root, "songCount"); OSS_Psoj(&(*getStarredStruct)->albums[i].created, array_album_root, "created"); OSS_Ploj(&(*getStarredStruct)->albums[i].duration, array_album_root, "duration"); OSS_Pioj(&(*getStarredStruct)->albums[i].playCount, array_album_root, "playCount"); OSS_Psoj(&(*getStarredStruct)->albums[i].artistId, array_album_root, "artistId"); OSS_Psoj(&(*getStarredStruct)->albums[i].artist, array_album_root, "artist"); OSS_Pioj(&(*getStarredStruct)->albums[i].year, array_album_root, "year"); OSS_Psoj(&(*getStarredStruct)->albums[i].genre, array_album_root, "genre"); } } } else { // No starred albums (*getStarredStruct)->albumCount = 0; } // Extract starred songs if ((*getStarredStruct)->songCount != -1) { // Count, allocate, initialize, and extract (*getStarredStruct)->songCount = cJSON_GetArraySize(song_root); (*getStarredStruct)->songs = malloc((*getStarredStruct)->songCount * sizeof(opensubsonic_getStarred_song_struct)); for (int i = 0; i < (*getStarredStruct)->songCount; i++) { (*getStarredStruct)->songs[i].id = NULL; (*getStarredStruct)->songs[i].parent = NULL; (*getStarredStruct)->songs[i].title = NULL; (*getStarredStruct)->songs[i].album = NULL; (*getStarredStruct)->songs[i].artist = NULL; (*getStarredStruct)->songs[i].track = 0; (*getStarredStruct)->songs[i].year = 0; (*getStarredStruct)->songs[i].coverArt = NULL; (*getStarredStruct)->songs[i].size = 0; (*getStarredStruct)->songs[i].starred = NULL; (*getStarredStruct)->songs[i].duration = 0; (*getStarredStruct)->songs[i].bitRate = 0; (*getStarredStruct)->songs[i].bitDepth = 0; (*getStarredStruct)->songs[i].samplingRate = 0; (*getStarredStruct)->songs[i].channelCount = 0; (*getStarredStruct)->songs[i].playCount = 0; (*getStarredStruct)->songs[i].discNumber = 0; (*getStarredStruct)->songs[i].created = NULL; (*getStarredStruct)->songs[i].albumId = NULL; (*getStarredStruct)->songs[i].artistId = NULL; } for (int i = 0; i < (*getStarredStruct)->songCount; i++) { cJSON* array_song_root = cJSON_GetArrayItem(song_root, i); if (array_song_root != NULL) { OSS_Psoj(&(*getStarredStruct)->songs[i].id, array_song_root, "id"); OSS_Psoj(&(*getStarredStruct)->songs[i].parent, array_song_root, "parent"); OSS_Psoj(&(*getStarredStruct)->songs[i].title, array_song_root, "title"); OSS_Psoj(&(*getStarredStruct)->songs[i].album, array_song_root, "album"); OSS_Psoj(&(*getStarredStruct)->songs[i].artist, array_song_root, "artist"); OSS_Pioj(&(*getStarredStruct)->songs[i].track, array_song_root, "track"); OSS_Pioj(&(*getStarredStruct)->songs[i].year, array_song_root, "year"); OSS_Psoj(&(*getStarredStruct)->songs[i].coverArt, array_song_root, "coverArt"); OSS_Ploj(&(*getStarredStruct)->songs[i].size, array_song_root, "size"); OSS_Psoj(&(*getStarredStruct)->songs[i].starred, array_song_root, "starred"); OSS_Ploj(&(*getStarredStruct)->songs[i].duration, array_song_root, "duration"); OSS_Pioj(&(*getStarredStruct)->songs[i].bitRate, array_song_root, "bitRate"); OSS_Pioj(&(*getStarredStruct)->songs[i].bitDepth, array_song_root, "bitDepth"); OSS_Ploj(&(*getStarredStruct)->songs[i].samplingRate, array_song_root, "samplingRate"); OSS_Pioj(&(*getStarredStruct)->songs[i].channelCount, array_song_root, "channelCount"); OSS_Pioj(&(*getStarredStruct)->songs[i].playCount, array_song_root, "playCount"); OSS_Pioj(&(*getStarredStruct)->songs[i].discNumber, array_song_root, "discNumber"); OSS_Psoj(&(*getStarredStruct)->songs[i].created, array_song_root, "created"); OSS_Psoj(&(*getStarredStruct)->songs[i].albumId, array_song_root, "albumId"); OSS_Psoj(&(*getStarredStruct)->songs[i].artistId, array_song_root, "artistId"); } } } else { // No starred songs (*getStarredStruct)->songCount = 0; } cJSON_Delete(root); return 0; } void opensubsonic_getStarred_struct_free(opensubsonic_getStarred_struct** getStarredStruct) { logger_log_general(__func__, "Freeing /getStarred endpoint heap objects."); if ((*getStarredStruct)->status != NULL) { free((*getStarredStruct)->status); } if ((*getStarredStruct)->errorMessage != NULL) { free((*getStarredStruct)->errorMessage); } for (int i = 0; i < (*getStarredStruct)->artistCount; i++) { if ((*getStarredStruct)->artists[i].id != NULL) { free((*getStarredStruct)->artists[i].id); } if ((*getStarredStruct)->artists[i].name != NULL) { free((*getStarredStruct)->artists[i].name); } if ((*getStarredStruct)->artists[i].coverArt != NULL) { free((*getStarredStruct)->artists[i].coverArt); } if ((*getStarredStruct)->artists[i].starred != NULL) { free((*getStarredStruct)->artists[i].starred); } } for (int i = 0; i < (*getStarredStruct)->albumCount; i++) { if ((*getStarredStruct)->albums[i].id != NULL) { free((*getStarredStruct)->albums[i].id); } if ((*getStarredStruct)->albums[i].parent != NULL) { free((*getStarredStruct)->albums[i].parent); } if ((*getStarredStruct)->albums[i].album != NULL) { free((*getStarredStruct)->albums[i].album); } if ((*getStarredStruct)->albums[i].title != NULL) { free((*getStarredStruct)->albums[i].title); } if ((*getStarredStruct)->albums[i].name != NULL) { free((*getStarredStruct)->albums[i].name); } if ((*getStarredStruct)->albums[i].coverArt != NULL) { free((*getStarredStruct)->albums[i].coverArt); } if ((*getStarredStruct)->albums[i].created != NULL) { free((*getStarredStruct)->albums[i].created); } if ((*getStarredStruct)->albums[i].artistId != NULL) { free((*getStarredStruct)->albums[i].artistId); } if ((*getStarredStruct)->albums[i].artist != NULL) { free((*getStarredStruct)->albums[i].artist); } if ((*getStarredStruct)->albums[i].genre != NULL) { free((*getStarredStruct)->albums[i].genre); } } for (int i = 0; i < (*getStarredStruct)->songCount; i++) { if ((*getStarredStruct)->songs[i].id != NULL) { free((*getStarredStruct)->songs[i].id); } if ((*getStarredStruct)->songs[i].parent != NULL) { free((*getStarredStruct)->songs[i].parent); } if ((*getStarredStruct)->songs[i].title != NULL) { free((*getStarredStruct)->songs[i].title); } if ((*getStarredStruct)->songs[i].album != NULL) { free((*getStarredStruct)->songs[i].album); } if ((*getStarredStruct)->songs[i].artist != NULL) { free((*getStarredStruct)->songs[i].artist); } if ((*getStarredStruct)->songs[i].coverArt != NULL) { free((*getStarredStruct)->songs[i].coverArt); } if ((*getStarredStruct)->songs[i].starred != NULL) { free((*getStarredStruct)->songs[i].starred); } if ((*getStarredStruct)->songs[i].created != NULL) { free((*getStarredStruct)->songs[i].created); } if ((*getStarredStruct)->songs[i].albumId != NULL) { free((*getStarredStruct)->songs[i].albumId); } if ((*getStarredStruct)->songs[i].artistId != NULL) { free((*getStarredStruct)->songs[i].artistId); } } if ((*getStarredStruct)->artists != NULL) { free((*getStarredStruct)->artists); } if ((*getStarredStruct)->albums != NULL) { free((*getStarredStruct)->albums); } if ((*getStarredStruct)->songs != NULL) { free((*getStarredStruct)->songs); } if (*getStarredStruct != NULL) { free(*getStarredStruct); } }