Subsonic API: added 'roles' in artist entries
This commit is contained in:
@@ -307,7 +307,7 @@ namespace API::Subsonic
|
||||
Response resp{ (itEntryPoint->second.func)(requestContext) };
|
||||
|
||||
resp.write(response.out(), format);
|
||||
response.setMimeType(ResponseFormatToMimeType(format));
|
||||
response.setMimeType(std::string{ ResponseFormatToMimeType(format) });
|
||||
|
||||
LMS_LOG(API_SUBSONIC, DEBUG) << "Request " << requestId << " '" << requestPath << "' handled!";
|
||||
return;
|
||||
@@ -331,7 +331,7 @@ namespace API::Subsonic
|
||||
<< ", code = " << static_cast<int>(e.getCode()) << ", msg = '" << e.getMessage() << "'";
|
||||
Response resp{ Response::createFailedResponse(protocolVersion, e) };
|
||||
resp.write(response.out(), format);
|
||||
response.setMimeType(ResponseFormatToMimeType(format));
|
||||
response.setMimeType(std::string{ ResponseFormatToMimeType(format) });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,8 +33,7 @@
|
||||
|
||||
namespace API::Subsonic
|
||||
{
|
||||
|
||||
std::string ResponseFormatToMimeType(ResponseFormat format)
|
||||
std::string_view ResponseFormatToMimeType(ResponseFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
@@ -47,7 +46,7 @@ namespace API::Subsonic
|
||||
|
||||
void Response::Node::setValue(std::string_view value)
|
||||
{
|
||||
if (!_children.empty() || !_childrenArrays.empty())
|
||||
if (!_children.empty() || !_childrenArrays.empty() || !_childrenValues.empty())
|
||||
throw LmsException{ "Node already has children" };
|
||||
|
||||
_value = std::string{ value };
|
||||
@@ -55,7 +54,7 @@ namespace API::Subsonic
|
||||
|
||||
void Response::Node::setValue(long long value)
|
||||
{
|
||||
if (!_children.empty() || !_childrenArrays.empty())
|
||||
if (!_children.empty() || !_childrenArrays.empty() || !_childrenValues.empty())
|
||||
throw LmsException{ "Node already has children" };
|
||||
|
||||
_value = value;
|
||||
@@ -82,6 +81,21 @@ namespace API::Subsonic
|
||||
_childrenArrays[key].emplace_back(std::move(node));
|
||||
}
|
||||
|
||||
void Response::Node::createArrayValue(const std::string& key)
|
||||
{
|
||||
if (_value)
|
||||
throw LmsException{ "Node already has a value" };
|
||||
|
||||
_childrenValues.emplace(key, std::vector<std::string>{});
|
||||
}
|
||||
|
||||
void Response::Node::addArrayValue(const std::string& key, std::string_view value)
|
||||
{
|
||||
if (_value)
|
||||
throw LmsException{ "Node already has a value" };
|
||||
|
||||
_childrenValues[key].push_back(std::string{ value });
|
||||
}
|
||||
|
||||
Response::Node& Response::Node::createChild(const std::string& key)
|
||||
{
|
||||
@@ -236,21 +250,28 @@ namespace API::Subsonic
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto itChildNode : node._children)
|
||||
for (const auto& [key, childNodes] : node._children)
|
||||
{
|
||||
for (const Response::Node& childNode : itChildNode.second)
|
||||
res[itChildNode.first] = nodeToJsonObject(childNode);
|
||||
for (const Response::Node& childNode : childNodes)
|
||||
res[key] = nodeToJsonObject(childNode);
|
||||
}
|
||||
|
||||
for (auto itChildArrayNode : node._childrenArrays)
|
||||
for (const auto& [key, childArrayNodes] : node._childrenArrays)
|
||||
{
|
||||
const std::vector<Response::Node>& childArrayNodes{ itChildArrayNode.second };
|
||||
|
||||
Json::Array array;
|
||||
for (const Response::Node& childNode : childArrayNodes)
|
||||
array.emplace_back(nodeToJsonObject(childNode));
|
||||
|
||||
res[itChildArrayNode.first] = std::move(array);
|
||||
res[key] = std::move(array);
|
||||
}
|
||||
|
||||
for (const auto& [key, childValues] : node._childrenValues)
|
||||
{
|
||||
Json::Array array;
|
||||
for (const std::string& childValue : childValues)
|
||||
array.emplace_back(Json::Value{ childValue });
|
||||
|
||||
res[key] = std::move(array);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace API::Subsonic
|
||||
json,
|
||||
};
|
||||
|
||||
std::string ResponseFormatToMimeType(ResponseFormat format);
|
||||
std::string_view ResponseFormatToMimeType(ResponseFormat format);
|
||||
|
||||
class Error
|
||||
{
|
||||
@@ -202,7 +202,7 @@ namespace API::Subsonic
|
||||
_attributes[std::string{ key }] = static_cast<long long>(value);
|
||||
}
|
||||
|
||||
// A Node has either a value or some children
|
||||
// A Node has either a single value or an array of values or some children
|
||||
void setValue(std::string_view value);
|
||||
void setValue(long long value);
|
||||
Node& createChild(const std::string& key);
|
||||
@@ -210,6 +210,8 @@ namespace API::Subsonic
|
||||
|
||||
void addChild(const std::string& key, Node node);
|
||||
void addArrayChild(const std::string& key, Node node);
|
||||
void createArrayValue(const std::string& key);
|
||||
void addArrayValue(const std::string& key, std::string_view value);
|
||||
|
||||
private:
|
||||
void setVersionAttribute(ProtocolVersion version);
|
||||
@@ -220,6 +222,7 @@ namespace API::Subsonic
|
||||
std::optional<ValueType> _value;
|
||||
std::map<std::string, std::vector<Node>> _children;
|
||||
std::map<std::string, std::vector<Node>> _childrenArrays;
|
||||
std::map<std::string, std::vector<std::string>> _childrenValues;
|
||||
};
|
||||
|
||||
static Response createOkResponse(ProtocolVersion protocolVersion);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "services/database/Artist.hpp"
|
||||
#include "services/database/Release.hpp"
|
||||
#include "services/database/TrackArtistLink.hpp"
|
||||
#include "services/database/User.hpp"
|
||||
#include "services/scrobbling/IScrobblingService.hpp"
|
||||
#include "utils/Service.hpp"
|
||||
@@ -50,6 +51,26 @@ namespace API::Subsonic
|
||||
|
||||
return StringUtils::joinStrings(names, ", ");
|
||||
}
|
||||
|
||||
std::string_view toString(TrackArtistLinkType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TrackArtistLinkType::Arranger: return "arranger";
|
||||
case TrackArtistLinkType::Artist: return "artist";
|
||||
case TrackArtistLinkType::Composer: return "composer";
|
||||
case TrackArtistLinkType::Conductor: return "conductor";
|
||||
case TrackArtistLinkType::Lyricist: return "lyricist";
|
||||
case TrackArtistLinkType::Mixer: return "mixer";
|
||||
case TrackArtistLinkType::Performer: return "performer";
|
||||
case TrackArtistLinkType::Producer: return "producrer";
|
||||
case TrackArtistLinkType::ReleaseArtist: return "albumartist";
|
||||
case TrackArtistLinkType::Remixer: return "remixer";
|
||||
case TrackArtistLinkType::Writer: return "writer";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
Response::Node createArtistNode(const Artist::pointer& artist, Session& session, const User::pointer& user, bool id3)
|
||||
@@ -73,8 +94,15 @@ namespace API::Subsonic
|
||||
std::optional<UUID> mbid {artist->getMBID()};
|
||||
artistNode.setAttribute("musicBrainzId", mbid ? mbid->getAsString() : "");
|
||||
}
|
||||
|
||||
artistNode.setAttribute("sortName", artist->getSortName());
|
||||
|
||||
// roles
|
||||
Response::Node roles;
|
||||
artistNode.createArrayValue("roles");
|
||||
for (const TrackArtistLinkType linkType : TrackArtistLink::findUsedTypes(session, artist->getId()))
|
||||
artistNode.addArrayValue("roles", Utils::toString(linkType));
|
||||
|
||||
return artistNode;
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "services/database/Object.hpp"
|
||||
#include "services/database/Types.hpp"
|
||||
#include "SubsonicResponse.hpp"
|
||||
|
||||
namespace Database
|
||||
@@ -36,6 +37,7 @@ namespace API::Subsonic
|
||||
namespace Utils
|
||||
{
|
||||
std::string joinArtistNames(const std::vector<Database::ObjectPtr<Database::Artist>>& artists);
|
||||
std::string_view toString(Database::TrackArtistLinkType type);
|
||||
}
|
||||
Response::Node createArtistNode(const Database::ObjectPtr<Database::Artist>& artist, Database::Session& session, const Database::ObjectPtr<Database::User>& user, bool id3);
|
||||
}
|
||||
Reference in New Issue
Block a user