diff --git a/src/libs/subsonic/impl/Scan.cpp b/src/libs/subsonic/impl/Scan.cpp index 2e359c5a..544f71dd 100644 --- a/src/libs/subsonic/impl/Scan.cpp +++ b/src/libs/subsonic/impl/Scan.cpp @@ -36,7 +36,7 @@ namespace API::Subsonic::Scan statusResponse.setAttribute("scanning", scanStatus.currentState == IMediaScanner::State::InProgress ? "true" : "false"); if (scanStatus.currentState == IMediaScanner::State::InProgress && scanStatus.inProgressScanStats) - statusResponse.setAttribute("count", std::to_string(scanStatus.inProgressScanStats->processedFiles)); + statusResponse.setAttribute("count", scanStatus.inProgressScanStats->processedFiles); return statusResponse; } diff --git a/src/libs/subsonic/impl/SubsonicResource.cpp b/src/libs/subsonic/impl/SubsonicResource.cpp index 0adefb39..ad53f93d 100644 --- a/src/libs/subsonic/impl/SubsonicResource.cpp +++ b/src/libs/subsonic/impl/SubsonicResource.cpp @@ -290,18 +290,18 @@ trackToResponseNode(const Track::pointer& track, Session& dbSession, const User: trackResponse.setAttribute("isDir", "false"); trackResponse.setAttribute("title", track->getName()); if (track->getTrackNumber()) - trackResponse.setAttribute("track", std::to_string(*track->getTrackNumber())); + trackResponse.setAttribute("track", *track->getTrackNumber()); if (track->getDiscNumber()) - trackResponse.setAttribute("discNumber", std::to_string(*track->getDiscNumber())); + trackResponse.setAttribute("discNumber", *track->getDiscNumber()); if (track->getYear()) - trackResponse.setAttribute("year", std::to_string(*track->getYear())); + trackResponse.setAttribute("year", *track->getYear()); trackResponse.setAttribute("path", getTrackPath(track)); { std::error_code ec; const auto fileSize {std::filesystem::file_size(track->getPath(), ec)}; if (!ec) - trackResponse.setAttribute("size", std::to_string(fileSize)); + trackResponse.setAttribute("size", fileSize); } if (track->getPath().has_extension()) @@ -331,7 +331,7 @@ trackToResponseNode(const Track::pointer& track, Session& dbSession, const User: trackResponse.setAttribute("parent", IdToString({Id::Type::Release, track->getRelease().id()})); } - trackResponse.setAttribute("duration", std::to_string(std::chrono::duration_cast(track->getDuration()).count())); + trackResponse.setAttribute("duration", std::chrono::duration_cast(track->getDuration()).count()); trackResponse.setAttribute("type", "music"); if (user->hasStarredTrack(track)) @@ -355,7 +355,7 @@ trackBookmarkToResponseNode(const TrackBookmark::pointer& trackBookmark) { Response::Node trackBookmarkNode; - trackBookmarkNode.setAttribute("position", std::to_string(trackBookmark->getOffset().count())); + trackBookmarkNode.setAttribute("position", trackBookmark->getOffset().count()); if (!trackBookmark->getComment().empty()) trackBookmarkNode.setAttribute("comment", trackBookmark->getComment()); trackBookmarkNode.setAttribute("created", reportedCreatedBookmarkDate); @@ -374,7 +374,7 @@ releaseToResponseNode(const Release::pointer& release, Session& dbSession, const if (id3) { albumNode.setAttribute("name", release->getName()); - albumNode.setAttribute("songCount", std::to_string(release->getTracksCount())); + albumNode.setAttribute("songCount", release->getTracksCount()); albumNode.setAttribute("duration", std::to_string(std::chrono::duration_cast(release->getDuration()).count())); } else @@ -387,7 +387,7 @@ releaseToResponseNode(const Release::pointer& release, Session& dbSession, const albumNode.setAttribute("coverArt", IdToString({Id::Type::Release, release.id()})); auto releaseYear {release->getReleaseYear()}; if (releaseYear) - albumNode.setAttribute("year", std::to_string(*releaseYear)); + albumNode.setAttribute("year", *releaseYear); auto artists {release->getReleaseArtists()}; if (artists.empty()) @@ -443,7 +443,7 @@ artistToResponseNode(const User::pointer& user, const Artist::pointer& artist, b artistNode.setAttribute("name", artist->getName()); if (id3) - artistNode.setAttribute("albumCount", std::to_string(artist->getReleaseCount())); + artistNode.setAttribute("albumCount", artist->getReleaseCount()); if (user->hasStarredArtist(artist)) artistNode.setAttribute("starred", reportedStarredDate); @@ -458,8 +458,8 @@ clusterToResponseNode(const Cluster::pointer& cluster) Response::Node clusterNode; clusterNode.setValue(cluster->getName()); - clusterNode.setAttribute("songCount", std::to_string(cluster->getTracksCount())); - clusterNode.setAttribute("albumCount", std::to_string(cluster->getReleasesCount())); + clusterNode.setAttribute("songCount", cluster->getTracksCount()); + clusterNode.setAttribute("albumCount", cluster->getReleasesCount()); return clusterNode; } @@ -1208,8 +1208,8 @@ tracklistToResponseNode(const TrackList::pointer& tracklist, Session&) playlistNode.setAttribute("id", IdToString({Id::Type::Playlist, tracklist.id()})); playlistNode.setAttribute("name", tracklist->getName()); - playlistNode.setAttribute("songCount", std::to_string(tracklist->getCount())); - playlistNode.setAttribute("duration", std::to_string(std::chrono::duration_cast(tracklist->getDuration()).count())); + playlistNode.setAttribute("songCount", tracklist->getCount()); + playlistNode.setAttribute("duration", std::chrono::duration_cast(tracklist->getDuration()).count()); playlistNode.setAttribute("public", tracklist->isPublic() ? "true" : "false"); playlistNode.setAttribute("created", ""); playlistNode.setAttribute("owner", tracklist->getUser()->getLoginName()); diff --git a/src/libs/subsonic/impl/SubsonicResponse.cpp b/src/libs/subsonic/impl/SubsonicResponse.cpp index b6b2431d..893be143 100644 --- a/src/libs/subsonic/impl/SubsonicResponse.cpp +++ b/src/libs/subsonic/impl/SubsonicResponse.cpp @@ -46,6 +46,15 @@ ResponseFormatToMimeType(ResponseFormat format) void Response::Node::setValue(std::string_view value) +{ + if (!_children.empty() || !_childrenArrays.empty()) + throw LmsException {"Node already has children"}; + + _value = std::string {value}; +} + +void +Response::Node::setValue(long long value) { if (!_children.empty() || !_childrenArrays.empty()) throw LmsException {"Node already has children"}; @@ -55,6 +64,12 @@ Response::Node::setValue(std::string_view value) void Response::Node::setAttribute(std::string_view key, std::string_view value) +{ + _attributes[std::string {key}] = std::string {value}; +} + +void +Response::Node::setAttribute(std::string_view key, long long value) { _attributes[std::string {key}] = value; } @@ -62,7 +77,7 @@ Response::Node::setAttribute(std::string_view key, std::string_view value) void Response::Node::addChild(const std::string& key, Node node) { - if (!_value.empty()) + if (_value.valueless_by_exception()) throw LmsException {"Node already has a value"}; _children[key].emplace_back(std::move(node)); @@ -71,7 +86,7 @@ Response::Node::addChild(const std::string& key, Node node) void Response::Node::addArrayChild(const std::string& key, Node node) { - if (!_value.empty()) + if (_value.valueless_by_exception()) throw LmsException {"Node already has a value"}; _childrenArrays[key].emplace_back(std::move(node)); @@ -160,11 +175,19 @@ Response::writeXML(std::ostream& os) boost::property_tree::ptree res; for (auto itAttribute : node._attributes) - res.put("." + itAttribute.first, itAttribute.second); - - if (!node._value.empty()) { - res.put_value(node._value); + if (std::holds_alternative(itAttribute.second)) + res.put("." + itAttribute.first, std::get(itAttribute.second)); + else if (std::holds_alternative(itAttribute.second)) + res.put("." + itAttribute.first, std::get(itAttribute.second)); + } + + if (node._value.valueless_by_exception()) + { + if (std::holds_alternative(node._value)) + res.put_value(std::get(node._value)); + else if (std::holds_alternative(node._value)) + res.put_value(std::get(node._value)); } else { @@ -200,11 +223,19 @@ Response::writeJSON(std::ostream& os) Json::Object res; for (auto itAttribute : node._attributes) - res[itAttribute.first] = Json::Value {itAttribute.second}; - - if (!node._value.empty()) { - res["value"] = Json::Value {node._value}; + if (std::holds_alternative(itAttribute.second)) + res[itAttribute.first] = Json::Value {std::get(itAttribute.second)}; + else if (std::holds_alternative(itAttribute.second)) + res[itAttribute.first] = Json::Value {std::get(itAttribute.second)}; + } + + if (node._value.valueless_by_exception()) + { + if (std::holds_alternative(node._value)) + res["value"] = Json::Value {std::get(node._value)}; + else if (std::holds_alternative(node._value)) + res["value"] = Json::Value {std::get(node._value)}; } else { diff --git a/src/libs/subsonic/impl/SubsonicResponse.hpp b/src/libs/subsonic/impl/SubsonicResponse.hpp index a88217ad..8354cbf2 100644 --- a/src/libs/subsonic/impl/SubsonicResponse.hpp +++ b/src/libs/subsonic/impl/SubsonicResponse.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -181,9 +182,11 @@ class Response { public: void setAttribute(std::string_view key, std::string_view value); + void setAttribute(std::string_view key, long long value); // A Node has either a value or some children void setValue(std::string_view value); + void setValue(long long value); Node& createChild(const std::string& key); Node& createArrayChild(const std::string& key); @@ -192,8 +195,8 @@ class Response private: friend class Response; - std::map _attributes; - std::string _value; + std::map> _attributes; + std::variant _value; std::map> _children; std::map> _childrenArrays; };