Subsonic API: improved compatibility for DSub client

This commit is contained in:
emeric
2019-04-08 13:38:38 +02:00
parent 93cb5cd50c
commit 3da931e52a
4 changed files with 85 additions and 19 deletions
+79 -13
View File
@@ -32,6 +32,7 @@
#include "database/Release.hpp"
#include "database/Track.hpp"
#include "main/Services.hpp"
#include "similarity/SimilaritySearcher.hpp"
#include "utils/Logger.hpp"
#include "utils/Utils.hpp"
#include "SubsonicId.hpp"
@@ -48,6 +49,8 @@
#define GET_ALBUM_LIST2_URL "/rest/getAlbumList2.view"
#define GET_ALBUM_URL "/rest/getAlbum.view"
#define GET_ARTIST_URL "/rest/getArtist.view"
#define GET_ARTIST_INFO_URL "/rest/getArtistInfo.view"
#define GET_ARTIST_INFO2_URL "/rest/getArtistInfo2.view"
#define GET_ARTISTS_URL "/rest/getArtists.view"
#define GET_MUSIC_DIRECTORY_URL "/rest/getMusicDirectory.view"
#define GET_MUSIC_FOLDERS_URL "/rest/getMusicFolders.view"
@@ -76,6 +79,8 @@ static Response handleGetAlbumListRequest(const Wt::Http::ParameterMap& request,
static Response handleGetAlbumList2Request(const Wt::Http::ParameterMap& request, Database::Handler& db);
static Response handleGetAlbumRequest(const Wt::Http::ParameterMap& request, Database::Handler& db);
static Response handleGetArtistRequest(const Wt::Http::ParameterMap& request, Database::Handler& db);
static Response handleGetArtistInfoRequest(const Wt::Http::ParameterMap& request, Database::Handler& db);
static Response handleGetArtistInfo2Request(const Wt::Http::ParameterMap& request, Database::Handler& db);
static Response handleGetArtistsRequest(const Wt::Http::ParameterMap& request, Database::Handler& db);
static Response handleGetMusicDirectoryRequest(const Wt::Http::ParameterMap& request, Database::Handler& db);
static Response handleGetMusicFoldersRequest(const Wt::Http::ParameterMap& request, Database::Handler& db);
@@ -102,6 +107,8 @@ static std::map<std::string, RequestHandlerFunc> requestHandlers
{GET_ALBUM_LIST2_URL, handleGetAlbumList2Request},
{GET_ALBUM_URL, handleGetAlbumRequest},
{GET_ARTIST_URL, handleGetArtistRequest},
{GET_ARTIST_INFO_URL, handleGetArtistInfoRequest},
{GET_ARTIST_INFO2_URL, handleGetArtistInfo2Request},
{GET_ARTISTS_URL, handleGetArtistsRequest},
{GET_MUSIC_DIRECTORY_URL, handleGetMusicDirectoryRequest},
{GET_MUSIC_FOLDERS_URL, handleGetMusicFoldersRequest},
@@ -572,9 +579,7 @@ Response
handleGetAlbumListRequestCommon(const Wt::Http::ParameterMap& request, Database::Handler& db, bool id3)
{
// Mandatory params
auto type {getParameterAs<std::string>(request, "type")};
if (!type)
throw Error {Error::Code::RequiredParameterMissing};
std::string type {getMandatoryParameterAs<std::string>(request, "type")};
// Optional params
std::size_t size {getParameterAs<std::size_t>(request, "size").get_value_or(10)};
@@ -584,19 +589,35 @@ handleGetAlbumListRequestCommon(const Wt::Http::ParameterMap& request, Database:
Wt::Dbo::Transaction transaction {db.getSession()};
if (*type == "random")
if (type == "random")
{
releases = getRandomAlbums(db.getSession(), offset, size);
}
else if (*type == "newest")
else if (type == "newest")
{
auto after {Wt::WLocalDateTime::currentServerDateTime().toUTC().addMonths(-6)};
releases = Database::Release::getLastAdded(db.getSession(), after, offset, size);
}
else if (*type == "alphabeticalByName")
else if (type == "alphabeticalByName")
{
releases = Database::Release::getAll(db.getSession(), offset, size);
}
else if (type == "byGenre")
{
// Mandatory param
std::string genre {getMandatoryParameterAs<std::string>(request, "genre")};
Database::ClusterType::pointer clusterType {Database::ClusterType::getByName(db.getSession(), CLUSTER_TYPE_GENRE)};
if (clusterType)
{
Database::Cluster::pointer cluster {clusterType->getCluster(genre)};
if (cluster)
{
bool more;
releases = Database::Release::getByFilter(db.getSession(), {cluster.id()}, {}, offset, size, more);
}
}
}
else
throw Error {Error::CustomType::NotImplemented};
@@ -632,7 +653,7 @@ handleGetAlbumRequest(const Wt::Http::ParameterMap& request, Database::Handler&
Wt::Dbo::Transaction transaction {db.getSession()};
Database::Release::pointer release {Database::Release::getById(db.getSession(), id.id)};
Database::Release::pointer release {Database::Release::getById(db.getSession(), id.value)};
if (!release)
throw Error {Error::Code::RequestedDataNotFound};
@@ -659,7 +680,7 @@ handleGetArtistRequest(const Wt::Http::ParameterMap& request, Database::Handler&
Wt::Dbo::Transaction transaction {db.getSession()};
Database::Artist::pointer artist {Database::Artist::getById(db.getSession(), id.id)};
Database::Artist::pointer artist {Database::Artist::getById(db.getSession(), id.value)};
if (!artist)
throw Error {Error::Code::RequestedDataNotFound};
@@ -675,6 +696,51 @@ handleGetArtistRequest(const Wt::Http::ParameterMap& request, Database::Handler&
return response;
}
static
Response handleGetArtistInfoRequestCommon(const Wt::Http::ParameterMap& request, Database::Handler& db, bool id3)
{
// Mandatory params
Id id {getMandatoryParameterAs<Id>(request, "id")};
if (id.type != Id::Type::Artist)
throw Error {Error::CustomType::BadId};
// Optional params
std::size_t count {getParameterAs<std::size_t>(request, "count").get_value_or(10)};
Wt::Dbo::Transaction transaction {db.getSession()};
Database::Artist::pointer artist {Database::Artist::getById(db.getSession(), id.value)};
if (!artist)
throw Error {Error::Code::RequestedDataNotFound};
Response response {Response::createOkResponse()};
Response::Node& artistInfoNode {response.createNode(id3 ? "artistInfo2" : "artistInfo")};
if (!artist->getMBID().empty())
artistInfoNode.createChild("musicBrainzId").setValue(artist->getMBID());
auto similarArtistsId {getServices().similaritySearcher->getSimilarArtists(db.getSession(), artist.id(), count)};
for ( const auto& similarArtistId : similarArtistsId )
{
Database::Artist::pointer similarArtist {Database::Artist::getById(db.getSession(), similarArtistId)};
if (similarArtist)
artistInfoNode.addArrayChild("similarArtist", artistToResponseNode(similarArtist, id3));
}
return response;
}
Response handleGetArtistInfoRequest(const Wt::Http::ParameterMap& request, Database::Handler& db)
{
return handleGetArtistInfoRequestCommon(request, db, false /* no id3 */);
}
static Response handleGetArtistInfo2Request(const Wt::Http::ParameterMap& request, Database::Handler& db)
{
return handleGetArtistInfoRequestCommon(request, db, true /* id3 */);
}
Response
handleGetArtistsRequest(const Wt::Http::ParameterMap& request, Database::Handler& db)
{
@@ -724,7 +790,7 @@ handleGetMusicDirectoryRequest(const Wt::Http::ParameterMap& request, Database::
{
Wt::Dbo::Transaction transaction {db.getSession()};
auto artist {Database::Artist::getById(db.getSession(), id.id)};
auto artist {Database::Artist::getById(db.getSession(), id.value)};
if (!artist)
throw Error {Error::Code::RequestedDataNotFound};
@@ -741,7 +807,7 @@ handleGetMusicDirectoryRequest(const Wt::Http::ParameterMap& request, Database::
{
Wt::Dbo::Transaction transaction {db.getSession()};
auto release {Database::Release::getById(db.getSession(), id.id)};
auto release {Database::Release::getById(db.getSession(), id.value)};
if (!release)
throw Error {Error::Code::RequestedDataNotFound};
@@ -940,7 +1006,7 @@ createTranscoder(const Wt::Http::ParameterMap& request, Database::Handler& db)
{
Wt::Dbo::Transaction transaction {db.getSession()};
auto track {Database::Track::getById(db.getSession(), id.id)};
auto track {Database::Track::getById(db.getSession(), id.value)};
if (!track)
throw Error {Error::Code::RequestedDataNotFound};
@@ -1018,10 +1084,10 @@ handleGetCoverArt(const Wt::Http::Request& request, Database::Handler& db, Wt::H
switch (id.type)
{
case Id::Type::Track:
cover = getServices().coverArtGrabber->getFromTrack(db.getSession(), id.id, Image::Format::JPEG, *size);
cover = getServices().coverArtGrabber->getFromTrack(db.getSession(), id.value, Image::Format::JPEG, *size);
break;
case Id::Type::Release:
cover = getServices().coverArtGrabber->getFromRelease(db.getSession(), id.id, Image::Format::JPEG, *size);
cover = getServices().coverArtGrabber->getFromRelease(db.getSession(), id.value, Image::Format::JPEG, *size);
break;
default:
throw Error {Error::CustomType::BadId};