Subsonic API: added 'contributor' in song entries

This commit is contained in:
emeric
2023-10-04 18:51:38 +02:00
parent 8f29410670
commit 4f25331e1d
8 changed files with 122 additions and 17 deletions
+1
View File
@@ -12,6 +12,7 @@ add_library(lmssubsonic SHARED
impl/responses/Album.cpp
impl/responses/Artist.cpp
impl/responses/Bookmark.cpp
impl/responses/Contributor.cpp
impl/responses/Genre.cpp
impl/responses/Playlist.cpp
impl/responses/Song.cpp
+10 -1
View File
@@ -73,6 +73,15 @@ namespace API::Subsonic
_children[key].emplace_back(std::move(node));
}
void Response::Node::createEmptyArrayChild(const std::string& key)
{
if (_value)
throw LmsException{ "Node already has a value" };
_childrenArrays.emplace(key, std::vector<Node>{});
}
void Response::Node::addArrayChild(const std::string& key, Node node)
{
if (_value)
@@ -81,7 +90,7 @@ namespace API::Subsonic
_childrenArrays[key].emplace_back(std::move(node));
}
void Response::Node::createArrayValue(const std::string& key)
void Response::Node::createEmptyArrayValue(const std::string& key)
{
if (_value)
throw LmsException{ "Node already has a value" };
+2 -1
View File
@@ -209,8 +209,9 @@ namespace API::Subsonic
Node& createArrayChild(const std::string& key);
void addChild(const std::string& key, Node node);
void createEmptyArrayChild(const std::string& key);
void addArrayChild(const std::string& key, Node node);
void createArrayValue(const std::string& key);
void createEmptyArrayValue(const std::string& key);
void addArrayValue(const std::string& key, std::string_view value);
private:
+25 -15
View File
@@ -56,17 +56,17 @@ namespace API::Subsonic
{
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";
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";
@@ -75,7 +75,7 @@ namespace API::Subsonic
Response::Node createArtistNode(const Artist::pointer& artist, Session& session, const User::pointer& user, bool id3)
{
Response::Node artistNode;
Response::Node artistNode{ createArtistNode(artist) };
artistNode.setAttribute("id", idToString(artist->getId()));
artistNode.setAttribute("name", artist->getName());
@@ -91,18 +91,28 @@ namespace API::Subsonic
// OpenSubsonic specific fields (must always be set)
{
std::optional<UUID> mbid {artist->getMBID()};
std::optional<UUID> mbid{ artist->getMBID() };
artistNode.setAttribute("musicBrainzId", mbid ? mbid->getAsString() : "");
}
artistNode.setAttribute("sortName", artist->getSortName());
// roles
Response::Node roles;
artistNode.createArrayValue("roles");
artistNode.createEmptyArrayValue("roles");
for (const TrackArtistLinkType linkType : TrackArtistLink::findUsedTypes(session, artist->getId()))
artistNode.addArrayValue("roles", Utils::toString(linkType));
return artistNode;
}
Response::Node createArtistNode(const Artist::pointer& artist)
{
Response::Node artistNode;
artistNode.setAttribute("id", idToString(artist->getId()));
artistNode.setAttribute("name", artist->getName());
return artistNode;
}
}
@@ -40,4 +40,5 @@ namespace API::Subsonic
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);
Response::Node createArtistNode(const Database::ObjectPtr<Database::Artist>& artist); // only minimal info
}
@@ -0,0 +1,40 @@
/*
* Copyright (C) 2023 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include "responses/Contributor.hpp"
#include "services/database/Object.hpp"
#include "services/database/TrackArtistLink.hpp"
#include "SubsonicResponse.hpp"
#include "responses/Artist.hpp"
namespace API::Subsonic
{
Response::Node createContributorNode(const Database::ObjectPtr<Database::TrackArtistLink>& trackArtistLink)
{
Response::Node contributorNode;
contributorNode.setAttribute("role", Utils::toString(trackArtistLink->getType()));
if (!trackArtistLink->getSubType().empty())
contributorNode.setAttribute("subRole", trackArtistLink->getSubType());
contributorNode.addChild("artist", createArtistNode(trackArtistLink->getArtist()));
return contributorNode;
}
}
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2023 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "services/database/Object.hpp"
#include "SubsonicResponse.hpp"
namespace Database
{
class TrackArtistLink;
}
namespace API::Subsonic
{
Response::Node createContributorNode(const Database::ObjectPtr<Database::TrackArtistLink>& trackArtistLink);
}
+10
View File
@@ -25,11 +25,13 @@
#include "services/database/Cluster.hpp"
#include "services/database/Release.hpp"
#include "services/database/Track.hpp"
#include "services/database/TrackArtistLink.hpp"
#include "services/database/User.hpp"
#include "services/scrobbling/IScrobblingService.hpp"
#include "utils/Service.hpp"
#include "utils/String.hpp"
#include "responses/Artist.hpp"
#include "responses/Contributor.hpp"
#include "SubsonicId.hpp"
#include "Utils.hpp"
@@ -159,6 +161,14 @@ namespace API::Subsonic
trackResponse.setAttribute("musicBrainzId", mbid ? mbid->getAsString() : "");
}
trackResponse.createEmptyArrayChild("contributors");
for (const TrackArtistLinkId linkId : TrackArtistLink::find(dbSession, TrackArtistLink::FindParameters{}.setTrack(track->getId())).results)
{
TrackArtistLink::pointer link{ TrackArtistLink::find(dbSession, linkId) };
if (link)
trackResponse.addArrayChild("contributors", createContributorNode(link));
}
return trackResponse;
}
}