Refactored request context handling
This commit is contained in:
@@ -47,12 +47,12 @@ namespace lms::api::subsonic
|
||||
Response handleGetAlbumListRequestCommon(RequestContext& context, bool id3)
|
||||
{
|
||||
// Mandatory params
|
||||
const std::string type{ getMandatoryParameterAs<std::string>(context.parameters, "type") };
|
||||
const std::string type{ getMandatoryParameterAs<std::string>(context.getParameters(), "type") };
|
||||
|
||||
// Optional params
|
||||
const MediaLibraryId mediaLibraryId{ getParameterAs<MediaLibraryId>(context.parameters, "musicFolderId").value_or(MediaLibraryId{}) };
|
||||
const std::size_t size{ getParameterAs<std::size_t>(context.parameters, "size").value_or(10) };
|
||||
const std::size_t offset{ getParameterAs<std::size_t>(context.parameters, "offset").value_or(0) };
|
||||
const MediaLibraryId mediaLibraryId{ getParameterAs<MediaLibraryId>(context.getParameters(), "musicFolderId").value_or(MediaLibraryId{}) };
|
||||
const std::size_t size{ getParameterAs<std::size_t>(context.getParameters(), "size").value_or(10) };
|
||||
const std::size_t offset{ getParameterAs<std::size_t>(context.getParameters(), "offset").value_or(0) };
|
||||
if (size > defaultMaxCountSize)
|
||||
throw ParameterValueTooHighGenericError{ "size", defaultMaxCountSize };
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace lms::api::subsonic
|
||||
scrobbling::IScrobblingService& scrobblingService{ *core::Service<scrobbling::IScrobblingService>::get() };
|
||||
feedback::IFeedbackService& feedbackService{ *core::Service<feedback::IFeedbackService>::get() };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
if (type == "alphabeticalByName")
|
||||
{
|
||||
@@ -71,7 +71,7 @@ namespace lms::api::subsonic
|
||||
params.setRange(range);
|
||||
params.filters.setMediaLibrary(mediaLibraryId);
|
||||
|
||||
releases = Release::findIds(context.dbSession, params);
|
||||
releases = Release::findIds(context.getDbSession(), params);
|
||||
}
|
||||
else if (type == "alphabeticalByArtist")
|
||||
{
|
||||
@@ -80,14 +80,14 @@ namespace lms::api::subsonic
|
||||
params.setRange(range);
|
||||
params.filters.setMediaLibrary(mediaLibraryId);
|
||||
|
||||
releases = Release::findIds(context.dbSession, params);
|
||||
releases = Release::findIds(context.getDbSession(), params);
|
||||
}
|
||||
else if (type == "byGenre")
|
||||
{
|
||||
// Mandatory param
|
||||
const std::string genre{ getMandatoryParameterAs<std::string>(context.parameters, "genre") };
|
||||
const std::string genre{ getMandatoryParameterAs<std::string>(context.getParameters(), "genre") };
|
||||
|
||||
if (const ClusterType::pointer clusterType{ ClusterType::find(context.dbSession, "GENRE") })
|
||||
if (const ClusterType::pointer clusterType{ ClusterType::find(context.getDbSession(), "GENRE") })
|
||||
{
|
||||
if (const Cluster::pointer cluster{ clusterType->getCluster(genre) })
|
||||
{
|
||||
@@ -97,14 +97,14 @@ namespace lms::api::subsonic
|
||||
params.setSortMethod(ReleaseSortMethod::Name);
|
||||
params.setRange(range);
|
||||
|
||||
releases = Release::findIds(context.dbSession, params);
|
||||
releases = Release::findIds(context.getDbSession(), params);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == "byYear")
|
||||
{
|
||||
const int fromYear{ getMandatoryParameterAs<int>(context.parameters, "fromYear") };
|
||||
const int toYear{ getMandatoryParameterAs<int>(context.parameters, "toYear") };
|
||||
const int fromYear{ getMandatoryParameterAs<int>(context.getParameters(), "fromYear") };
|
||||
const int toYear{ getMandatoryParameterAs<int>(context.getParameters(), "toYear") };
|
||||
|
||||
Release::FindParameters params;
|
||||
params.setSortMethod(fromYear > toYear ? ReleaseSortMethod::DateDesc : ReleaseSortMethod::DateAsc);
|
||||
@@ -112,12 +112,12 @@ namespace lms::api::subsonic
|
||||
params.setDateRange(YearRange{ std::min(fromYear, toYear), std::max(fromYear, toYear) });
|
||||
params.filters.setMediaLibrary(mediaLibraryId);
|
||||
|
||||
releases = Release::findIds(context.dbSession, params);
|
||||
releases = Release::findIds(context.getDbSession(), params);
|
||||
}
|
||||
else if (type == "frequent")
|
||||
{
|
||||
scrobbling::IScrobblingService::FindParameters params;
|
||||
params.setUser(context.user->getId());
|
||||
params.setUser(context.getUser()->getId());
|
||||
params.setRange(range);
|
||||
params.filters.setMediaLibrary(mediaLibraryId);
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace lms::api::subsonic
|
||||
params.setRange(range);
|
||||
params.filters.setMediaLibrary(mediaLibraryId);
|
||||
|
||||
releases = Release::findIds(context.dbSession, params);
|
||||
releases = Release::findIds(context.getDbSession(), params);
|
||||
}
|
||||
else if (type == "random")
|
||||
{
|
||||
@@ -141,12 +141,12 @@ namespace lms::api::subsonic
|
||||
params.setRange(Range{ 0, size });
|
||||
params.filters.setMediaLibrary(mediaLibraryId);
|
||||
|
||||
releases = Release::findIds(context.dbSession, params);
|
||||
releases = Release::findIds(context.getDbSession(), params);
|
||||
}
|
||||
else if (type == "recent")
|
||||
{
|
||||
scrobbling::IScrobblingService::FindParameters params;
|
||||
params.setUser(context.user->getId());
|
||||
params.setUser(context.getUser()->getId());
|
||||
params.setRange(range);
|
||||
params.filters.setMediaLibrary(mediaLibraryId);
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace lms::api::subsonic
|
||||
else if (type == "starred")
|
||||
{
|
||||
feedback::IFeedbackService::FindParameters params;
|
||||
params.setUser(context.user->getId());
|
||||
params.setUser(context.getUser()->getId());
|
||||
params.setRange(range);
|
||||
params.filters.setMediaLibrary(mediaLibraryId);
|
||||
|
||||
@@ -166,12 +166,12 @@ namespace lms::api::subsonic
|
||||
throw NotImplementedGenericError{};
|
||||
}
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& albumListNode{ response.createNode(id3 ? Response::Node::Key{ "albumList2" } : Response::Node::Key{ "albumList" }) };
|
||||
|
||||
for (const ReleaseId releaseId : releases.results)
|
||||
{
|
||||
const Release::pointer release{ Release::find(context.dbSession, releaseId) };
|
||||
const Release::pointer release{ Release::find(context.getDbSession(), releaseId) };
|
||||
albumListNode.addArrayChild("album", createAlbumNode(context, release, id3));
|
||||
}
|
||||
|
||||
@@ -181,11 +181,11 @@ namespace lms::api::subsonic
|
||||
Response handleGetStarredRequestCommon(RequestContext& context, bool id3)
|
||||
{
|
||||
// Optional parameters
|
||||
const MediaLibraryId mediaLibrary{ getParameterAs<MediaLibraryId>(context.parameters, "musicFolderId").value_or(MediaLibraryId{}) };
|
||||
const MediaLibraryId mediaLibrary{ getParameterAs<MediaLibraryId>(context.getParameters(), "musicFolderId").value_or(MediaLibraryId{}) };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& starredNode{ response.createNode(id3 ? Response::Node::Key{ "starred2" } : Response::Node::Key{ "starred" }) };
|
||||
|
||||
feedback::IFeedbackService& feedbackService{ *core::Service<feedback::IFeedbackService>::get() };
|
||||
@@ -194,29 +194,29 @@ namespace lms::api::subsonic
|
||||
if (id3)
|
||||
{
|
||||
feedback::IFeedbackService::ArtistFindParameters artistFindParams;
|
||||
artistFindParams.setUser(context.user->getId());
|
||||
artistFindParams.setUser(context.getUser()->getId());
|
||||
artistFindParams.setSortMethod(ArtistSortMethod::SortName);
|
||||
for (const ArtistId artistId : feedbackService.findStarredArtists(artistFindParams).results)
|
||||
{
|
||||
if (auto artist{ Artist::find(context.dbSession, artistId) })
|
||||
if (auto artist{ Artist::find(context.getDbSession(), artistId) })
|
||||
starredNode.addArrayChild("artist", createArtistNode(context, artist));
|
||||
}
|
||||
}
|
||||
|
||||
feedback::IFeedbackService::FindParameters findParameters;
|
||||
findParameters.setUser(context.user->getId());
|
||||
findParameters.setUser(context.getUser()->getId());
|
||||
findParameters.filters.setMediaLibrary(mediaLibrary);
|
||||
|
||||
for (const ReleaseId releaseId : feedbackService.findStarredReleases(findParameters).results)
|
||||
{
|
||||
if (auto release{ Release::find(context.dbSession, releaseId) })
|
||||
if (auto release{ Release::find(context.getDbSession(), releaseId) })
|
||||
starredNode.addArrayChild("album", createAlbumNode(context, release, id3));
|
||||
}
|
||||
|
||||
for (const TrackId trackId : feedbackService.findStarredTracks(findParameters).results)
|
||||
{
|
||||
if (auto track{ Track::find(context.dbSession, trackId) })
|
||||
starredNode.addArrayChild("song", createSongNode(context, track, context.user));
|
||||
if (auto track{ Track::find(context.getDbSession(), trackId) })
|
||||
starredNode.addArrayChild("song", createSongNode(context, track, context.getUser()));
|
||||
}
|
||||
|
||||
return response;
|
||||
@@ -236,23 +236,23 @@ namespace lms::api::subsonic
|
||||
Response handleGetRandomSongsRequest(RequestContext& context)
|
||||
{
|
||||
// Optional params
|
||||
const MediaLibraryId mediaLibraryId{ getParameterAs<MediaLibraryId>(context.parameters, "musicFolderId").value_or(MediaLibraryId{}) };
|
||||
std::size_t size{ getParameterAs<std::size_t>(context.parameters, "size").value_or(50) };
|
||||
const MediaLibraryId mediaLibraryId{ getParameterAs<MediaLibraryId>(context.getParameters(), "musicFolderId").value_or(MediaLibraryId{}) };
|
||||
std::size_t size{ getParameterAs<std::size_t>(context.getParameters(), "size").value_or(50) };
|
||||
if (size > defaultMaxCountSize)
|
||||
throw ParameterValueTooHighGenericError{ "size", defaultMaxCountSize };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& randomSongsNode{ response.createNode("randomSongs") };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
Track::FindParameters params;
|
||||
params.setSortMethod(TrackSortMethod::Random);
|
||||
params.setRange(Range{ 0, size });
|
||||
params.filters.setMediaLibrary(mediaLibraryId);
|
||||
|
||||
Track::find(context.dbSession, params, [&](const Track::pointer& track) {
|
||||
randomSongsNode.addArrayChild("song", createSongNode(context, track, context.user));
|
||||
Track::find(context.getDbSession(), params, [&](const Track::pointer& track) {
|
||||
randomSongsNode.addArrayChild("song", createSongNode(context, track, context.getUser()));
|
||||
});
|
||||
|
||||
return response;
|
||||
@@ -261,19 +261,19 @@ namespace lms::api::subsonic
|
||||
Response handleGetSongsByGenreRequest(RequestContext& context)
|
||||
{
|
||||
// Mandatory params
|
||||
std::string genre{ getMandatoryParameterAs<std::string>(context.parameters, "genre") };
|
||||
std::string genre{ getMandatoryParameterAs<std::string>(context.getParameters(), "genre") };
|
||||
|
||||
// Optional params
|
||||
const MediaLibraryId mediaLibrary{ getParameterAs<MediaLibraryId>(context.parameters, "musicFolderId").value_or(MediaLibraryId{}) };
|
||||
std::size_t count{ getParameterAs<std::size_t>(context.parameters, "count").value_or(10) };
|
||||
const MediaLibraryId mediaLibrary{ getParameterAs<MediaLibraryId>(context.getParameters(), "musicFolderId").value_or(MediaLibraryId{}) };
|
||||
std::size_t count{ getParameterAs<std::size_t>(context.getParameters(), "count").value_or(10) };
|
||||
if (count > defaultMaxCountSize)
|
||||
throw ParameterValueTooHighGenericError{ "count", defaultMaxCountSize };
|
||||
|
||||
std::size_t offset{ getParameterAs<std::size_t>(context.parameters, "offset").value_or(0) };
|
||||
std::size_t offset{ getParameterAs<std::size_t>(context.getParameters(), "offset").value_or(0) };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
auto clusterType{ ClusterType::find(context.dbSession, "GENRE") };
|
||||
auto clusterType{ ClusterType::find(context.getDbSession(), "GENRE") };
|
||||
if (!clusterType)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
@@ -281,7 +281,7 @@ namespace lms::api::subsonic
|
||||
if (!cluster)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& songsByGenreNode{ response.createNode("songsByGenre") };
|
||||
|
||||
Track::FindParameters params;
|
||||
@@ -289,8 +289,8 @@ namespace lms::api::subsonic
|
||||
params.filters.setMediaLibrary(mediaLibrary);
|
||||
params.setRange(Range{ offset, count });
|
||||
|
||||
Track::find(context.dbSession, params, [&](const Track::pointer& track) {
|
||||
songsByGenreNode.addArrayChild("song", createSongNode(context, track, context.user));
|
||||
Track::find(context.getDbSession(), params, [&](const Track::pointer& track) {
|
||||
songsByGenreNode.addArrayChild("song", createSongNode(context, track, context.getUser()));
|
||||
});
|
||||
|
||||
return response;
|
||||
|
||||
@@ -38,18 +38,18 @@ namespace lms::api::subsonic
|
||||
|
||||
Response handleGetBookmarks(RequestContext& context)
|
||||
{
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
const auto bookmarkIds{ TrackBookmark::find(context.dbSession, context.user->getId()) };
|
||||
const auto bookmarkIds{ TrackBookmark::find(context.getDbSession(), context.getUser()->getId()) };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& bookmarksNode{ response.createNode("bookmarks") };
|
||||
|
||||
for (const TrackBookmarkId bookmarkId : bookmarkIds.results)
|
||||
{
|
||||
const TrackBookmark::pointer bookmark{ TrackBookmark::find(context.dbSession, bookmarkId) };
|
||||
const TrackBookmark::pointer bookmark{ TrackBookmark::find(context.getDbSession(), bookmarkId) };
|
||||
Response::Node bookmarkNode{ createBookmarkNode(bookmark) };
|
||||
bookmarkNode.addChild("entry", createSongNode(context, bookmark->getTrack(), context.user));
|
||||
bookmarkNode.addChild("entry", createSongNode(context, bookmark->getTrack(), context.getUser()));
|
||||
bookmarksNode.addArrayChild("bookmark", std::move(bookmarkNode));
|
||||
}
|
||||
|
||||
@@ -59,51 +59,51 @@ namespace lms::api::subsonic
|
||||
Response handleCreateBookmark(RequestContext& context)
|
||||
{
|
||||
// Mandatory params
|
||||
TrackId trackId{ getMandatoryParameterAs<TrackId>(context.parameters, "id") };
|
||||
unsigned long position{ getMandatoryParameterAs<unsigned long>(context.parameters, "position") };
|
||||
const std::optional<std::string> comment{ getParameterAs<std::string>(context.parameters, "comment") };
|
||||
TrackId trackId{ getMandatoryParameterAs<TrackId>(context.getParameters(), "id") };
|
||||
unsigned long position{ getMandatoryParameterAs<unsigned long>(context.getParameters(), "position") };
|
||||
const std::optional<std::string> comment{ getParameterAs<std::string>(context.getParameters(), "comment") };
|
||||
|
||||
auto transaction{ context.dbSession.createWriteTransaction() };
|
||||
auto transaction{ context.getDbSession().createWriteTransaction() };
|
||||
|
||||
const Track::pointer track{ Track::find(context.dbSession, trackId) };
|
||||
const Track::pointer track{ Track::find(context.getDbSession(), trackId) };
|
||||
if (!track)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
// Replace any existing bookmark
|
||||
auto bookmark{ TrackBookmark::find(context.dbSession, context.user->getId(), trackId) };
|
||||
auto bookmark{ TrackBookmark::find(context.getDbSession(), context.getUser()->getId(), trackId) };
|
||||
if (!bookmark)
|
||||
bookmark = context.dbSession.create<TrackBookmark>(context.user, track);
|
||||
bookmark = context.getDbSession().create<TrackBookmark>(context.getUser(), track);
|
||||
|
||||
bookmark.modify()->setOffset(std::chrono::milliseconds{ position });
|
||||
if (comment)
|
||||
bookmark.modify()->setComment(*comment);
|
||||
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
|
||||
Response handleDeleteBookmark(RequestContext& context)
|
||||
{
|
||||
// Mandatory params
|
||||
TrackId trackId{ getMandatoryParameterAs<TrackId>(context.parameters, "id") };
|
||||
TrackId trackId{ getMandatoryParameterAs<TrackId>(context.getParameters(), "id") };
|
||||
|
||||
auto transaction{ context.dbSession.createWriteTransaction() };
|
||||
auto transaction{ context.getDbSession().createWriteTransaction() };
|
||||
|
||||
auto bookmark{ TrackBookmark::find(context.dbSession, context.user->getId(), trackId) };
|
||||
auto bookmark{ TrackBookmark::find(context.getDbSession(), context.getUser()->getId(), trackId) };
|
||||
if (!bookmark)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
bookmark.remove();
|
||||
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
|
||||
// Use a dedicated internal playlist
|
||||
Response handleGetPlayQueue(RequestContext& context)
|
||||
{
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
const db::PlayQueue::pointer playQueue{ db::PlayQueue::find(context.dbSession, context.user->getId(), "subsonic") };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
const db::PlayQueue::pointer playQueue{ db::PlayQueue::find(context.getDbSession(), context.getUser()->getId(), "subsonic") };
|
||||
if (playQueue)
|
||||
{
|
||||
Response::Node& playQueueNode{ response.createNode("playQueue") };
|
||||
@@ -115,7 +115,7 @@ namespace lms::api::subsonic
|
||||
}
|
||||
|
||||
// mandatory fields
|
||||
playQueueNode.setAttribute("username", context.user->getLoginName());
|
||||
playQueueNode.setAttribute("username", context.getUser()->getLoginName());
|
||||
playQueueNode.setAttribute("changed", core::stringUtils::toISO8601String(playQueue->getLastModifiedDateTime()));
|
||||
playQueueNode.setAttribute("changedBy", "unknown"); // we don't store the client name (could be several same clients on several devices...)
|
||||
|
||||
@@ -130,9 +130,9 @@ namespace lms::api::subsonic
|
||||
Response handleSavePlayQueue(RequestContext& context)
|
||||
{
|
||||
// optional params
|
||||
std::vector<db::TrackId> trackIds{ getMultiParametersAs<TrackId>(context.parameters, "id") };
|
||||
const std::optional<db::TrackId> currentTrackId{ getParameterAs<db::TrackId>(context.parameters, "current") };
|
||||
const std::chrono::milliseconds currentPositionInTrack{ getParameterAs<std::size_t>(context.parameters, "current").value_or(0) };
|
||||
std::vector<db::TrackId> trackIds{ getMultiParametersAs<TrackId>(context.getParameters(), "id") };
|
||||
const std::optional<db::TrackId> currentTrackId{ getParameterAs<db::TrackId>(context.getParameters(), "current") };
|
||||
const std::chrono::milliseconds currentPositionInTrack{ getParameterAs<std::size_t>(context.getParameters(), "current").value_or(0) };
|
||||
|
||||
std::vector<db::Track::pointer> tracks;
|
||||
tracks.reserve(trackIds.size());
|
||||
@@ -140,20 +140,20 @@ namespace lms::api::subsonic
|
||||
// no id means we clear the play queue (see https://github.com/opensubsonic/open-subsonic-api/pull/106)
|
||||
if (!trackIds.empty())
|
||||
{
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
for (db::TrackId trackId : trackIds)
|
||||
{
|
||||
if (db::Track::pointer track{ db::Track::find(context.dbSession, trackId) })
|
||||
if (db::Track::pointer track{ db::Track::find(context.getDbSession(), trackId) })
|
||||
tracks.push_back(track);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto transaction{ context.dbSession.createWriteTransaction() };
|
||||
auto transaction{ context.getDbSession().createWriteTransaction() };
|
||||
|
||||
db::PlayQueue::pointer playQueue{ db::PlayQueue::find(context.dbSession, context.user->getId(), "subsonic") };
|
||||
db::PlayQueue::pointer playQueue{ db::PlayQueue::find(context.getDbSession(), context.getUser()->getId(), "subsonic") };
|
||||
if (!playQueue)
|
||||
playQueue = context.dbSession.create<db::PlayQueue>(context.user, "subsonic");
|
||||
playQueue = context.getDbSession().create<db::PlayQueue>(context.getUser(), "subsonic");
|
||||
|
||||
playQueue.modify()->clear();
|
||||
std::size_t index{};
|
||||
@@ -171,6 +171,6 @@ namespace lms::api::subsonic
|
||||
playQueue.modify()->setLastModifiedDateTime(Wt::WDateTime::currentDateTime());
|
||||
}
|
||||
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
} // namespace lms::api::subsonic
|
||||
@@ -91,7 +91,7 @@ namespace lms::api::subsonic
|
||||
params.setParentDirectory(parentDirectory->getId());
|
||||
params.setSortMethod(DirectorySortMethod::Name);
|
||||
|
||||
Directory::find(context.dbSession, params, [&](const Directory::pointer& directory) {
|
||||
Directory::find(context.getDbSession(), params, [&](const Directory::pointer& directory) {
|
||||
const std::string_view name{ directory->getName() };
|
||||
assert(!name.empty());
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace lms::api::subsonic
|
||||
|
||||
const std::size_t meanTrackCountPerArtist{ (count / artistIds.size()) + 1 };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
std::vector<TrackId> tracks;
|
||||
tracks.reserve(count);
|
||||
@@ -126,7 +126,7 @@ namespace lms::api::subsonic
|
||||
params.setRange(Range{ 0, meanTrackCountPerArtist });
|
||||
params.setSortMethod(TrackSortMethod::Random);
|
||||
|
||||
const auto artistTracks{ Track::findIds(context.dbSession, params) };
|
||||
const auto artistTracks{ Track::findIds(context.getDbSession(), params) };
|
||||
tracks.insert(std::end(tracks),
|
||||
std::begin(artistTracks.results),
|
||||
std::end(artistTracks.results));
|
||||
@@ -145,7 +145,7 @@ namespace lms::api::subsonic
|
||||
|
||||
const std::size_t meanTrackCountPerRelease{ (count / releaseIds.size()) + 1 };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
std::vector<TrackId> tracks;
|
||||
tracks.reserve(count);
|
||||
@@ -157,7 +157,7 @@ namespace lms::api::subsonic
|
||||
params.setRange(Range{ 0, meanTrackCountPerRelease });
|
||||
params.setSortMethod(TrackSortMethod::Random);
|
||||
|
||||
const auto releaseTracks{ Track::findIds(context.dbSession, params) };
|
||||
const auto releaseTracks{ Track::findIds(context.getDbSession(), params) };
|
||||
tracks.insert(std::end(tracks),
|
||||
std::begin(releaseTracks.results),
|
||||
std::end(releaseTracks.results));
|
||||
@@ -174,31 +174,31 @@ namespace lms::api::subsonic
|
||||
Response handleGetSimilarSongsRequestCommon(RequestContext& context, bool id3)
|
||||
{
|
||||
// Optional params
|
||||
std::size_t count{ getParameterAs<std::size_t>(context.parameters, "count").value_or(50) };
|
||||
std::size_t count{ getParameterAs<std::size_t>(context.getParameters(), "count").value_or(50) };
|
||||
if (count > defaultMaxCountSize)
|
||||
throw ParameterValueTooHighGenericError{ "count", defaultMaxCountSize };
|
||||
|
||||
std::vector<TrackId> tracks;
|
||||
|
||||
if (const auto artistId{ getParameterAs<ArtistId>(context.parameters, "id") })
|
||||
if (const auto artistId{ getParameterAs<ArtistId>(context.getParameters(), "id") })
|
||||
tracks = findSimilarSongs(context, *artistId, count);
|
||||
else if (const auto releaseId{ getParameterAs<ReleaseId>(context.parameters, "id") })
|
||||
else if (const auto releaseId{ getParameterAs<ReleaseId>(context.getParameters(), "id") })
|
||||
tracks = findSimilarSongs(context, *releaseId, count);
|
||||
else if (const auto trackId{ getParameterAs<TrackId>(context.parameters, "id") })
|
||||
else if (const auto trackId{ getParameterAs<TrackId>(context.getParameters(), "id") })
|
||||
tracks = findSimilarSongs(context, *trackId, count);
|
||||
else
|
||||
throw BadParameterGenericError{ "id" };
|
||||
|
||||
core::random::shuffleContainer(tracks);
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& similarSongsNode{ response.createNode(id3 ? Response::Node::Key{ "similarSongs2" } : Response::Node::Key{ "similarSongs" }) };
|
||||
for (const TrackId trackId : tracks)
|
||||
{
|
||||
const Track::pointer track{ Track::find(context.dbSession, trackId) };
|
||||
similarSongsNode.addArrayChild("song", createSongNode(context, track, context.user));
|
||||
const Track::pointer track{ Track::find(context.getDbSession(), trackId) };
|
||||
similarSongsNode.addArrayChild("song", createSongNode(context, track, context.getUser()));
|
||||
}
|
||||
|
||||
return response;
|
||||
@@ -223,11 +223,11 @@ namespace lms::api::subsonic
|
||||
|
||||
Response handleGetMusicFoldersRequest(RequestContext& context)
|
||||
{
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& musicFoldersNode{ response.createNode("musicFolders") };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
MediaLibrary::find(context.dbSession, [&](const MediaLibrary::pointer& library) {
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
MediaLibrary::find(context.getDbSession(), [&](const MediaLibrary::pointer& library) {
|
||||
Response::Node& musicFolderNode{ musicFoldersNode.createArrayChild("musicFolder") };
|
||||
|
||||
musicFolderNode.setAttribute("id", library->getId().getValue());
|
||||
@@ -240,16 +240,16 @@ namespace lms::api::subsonic
|
||||
Response handleGetIndexesRequest(RequestContext& context)
|
||||
{
|
||||
// Optional params
|
||||
const MediaLibraryId mediaLibrary{ getParameterAs<MediaLibraryId>(context.parameters, "musicFolderId").value_or(MediaLibraryId{}) };
|
||||
const MediaLibraryId mediaLibrary{ getParameterAs<MediaLibraryId>(context.getParameters(), "musicFolderId").value_or(MediaLibraryId{}) };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& indexesNode{ response.createNode("indexes") };
|
||||
indexesNode.setAttribute("ignoredArticles", "");
|
||||
indexesNode.setAttribute("lastModified", reportedDummyDateULong); // TODO report last file write?
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
const std::vector<Directory::pointer> rootDirectories{ getRootDirectories(context.dbSession, mediaLibrary) };
|
||||
const std::vector<Directory::pointer> rootDirectories{ getRootDirectories(context.getDbSession(), mediaLibrary) };
|
||||
|
||||
IndexMap indexedDirectories;
|
||||
for (const Directory::pointer& rootdirectory : rootDirectories)
|
||||
@@ -257,8 +257,8 @@ namespace lms::api::subsonic
|
||||
Track::FindParameters params;
|
||||
params.setDirectory(rootdirectory->getId());
|
||||
|
||||
Track::find(context.dbSession, params, [&](const Track::pointer& track) {
|
||||
indexesNode.addArrayChild("child", createSongNode(context, track, context.user));
|
||||
Track::find(context.getDbSession(), params, [&](const Track::pointer& track) {
|
||||
indexesNode.addArrayChild("child", createSongNode(context, track, context.getUser()));
|
||||
});
|
||||
|
||||
getIndexedChildDirectories(context, rootdirectory, indexedDirectories);
|
||||
@@ -287,21 +287,21 @@ namespace lms::api::subsonic
|
||||
Response handleGetMusicDirectoryRequest(RequestContext& context)
|
||||
{
|
||||
// Mandatory params
|
||||
const auto directoryId{ getMandatoryParameterAs<DirectoryId>(context.parameters, "id") };
|
||||
const auto directoryId{ getMandatoryParameterAs<DirectoryId>(context.getParameters(), "id") };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& directoryNode{ response.createNode("directory") };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
const Directory::pointer directory{ Directory::find(context.dbSession, directoryId) };
|
||||
const Directory::pointer directory{ Directory::find(context.getDbSession(), directoryId) };
|
||||
if (!directory)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
if (const Release::pointer release{ getReleaseFromDirectory(context.dbSession, directoryId) })
|
||||
if (const Release::pointer release{ getReleaseFromDirectory(context.getDbSession(), directoryId) })
|
||||
{
|
||||
directoryNode.setAttribute("playCount", core::Service<scrobbling::IScrobblingService>::get()->getCount(context.user->getId(), release->getId()));
|
||||
if (const Wt::WDateTime dateTime{ core::Service<feedback::IFeedbackService>::get()->getStarredDateTime(context.user->getId(), release->getId()) }; dateTime.isValid())
|
||||
directoryNode.setAttribute("playCount", core::Service<scrobbling::IScrobblingService>::get()->getCount(context.getUser()->getId(), release->getId()));
|
||||
if (const Wt::WDateTime dateTime{ core::Service<feedback::IFeedbackService>::get()->getStarredDateTime(context.getUser()->getId(), release->getId()) }; dateTime.isValid())
|
||||
directoryNode.setAttribute("starred", core::stringUtils::toISO8601String(dateTime));
|
||||
}
|
||||
|
||||
@@ -317,8 +317,8 @@ namespace lms::api::subsonic
|
||||
params.setParentDirectory(directory->getId());
|
||||
params.setSortMethod(DirectorySortMethod::Name);
|
||||
|
||||
Directory::find(context.dbSession, params, [&](const Directory::pointer& subDirectory) {
|
||||
const Release::pointer release{ getReleaseFromDirectory(context.dbSession, subDirectory->getId()) };
|
||||
Directory::find(context.getDbSession(), params, [&](const Directory::pointer& subDirectory) {
|
||||
const Release::pointer release{ getReleaseFromDirectory(context.getDbSession(), subDirectory->getId()) };
|
||||
|
||||
if (release)
|
||||
{
|
||||
@@ -343,8 +343,8 @@ namespace lms::api::subsonic
|
||||
params.setDirectory(directory->getId());
|
||||
params.setSortMethod(TrackSortMethod::AbsoluteFilePath);
|
||||
|
||||
Track::find(context.dbSession, params, [&](const Track::pointer& track) {
|
||||
directoryNode.addArrayChild("child", createSongNode(context, track, context.user));
|
||||
Track::find(context.getDbSession(), params, [&](const Track::pointer& track) {
|
||||
directoryNode.addArrayChild("child", createSongNode(context, track, context.getUser()));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -353,13 +353,13 @@ namespace lms::api::subsonic
|
||||
|
||||
Response handleGetGenresRequest(RequestContext& context)
|
||||
{
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
|
||||
Response::Node& genresNode{ response.createNode("genres") };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
const ClusterType::pointer clusterType{ ClusterType::find(context.dbSession, "GENRE") };
|
||||
const ClusterType::pointer clusterType{ ClusterType::find(context.getDbSession(), "GENRE") };
|
||||
if (clusterType)
|
||||
{
|
||||
const auto clusters{ clusterType->getClusters() };
|
||||
@@ -374,9 +374,9 @@ namespace lms::api::subsonic
|
||||
Response handleGetArtistsRequest(RequestContext& context)
|
||||
{
|
||||
// Optional params
|
||||
const MediaLibraryId mediaLibrary{ getParameterAs<MediaLibraryId>(context.parameters, "musicFolderId").value_or(MediaLibraryId{}) };
|
||||
const MediaLibraryId mediaLibrary{ getParameterAs<MediaLibraryId>(context.getParameters(), "musicFolderId").value_or(MediaLibraryId{}) };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
|
||||
Response::Node& artistsNode{ response.createNode("artists") };
|
||||
artistsNode.setAttribute("ignoredArticles", "");
|
||||
@@ -384,10 +384,10 @@ namespace lms::api::subsonic
|
||||
|
||||
Artist::FindParameters parameters;
|
||||
{
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
parameters.setSortMethod(ArtistSortMethod::SortName);
|
||||
switch (context.user->getSubsonicArtistListMode())
|
||||
switch (context.getUser()->getSubsonicArtistListMode())
|
||||
{
|
||||
case SubsonicArtistListMode::AllArtists:
|
||||
break;
|
||||
@@ -411,10 +411,10 @@ namespace lms::api::subsonic
|
||||
bool hasMoreArtists{ true };
|
||||
while (hasMoreArtists)
|
||||
{
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
parameters.setRange(Range{ currentArtistOffset, batchSize });
|
||||
const auto artists{ Artist::find(context.dbSession, parameters) };
|
||||
const auto artists{ Artist::find(context.getDbSession(), parameters) };
|
||||
for (const Artist::pointer& artist : artists.results)
|
||||
{
|
||||
std::string_view sortName{ artist->getSortName() };
|
||||
@@ -441,9 +441,9 @@ namespace lms::api::subsonic
|
||||
|
||||
for (const ArtistId artistId : artistIds)
|
||||
{
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
if (const Artist::pointer artist{ Artist::find(context.dbSession, artistId) })
|
||||
if (const Artist::pointer artist{ Artist::find(context.getDbSession(), artistId) })
|
||||
indexNode.addArrayChild("artist", createArtistNode(context, artist));
|
||||
}
|
||||
}
|
||||
@@ -454,18 +454,18 @@ namespace lms::api::subsonic
|
||||
Response handleGetArtistRequest(RequestContext& context)
|
||||
{
|
||||
// Mandatory params
|
||||
ArtistId id{ getMandatoryParameterAs<ArtistId>(context.parameters, "id") };
|
||||
ArtistId id{ getMandatoryParameterAs<ArtistId>(context.getParameters(), "id") };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
const Artist::pointer artist{ Artist::find(context.dbSession, id) };
|
||||
const Artist::pointer artist{ Artist::find(context.getDbSession(), id) };
|
||||
if (!artist)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node artistNode{ createArtistNode(context, artist) };
|
||||
|
||||
const auto releases{ Release::find(context.dbSession, Release::FindParameters{}.setArtist(artist->getId())) };
|
||||
const auto releases{ Release::find(context.getDbSession(), Release::FindParameters{}.setArtist(artist->getId())) };
|
||||
for (const Release::pointer& release : releases.results)
|
||||
artistNode.addArrayChild("album", createAlbumNode(context, release, true /* id3 */));
|
||||
|
||||
@@ -477,18 +477,18 @@ namespace lms::api::subsonic
|
||||
Response handleGetAlbumRequest(RequestContext& context)
|
||||
{
|
||||
// Mandatory params
|
||||
ReleaseId id{ getMandatoryParameterAs<ReleaseId>(context.parameters, "id") };
|
||||
ReleaseId id{ getMandatoryParameterAs<ReleaseId>(context.getParameters(), "id") };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
Release::pointer release{ Release::find(context.dbSession, id) };
|
||||
Release::pointer release{ Release::find(context.getDbSession(), id) };
|
||||
if (!release)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node albumNode{ createAlbumNode(context, release, true /* id3 */) };
|
||||
|
||||
const auto tracks{ Track::find(context.dbSession, Track::FindParameters{}.setRelease(id).setSortMethod(TrackSortMethod::Release)) };
|
||||
const auto tracks{ Track::find(context.getDbSession(), Track::FindParameters{}.setRelease(id).setSortMethod(TrackSortMethod::Release)) };
|
||||
for (const Track::pointer& track : tracks.results)
|
||||
albumNode.addArrayChild("song", createSongNode(context, track, true /* id3 */));
|
||||
|
||||
@@ -500,16 +500,16 @@ namespace lms::api::subsonic
|
||||
Response handleGetSongRequest(RequestContext& context)
|
||||
{
|
||||
// Mandatory params
|
||||
TrackId id{ getMandatoryParameterAs<TrackId>(context.parameters, "id") };
|
||||
TrackId id{ getMandatoryParameterAs<TrackId>(context.getParameters(), "id") };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
const Track::pointer track{ Track::find(context.dbSession, id) };
|
||||
const Track::pointer track{ Track::find(context.getDbSession(), id) };
|
||||
if (!track)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
response.addNode("song", createSongNode(context, track, context.user));
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
response.addNode("song", createSongNode(context, track, context.getUser()));
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -517,24 +517,24 @@ namespace lms::api::subsonic
|
||||
Response handleGetArtistInfo2Request(RequestContext& context)
|
||||
{
|
||||
// Mandatory params
|
||||
ArtistId id{ getMandatoryParameterAs<ArtistId>(context.parameters, "id") };
|
||||
ArtistId id{ getMandatoryParameterAs<ArtistId>(context.getParameters(), "id") };
|
||||
|
||||
// Optional params
|
||||
std::size_t count{ getParameterAs<std::size_t>(context.parameters, "count").value_or(20) };
|
||||
std::size_t count{ getParameterAs<std::size_t>(context.getParameters(), "count").value_or(20) };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& artistInfoNode{ response.createNode(Response::Node::Key{ "artistInfo2" }) };
|
||||
|
||||
{
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
const Artist::pointer artist{ Artist::find(context.dbSession, id) };
|
||||
const Artist::pointer artist{ Artist::find(context.getDbSession(), id) };
|
||||
if (!artist)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
if (const std::optional<core::UUID> artistMBID{ artist->getMBID() })
|
||||
{
|
||||
switch (context.responseFormat)
|
||||
switch (context.getResponseFormat())
|
||||
{
|
||||
case ResponseFormat::json:
|
||||
artistInfoNode.setAttribute("musicBrainzId", artistMBID->getAsString());
|
||||
@@ -545,10 +545,10 @@ namespace lms::api::subsonic
|
||||
}
|
||||
}
|
||||
|
||||
ArtistInfo::find(context.dbSession, id, Range{ .offset = 0, .size = 1 }, [&](const ArtistInfo::pointer& artistInfo) {
|
||||
ArtistInfo::find(context.getDbSession(), id, Range{ .offset = 0, .size = 1 }, [&](const ArtistInfo::pointer& artistInfo) {
|
||||
if (!artistInfo->getBiography().empty())
|
||||
{
|
||||
switch (context.responseFormat)
|
||||
switch (context.getResponseFormat())
|
||||
{
|
||||
case ResponseFormat::json:
|
||||
artistInfoNode.setAttribute("biography", artistInfo->getBiography());
|
||||
@@ -564,11 +564,11 @@ namespace lms::api::subsonic
|
||||
auto similarArtistsId{ core::Service<recommendation::IRecommendationService>::get()->getSimilarArtists(id, { TrackArtistLinkType::Artist, TrackArtistLinkType::ReleaseArtist }, count) };
|
||||
|
||||
{
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
for (const ArtistId similarArtistId : similarArtistsId)
|
||||
{
|
||||
const Artist::pointer similarArtist{ Artist::find(context.dbSession, similarArtistId) };
|
||||
const Artist::pointer similarArtist{ Artist::find(context.getDbSession(), similarArtistId) };
|
||||
if (similarArtist)
|
||||
artistInfoNode.addArrayChild("similarArtist", createArtistNode(context, similarArtist));
|
||||
}
|
||||
@@ -579,14 +579,14 @@ namespace lms::api::subsonic
|
||||
|
||||
Response handleGetAlbumInfo(RequestContext& context)
|
||||
{
|
||||
const db::DirectoryId directoryId{ getMandatoryParameterAs<db::DirectoryId>(context.parameters, "id") };
|
||||
const db::DirectoryId directoryId{ getMandatoryParameterAs<db::DirectoryId>(context.getParameters(), "id") };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
|
||||
{
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
if (db::Release::pointer release{ getReleaseFromDirectory(context.dbSession, directoryId) })
|
||||
if (db::Release::pointer release{ getReleaseFromDirectory(context.getDbSession(), directoryId) })
|
||||
response.addNode("albumInfo", createAlbumInfoNode(context, release));
|
||||
}
|
||||
return response;
|
||||
@@ -594,14 +594,14 @@ namespace lms::api::subsonic
|
||||
|
||||
Response handleGetAlbumInfo2(RequestContext& context)
|
||||
{
|
||||
const db::ReleaseId releaseId{ getMandatoryParameterAs<db::ReleaseId>(context.parameters, "id") };
|
||||
const db::ReleaseId releaseId{ getMandatoryParameterAs<db::ReleaseId>(context.getParameters(), "id") };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
|
||||
{
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
if (db::Release::pointer release{ db::Release::find(context.dbSession, releaseId) })
|
||||
if (db::Release::pointer release{ db::Release::find(context.getDbSession(), releaseId) })
|
||||
response.addNode("albumInfo", createAlbumInfoNode(context, release));
|
||||
}
|
||||
|
||||
@@ -621,29 +621,29 @@ namespace lms::api::subsonic
|
||||
Response handleGetTopSongs(RequestContext& context)
|
||||
{
|
||||
// Mandatory params
|
||||
std::string_view artistName{ getMandatoryParameterAs<std::string_view>(context.parameters, "artist") };
|
||||
std::size_t count{ getParameterAs<std::size_t>(context.parameters, "count").value_or(50) };
|
||||
std::string_view artistName{ getMandatoryParameterAs<std::string_view>(context.getParameters(), "artist") };
|
||||
std::size_t count{ getParameterAs<std::size_t>(context.getParameters(), "count").value_or(50) };
|
||||
if (count > defaultMaxCountSize)
|
||||
throw ParameterValueTooHighGenericError{ "count", defaultMaxCountSize };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& topSongs{ response.createNode("topSongs") };
|
||||
|
||||
const auto artists{ Artist::find(context.dbSession, artistName) };
|
||||
const auto artists{ Artist::find(context.getDbSession(), artistName) };
|
||||
if (artists.size() == 1)
|
||||
{
|
||||
scrobbling::IScrobblingService::FindParameters params;
|
||||
params.setUser(context.user->getId());
|
||||
params.setUser(context.getUser()->getId());
|
||||
params.setRange(db::Range{ 0, count });
|
||||
params.setArtist(artists.front()->getId());
|
||||
|
||||
const auto trackIds{ core::Service<scrobbling::IScrobblingService>::get()->getTopTracks(params) };
|
||||
for (const TrackId trackId : trackIds.results)
|
||||
{
|
||||
if (Track::pointer track{ Track::find(context.dbSession, trackId) })
|
||||
topSongs.addArrayChild("song", createSongNode(context, track, context.user));
|
||||
if (Track::pointer track{ Track::find(context.getDbSession(), trackId) })
|
||||
topSongs.addArrayChild("song", createSongNode(context, track, context.getUser()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -113,72 +113,72 @@ namespace lms::api::subsonic
|
||||
|
||||
Response handleStarRequest(RequestContext& context)
|
||||
{
|
||||
StarParameters params{ getStarParameters(context.parameters) };
|
||||
StarParameters params{ getStarParameters(context.getParameters()) };
|
||||
|
||||
for (const DirectoryId id : params.directoryIds)
|
||||
{
|
||||
if (const ReleaseId releaseId{ getReleaseIdFromDirectory(context.dbSession, id) }; releaseId.isValid())
|
||||
core::Service<feedback::IFeedbackService>::get()->star(context.user->getId(), releaseId);
|
||||
if (const ReleaseId releaseId{ getReleaseIdFromDirectory(context.getDbSession(), id) }; releaseId.isValid())
|
||||
core::Service<feedback::IFeedbackService>::get()->star(context.getUser()->getId(), releaseId);
|
||||
}
|
||||
|
||||
for (const ArtistId id : params.artistIds)
|
||||
core::Service<feedback::IFeedbackService>::get()->star(context.user->getId(), id);
|
||||
core::Service<feedback::IFeedbackService>::get()->star(context.getUser()->getId(), id);
|
||||
|
||||
for (const ReleaseId id : params.releaseIds)
|
||||
core::Service<feedback::IFeedbackService>::get()->star(context.user->getId(), id);
|
||||
core::Service<feedback::IFeedbackService>::get()->star(context.getUser()->getId(), id);
|
||||
|
||||
for (const TrackId id : params.trackIds)
|
||||
core::Service<feedback::IFeedbackService>::get()->star(context.user->getId(), id);
|
||||
core::Service<feedback::IFeedbackService>::get()->star(context.getUser()->getId(), id);
|
||||
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
|
||||
Response handleUnstarRequest(RequestContext& context)
|
||||
{
|
||||
const StarParameters params{ getStarParameters(context.parameters) };
|
||||
const StarParameters params{ getStarParameters(context.getParameters()) };
|
||||
|
||||
for (const DirectoryId id : params.directoryIds)
|
||||
{
|
||||
if (const ReleaseId releaseId{ getReleaseIdFromDirectory(context.dbSession, id) }; releaseId.isValid())
|
||||
core::Service<feedback::IFeedbackService>::get()->unstar(context.user->getId(), releaseId);
|
||||
if (const ReleaseId releaseId{ getReleaseIdFromDirectory(context.getDbSession(), id) }; releaseId.isValid())
|
||||
core::Service<feedback::IFeedbackService>::get()->unstar(context.getUser()->getId(), releaseId);
|
||||
}
|
||||
|
||||
for (const ArtistId id : params.artistIds)
|
||||
core::Service<feedback::IFeedbackService>::get()->unstar(context.user->getId(), id);
|
||||
core::Service<feedback::IFeedbackService>::get()->unstar(context.getUser()->getId(), id);
|
||||
|
||||
for (const ReleaseId id : params.releaseIds)
|
||||
core::Service<feedback::IFeedbackService>::get()->unstar(context.user->getId(), id);
|
||||
core::Service<feedback::IFeedbackService>::get()->unstar(context.getUser()->getId(), id);
|
||||
|
||||
for (const TrackId id : params.trackIds)
|
||||
core::Service<feedback::IFeedbackService>::get()->unstar(context.user->getId(), id);
|
||||
core::Service<feedback::IFeedbackService>::get()->unstar(context.getUser()->getId(), id);
|
||||
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
|
||||
Response handleSetRating(RequestContext& context)
|
||||
{
|
||||
const RatingParameters params{ getRatingParameters(context.parameters) };
|
||||
const RatingParameters params{ getRatingParameters(context.getParameters()) };
|
||||
|
||||
if (const ArtistId * artistId{ std::get_if<ArtistId>(¶ms.id) })
|
||||
core::Service<feedback::IFeedbackService>::get()->setRating(context.user->getId(), *artistId, params.rating);
|
||||
core::Service<feedback::IFeedbackService>::get()->setRating(context.getUser()->getId(), *artistId, params.rating);
|
||||
else if (const DirectoryId * directoryId{ std::get_if<DirectoryId>(¶ms.id) })
|
||||
{
|
||||
if (const ReleaseId releaseId{ getReleaseIdFromDirectory(context.dbSession, *directoryId) }; releaseId.isValid())
|
||||
core::Service<feedback::IFeedbackService>::get()->setRating(context.user->getId(), releaseId, params.rating);
|
||||
if (const ReleaseId releaseId{ getReleaseIdFromDirectory(context.getDbSession(), *directoryId) }; releaseId.isValid())
|
||||
core::Service<feedback::IFeedbackService>::get()->setRating(context.getUser()->getId(), releaseId, params.rating);
|
||||
}
|
||||
else if (const ReleaseId * releaseId{ std::get_if<ReleaseId>(¶ms.id) })
|
||||
core::Service<feedback::IFeedbackService>::get()->setRating(context.user->getId(), *releaseId, params.rating);
|
||||
core::Service<feedback::IFeedbackService>::get()->setRating(context.getUser()->getId(), *releaseId, params.rating);
|
||||
else if (const TrackId * trackId{ std::get_if<TrackId>(¶ms.id) })
|
||||
core::Service<feedback::IFeedbackService>::get()->setRating(context.user->getId(), *trackId, params.rating);
|
||||
core::Service<feedback::IFeedbackService>::get()->setRating(context.getUser()->getId(), *trackId, params.rating);
|
||||
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
|
||||
Response handleScrobble(RequestContext& context)
|
||||
{
|
||||
const std::vector<TrackId> ids{ getMandatoryMultiParametersAs<TrackId>(context.parameters, "id") };
|
||||
const std::vector<unsigned long> times{ getMultiParametersAs<unsigned long>(context.parameters, "time") };
|
||||
const bool submission{ getParameterAs<bool>(context.parameters, "submission").value_or(true) };
|
||||
const std::vector<TrackId> ids{ getMandatoryMultiParametersAs<TrackId>(context.getParameters(), "id") };
|
||||
const std::vector<unsigned long> times{ getMultiParametersAs<unsigned long>(context.getParameters(), "time") };
|
||||
const bool submission{ getParameterAs<bool>(context.getParameters(), "submission").value_or(true) };
|
||||
|
||||
// playing now => only one at a time
|
||||
if (!submission && ids.size() > 1)
|
||||
@@ -190,13 +190,13 @@ namespace lms::api::subsonic
|
||||
|
||||
if (!submission)
|
||||
{
|
||||
core::Service<scrobbling::IScrobblingService>::get()->listenStarted({ context.user->getId(), ids.front() });
|
||||
core::Service<scrobbling::IScrobblingService>::get()->listenStarted({ context.getUser()->getId(), ids.front() });
|
||||
}
|
||||
else
|
||||
{
|
||||
if (times.empty())
|
||||
{
|
||||
core::Service<scrobbling::IScrobblingService>::get()->listenFinished({ context.user->getId(), ids.front() });
|
||||
core::Service<scrobbling::IScrobblingService>::get()->listenFinished({ context.getUser()->getId(), ids.front() });
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -204,11 +204,11 @@ namespace lms::api::subsonic
|
||||
{
|
||||
const TrackId trackId{ ids[i] };
|
||||
const unsigned long time{ times[i] };
|
||||
core::Service<scrobbling::IScrobblingService>::get()->addTimedListen({ { context.user->getId(), trackId }, Wt::WDateTime::fromTime_t(static_cast<std::time_t>(time / 1000)) });
|
||||
core::Service<scrobbling::IScrobblingService>::get()->addTimedListen({ { context.getUser()->getId(), trackId }, Wt::WDateTime::fromTime_t(static_cast<std::time_t>(time / 1000)) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
} // namespace lms::api::subsonic
|
||||
@@ -51,7 +51,7 @@ namespace lms::api::subsonic::Scan
|
||||
|
||||
Response handleGetScanStatus(RequestContext& context)
|
||||
{
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
response.addNode("scanStatus", createStatusResponseNode());
|
||||
|
||||
return response;
|
||||
@@ -61,7 +61,7 @@ namespace lms::api::subsonic::Scan
|
||||
{
|
||||
core::Service<IScannerService>::get()->requestImmediateScan();
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
response.addNode("scanStatus", createStatusResponseNode());
|
||||
|
||||
return response;
|
||||
|
||||
@@ -176,20 +176,20 @@ namespace lms::api::subsonic
|
||||
StreamParameters getStreamParameters(RequestContext& context)
|
||||
{
|
||||
// Mandatory params
|
||||
const auto trackId{ getParameterAs<db::TrackId>(context.parameters, "id") };
|
||||
const auto podcastEpisodeId{ getParameterAs<db::PodcastEpisodeId>(context.parameters, "id") };
|
||||
const auto trackId{ getParameterAs<db::TrackId>(context.getParameters(), "id") };
|
||||
const auto podcastEpisodeId{ getParameterAs<db::PodcastEpisodeId>(context.getParameters(), "id") };
|
||||
if (!trackId && !podcastEpisodeId)
|
||||
throw RequiredParameterMissingError{ "id" };
|
||||
|
||||
const AudioFileId audioId{ trackId ? AudioFileId{ *trackId } : AudioFileId{ *podcastEpisodeId } };
|
||||
|
||||
// Optional params
|
||||
std::size_t maxBitRate{ getParameterAs<std::size_t>(context.parameters, "maxBitRate").value_or(0) * 1000 }; // "If set to zero, no limit is imposed", given in kpbs
|
||||
const std::string format{ getParameterAs<std::string>(context.parameters, "format").value_or("") };
|
||||
std::size_t timeOffset{ getParameterAs<std::size_t>(context.parameters, "timeOffset").value_or(0) };
|
||||
bool estimateContentLength{ getParameterAs<bool>(context.parameters, "estimateContentLength").value_or(false) };
|
||||
std::size_t maxBitRate{ getParameterAs<std::size_t>(context.getParameters(), "maxBitRate").value_or(0) * 1000 }; // "If set to zero, no limit is imposed", given in kpbs
|
||||
const std::string format{ getParameterAs<std::string>(context.getParameters(), "format").value_or("") };
|
||||
std::size_t timeOffset{ getParameterAs<std::size_t>(context.getParameters(), "timeOffset").value_or(0) };
|
||||
bool estimateContentLength{ getParameterAs<bool>(context.getParameters(), "estimateContentLength").value_or(false) };
|
||||
|
||||
const AudioFileInfo audioFileInfo{ getAudioFileInfo(context.dbSession, audioId) };
|
||||
const AudioFileInfo audioFileInfo{ getAudioFileInfo(context.getDbSession(), audioId) };
|
||||
|
||||
StreamParameters parameters;
|
||||
|
||||
@@ -205,8 +205,8 @@ namespace lms::api::subsonic
|
||||
std::optional<transcoding::OutputFormat> requestedFormat{ subsonicStreamFormatToAvOutputFormat(format) };
|
||||
if (!requestedFormat)
|
||||
{
|
||||
if (context.user->getSubsonicEnableTranscodingByDefault())
|
||||
requestedFormat = userTranscodeFormatToAvFormat(context.user->getSubsonicDefaultTranscodingOutputFormat());
|
||||
if (context.getUser()->getSubsonicEnableTranscodingByDefault())
|
||||
requestedFormat = userTranscodeFormatToAvFormat(context.getUser()->getSubsonicDefaultTranscodingOutputFormat());
|
||||
}
|
||||
|
||||
if (!requestedFormat && (maxBitRate == 0 || audioFileInfo.bitrate <= maxBitRate))
|
||||
@@ -231,9 +231,9 @@ namespace lms::api::subsonic
|
||||
|
||||
// Need to transcode here
|
||||
if (!requestedFormat)
|
||||
requestedFormat = userTranscodeFormatToAvFormat(context.user->getSubsonicDefaultTranscodingOutputFormat());
|
||||
requestedFormat = userTranscodeFormatToAvFormat(context.getUser()->getSubsonicDefaultTranscodingOutputFormat());
|
||||
if (!bitrate)
|
||||
bitrate = context.user->getSubsonicDefaultTranscodingOutputBitrate();
|
||||
bitrate = context.getUser()->getSubsonicDefaultTranscodingOutputBitrate();
|
||||
if (maxBitRate)
|
||||
bitrate = std::min<std::size_t>(bitrate, maxBitRate);
|
||||
|
||||
@@ -248,13 +248,13 @@ namespace lms::api::subsonic
|
||||
|
||||
Response handleGetLyrics(RequestContext& context)
|
||||
{
|
||||
std::string artistName{ getParameterAs<std::string>(context.parameters, "artist").value_or("") };
|
||||
std::string titleName{ getParameterAs<std::string>(context.parameters, "title").value_or("") };
|
||||
std::string artistName{ getParameterAs<std::string>(context.getParameters(), "artist").value_or("") };
|
||||
std::string titleName{ getParameterAs<std::string>(context.getParameters(), "title").value_or("") };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
|
||||
// best effort search, as this API is really limited
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
db::Track::FindParameters params;
|
||||
params.setName(titleName);
|
||||
@@ -262,7 +262,7 @@ namespace lms::api::subsonic
|
||||
params.setRange(db::Range{ .offset = 0, .size = 2 });
|
||||
|
||||
// Choice: we return nothing if there are too many results
|
||||
const auto tracks{ db::Track::findIds(context.dbSession, params) };
|
||||
const auto tracks{ db::Track::findIds(context.getDbSession(), params) };
|
||||
if (tracks.results.size() == 1)
|
||||
{
|
||||
// Choice: we return only the first lyrics if the track has many lyrics
|
||||
@@ -271,7 +271,7 @@ namespace lms::api::subsonic
|
||||
lyricsParams.setSortMethod(db::TrackLyricsSortMethod::ExternalFirst);
|
||||
lyricsParams.setRange(db::Range{ 0, 1 });
|
||||
|
||||
db::TrackLyrics::find(context.dbSession, lyricsParams, [&](const db::TrackLyrics::pointer& lyrics) {
|
||||
db::TrackLyrics::find(context.getDbSession(), lyricsParams, [&](const db::TrackLyrics::pointer& lyrics) {
|
||||
response.addNode("lyrics", createLyricsNode(context, lyrics));
|
||||
});
|
||||
}
|
||||
@@ -282,14 +282,14 @@ namespace lms::api::subsonic
|
||||
Response handleGetLyricsBySongId(RequestContext& context)
|
||||
{
|
||||
// mandatory params
|
||||
db::TrackId id{ getMandatoryParameterAs<db::TrackId>(context.parameters, "id") };
|
||||
db::TrackId id{ getMandatoryParameterAs<db::TrackId>(context.getParameters(), "id") };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& lyricsList{ response.createNode("lyricsList") };
|
||||
lyricsList.createEmptyArrayChild("structuredLyrics");
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
const db::Track::pointer track{ db::Track::find(context.dbSession, id) };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
const db::Track::pointer track{ db::Track::find(context.getDbSession(), id) };
|
||||
if (track)
|
||||
{
|
||||
db::TrackLyrics::FindParameters params;
|
||||
@@ -297,7 +297,7 @@ namespace lms::api::subsonic
|
||||
params.setExternal(true); // First try to only report external lyrics as they are often duplicate of embedded lyrics and support more features
|
||||
|
||||
bool hasExternalLyrics{};
|
||||
db::TrackLyrics::find(context.dbSession, params, [&](const db::TrackLyrics::pointer& lyrics) {
|
||||
db::TrackLyrics::find(context.getDbSession(), params, [&](const db::TrackLyrics::pointer& lyrics) {
|
||||
lyricsList.addArrayChild("structuredLyrics", createStructuredLyricsNode(context, lyrics));
|
||||
hasExternalLyrics = true;
|
||||
});
|
||||
@@ -305,7 +305,7 @@ namespace lms::api::subsonic
|
||||
if (!hasExternalLyrics)
|
||||
{
|
||||
params.setExternal(false);
|
||||
db::TrackLyrics::find(context.dbSession, params, [&](const db::TrackLyrics::pointer& lyrics) {
|
||||
db::TrackLyrics::find(context.getDbSession(), params, [&](const db::TrackLyrics::pointer& lyrics) {
|
||||
lyricsList.addArrayChild("structuredLyrics", createStructuredLyricsNode(context, lyrics));
|
||||
});
|
||||
}
|
||||
@@ -322,13 +322,13 @@ namespace lms::api::subsonic
|
||||
if (!continuation)
|
||||
{
|
||||
// Mandatory params
|
||||
db::TrackId id{ getMandatoryParameterAs<db::TrackId>(context.parameters, "id") };
|
||||
db::TrackId id{ getMandatoryParameterAs<db::TrackId>(context.getParameters(), "id") };
|
||||
|
||||
std::filesystem::path trackPath;
|
||||
{
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
auto track{ db::Track::find(context.dbSession, id) };
|
||||
auto track{ db::Track::find(context.getDbSession(), id) };
|
||||
if (!track)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
@@ -381,9 +381,9 @@ namespace lms::api::subsonic
|
||||
void handleGetCoverArt(RequestContext& context, const Wt::Http::Request& /*request*/, Wt::Http::Response& response)
|
||||
{
|
||||
// Mandatory params
|
||||
const CoverArtId coverArtId{ getMandatoryParameterAs<CoverArtId>(context.parameters, "id") };
|
||||
const CoverArtId coverArtId{ getMandatoryParameterAs<CoverArtId>(context.getParameters(), "id") };
|
||||
|
||||
std::optional<std::size_t> size{ getParameterAs<std::size_t>(context.parameters, "size") };
|
||||
std::optional<std::size_t> size{ getParameterAs<std::size_t>(context.getParameters(), "size") };
|
||||
if (size)
|
||||
*size = std::clamp(*size, std::size_t{ 32 }, std::size_t{ 2048 });
|
||||
|
||||
|
||||
@@ -53,9 +53,9 @@ namespace lms::api::subsonic
|
||||
|
||||
Response handleGetPlaylistsRequest(RequestContext& context)
|
||||
{
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& playlistsNode{ response.createNode("playlists") };
|
||||
|
||||
auto addTrackList{ [&](const db::TrackList::pointer& trackList) {
|
||||
@@ -65,10 +65,10 @@ namespace lms::api::subsonic
|
||||
// First add user's playlists
|
||||
{
|
||||
TrackList::FindParameters params;
|
||||
params.setUser(context.user->getId());
|
||||
params.setUser(context.getUser()->getId());
|
||||
params.setType(TrackListType::PlayList);
|
||||
|
||||
db::TrackList::find(context.dbSession, params, [&](const db::TrackList::pointer& trackList) {
|
||||
db::TrackList::find(context.getDbSession(), params, [&](const db::TrackList::pointer& trackList) {
|
||||
addTrackList(trackList);
|
||||
});
|
||||
}
|
||||
@@ -78,10 +78,10 @@ namespace lms::api::subsonic
|
||||
TrackList::FindParameters params;
|
||||
params.setVisibility(TrackList::Visibility::Public);
|
||||
params.setType(TrackListType::PlayList);
|
||||
params.setExcludedUser(context.user->getId());
|
||||
params.setExcludedUser(context.getUser()->getId());
|
||||
|
||||
db::TrackList::find(context.dbSession, params, [&](const db::TrackList::pointer& trackList) {
|
||||
assert(trackList->getUserId() != context.user->getId());
|
||||
db::TrackList::find(context.getDbSession(), params, [&](const db::TrackList::pointer& trackList) {
|
||||
assert(trackList->getUserId() != context.getUser()->getId());
|
||||
addTrackList(trackList);
|
||||
});
|
||||
}
|
||||
@@ -92,23 +92,23 @@ namespace lms::api::subsonic
|
||||
Response handleGetPlaylistRequest(RequestContext& context)
|
||||
{
|
||||
// Mandatory params
|
||||
TrackListId trackListId{ getMandatoryParameterAs<TrackListId>(context.parameters, "id") };
|
||||
TrackListId trackListId{ getMandatoryParameterAs<TrackListId>(context.getParameters(), "id") };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
TrackList::pointer trackList{ TrackList::find(context.dbSession, trackListId) };
|
||||
TrackList::pointer trackList{ TrackList::find(context.getDbSession(), trackListId) };
|
||||
if (!trackList || trackList->getType() != TrackListType::PlayList)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
if (trackList->getUserId() != context.user->getId() && trackList->getVisibility() != TrackList::Visibility::Public)
|
||||
if (trackList->getUserId() != context.getUser()->getId() && trackList->getVisibility() != TrackList::Visibility::Public)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node playlistNode{ createPlaylistNode(context, trackList) };
|
||||
|
||||
auto entries{ trackList->getEntries() };
|
||||
for (const TrackListEntry::pointer& entry : entries.results)
|
||||
playlistNode.addArrayChild("entry", createSongNode(context, entry->getTrack(), context.user));
|
||||
playlistNode.addArrayChild("entry", createSongNode(context, entry->getTrack(), context.getUser()));
|
||||
|
||||
response.addNode("playlist", std::move(playlistNode));
|
||||
|
||||
@@ -118,21 +118,21 @@ namespace lms::api::subsonic
|
||||
Response handleCreatePlaylistRequest(RequestContext& context)
|
||||
{
|
||||
// Optional params
|
||||
const auto id{ getParameterAs<TrackListId>(context.parameters, "playlistId") };
|
||||
auto name{ getParameterAs<std::string>(context.parameters, "name") };
|
||||
const auto id{ getParameterAs<TrackListId>(context.getParameters(), "playlistId") };
|
||||
auto name{ getParameterAs<std::string>(context.getParameters(), "name") };
|
||||
|
||||
std::vector<TrackId> trackIds{ getMultiParametersAs<TrackId>(context.parameters, "songId") };
|
||||
std::vector<TrackId> trackIds{ getMultiParametersAs<TrackId>(context.getParameters(), "songId") };
|
||||
|
||||
if (!name && !id)
|
||||
throw RequiredParameterMissingError{ "name or playlistId" };
|
||||
|
||||
auto transaction{ context.dbSession.createWriteTransaction() };
|
||||
auto transaction{ context.getDbSession().createWriteTransaction() };
|
||||
|
||||
TrackList::pointer trackList;
|
||||
if (id)
|
||||
{
|
||||
trackList = TrackList::find(context.dbSession, *id);
|
||||
checkTrackListModificationAccess(trackList, context.user->getId());
|
||||
trackList = TrackList::find(context.getDbSession(), *id);
|
||||
checkTrackListModificationAccess(trackList, context.getUser()->getId());
|
||||
|
||||
if (name)
|
||||
trackList.modify()->setName(*name);
|
||||
@@ -142,26 +142,26 @@ namespace lms::api::subsonic
|
||||
}
|
||||
else
|
||||
{
|
||||
trackList = context.dbSession.create<TrackList>(*name, TrackListType::PlayList);
|
||||
trackList.modify()->setUser(context.user);
|
||||
trackList = context.getDbSession().create<TrackList>(*name, TrackListType::PlayList);
|
||||
trackList.modify()->setUser(context.getUser());
|
||||
trackList.modify()->setVisibility(TrackList::Visibility::Private);
|
||||
}
|
||||
|
||||
for (const TrackId trackId : trackIds)
|
||||
{
|
||||
Track::pointer track{ Track::find(context.dbSession, trackId) };
|
||||
Track::pointer track{ Track::find(context.getDbSession(), trackId) };
|
||||
if (!track)
|
||||
continue;
|
||||
|
||||
context.dbSession.create<TrackListEntry>(track, trackList);
|
||||
context.getDbSession().create<TrackListEntry>(track, trackList);
|
||||
}
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node playlistNode{ createPlaylistNode(context, trackList) };
|
||||
|
||||
auto entries{ trackList->getEntries() };
|
||||
for (const TrackListEntry::pointer& entry : entries.results)
|
||||
playlistNode.addArrayChild("entry", createSongNode(context, entry->getTrack(), context.user));
|
||||
playlistNode.addArrayChild("entry", createSongNode(context, entry->getTrack(), context.getUser()));
|
||||
|
||||
response.addNode("playlist", std::move(playlistNode));
|
||||
|
||||
@@ -171,19 +171,19 @@ namespace lms::api::subsonic
|
||||
Response handleUpdatePlaylistRequest(RequestContext& context)
|
||||
{
|
||||
// Mandatory params
|
||||
TrackListId id{ getMandatoryParameterAs<TrackListId>(context.parameters, "playlistId") };
|
||||
TrackListId id{ getMandatoryParameterAs<TrackListId>(context.getParameters(), "playlistId") };
|
||||
|
||||
// Optional parameters
|
||||
auto name{ getParameterAs<std::string>(context.parameters, "name") };
|
||||
auto isPublic{ getParameterAs<bool>(context.parameters, "public") };
|
||||
auto name{ getParameterAs<std::string>(context.getParameters(), "name") };
|
||||
auto isPublic{ getParameterAs<bool>(context.getParameters(), "public") };
|
||||
|
||||
std::vector<TrackId> trackIdsToAdd{ getMultiParametersAs<TrackId>(context.parameters, "songIdToAdd") };
|
||||
std::vector<std::size_t> trackPositionsToRemove{ getMultiParametersAs<std::size_t>(context.parameters, "songIndexToRemove") };
|
||||
std::vector<TrackId> trackIdsToAdd{ getMultiParametersAs<TrackId>(context.getParameters(), "songIdToAdd") };
|
||||
std::vector<std::size_t> trackPositionsToRemove{ getMultiParametersAs<std::size_t>(context.getParameters(), "songIndexToRemove") };
|
||||
|
||||
auto transaction{ context.dbSession.createWriteTransaction() };
|
||||
auto transaction{ context.getDbSession().createWriteTransaction() };
|
||||
|
||||
TrackList::pointer trackList{ TrackList::find(context.dbSession, id) };
|
||||
checkTrackListModificationAccess(trackList, context.user->getId());
|
||||
TrackList::pointer trackList{ TrackList::find(context.getDbSession(), id) };
|
||||
checkTrackListModificationAccess(trackList, context.getUser()->getId());
|
||||
|
||||
if (name)
|
||||
trackList.modify()->setName(*name);
|
||||
@@ -206,27 +206,27 @@ namespace lms::api::subsonic
|
||||
// Add tracks
|
||||
for (const TrackId trackIdToAdd : trackIdsToAdd)
|
||||
{
|
||||
Track::pointer track{ Track::find(context.dbSession, trackIdToAdd) };
|
||||
Track::pointer track{ Track::find(context.getDbSession(), trackIdToAdd) };
|
||||
if (!track)
|
||||
continue;
|
||||
|
||||
context.dbSession.create<TrackListEntry>(track, trackList);
|
||||
context.getDbSession().create<TrackListEntry>(track, trackList);
|
||||
}
|
||||
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
|
||||
Response handleDeletePlaylistRequest(RequestContext& context)
|
||||
{
|
||||
TrackListId id{ getMandatoryParameterAs<TrackListId>(context.parameters, "id") };
|
||||
TrackListId id{ getMandatoryParameterAs<TrackListId>(context.getParameters(), "id") };
|
||||
|
||||
auto transaction{ context.dbSession.createWriteTransaction() };
|
||||
auto transaction{ context.getDbSession().createWriteTransaction() };
|
||||
|
||||
TrackList::pointer trackList{ TrackList::find(context.dbSession, id) };
|
||||
checkTrackListModificationAccess(trackList, context.user->getId());
|
||||
TrackList::pointer trackList{ TrackList::find(context.getDbSession(), id) };
|
||||
checkTrackListModificationAccess(trackList, context.getUser()->getId());
|
||||
|
||||
trackList.remove();
|
||||
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
} // namespace lms::api::subsonic
|
||||
@@ -34,14 +34,14 @@ namespace lms::api::subsonic
|
||||
{
|
||||
Response handleGetPodcasts(RequestContext& context)
|
||||
{
|
||||
const bool includeEpisodes{ getParameterAs<bool>(context.parameters, "includeEpisodes").value_or(true) };
|
||||
const std::optional<db::PodcastId> podcastId{ getParameterAs<db::PodcastId>(context.parameters, "id") };
|
||||
const bool includeEpisodes{ getParameterAs<bool>(context.getParameters(), "includeEpisodes").value_or(true) };
|
||||
const std::optional<db::PodcastId> podcastId{ getParameterAs<db::PodcastId>(context.getParameters(), "id") };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& podcastsNode{ response.createNode("podcasts") };
|
||||
podcastsNode.createEmptyArrayChild("channel");
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
auto processPodcast{ [&](const db::Podcast::pointer& podcast) {
|
||||
podcastsNode.addArrayChild("channel", createPodcastNode(context, podcast, includeEpisodes));
|
||||
@@ -49,34 +49,34 @@ namespace lms::api::subsonic
|
||||
|
||||
if (podcastId.has_value())
|
||||
{
|
||||
db::Podcast::pointer podcast{ db::Podcast::find(context.dbSession, podcastId.value()) };
|
||||
db::Podcast::pointer podcast{ db::Podcast::find(context.getDbSession(), podcastId.value()) };
|
||||
if (!podcast)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
processPodcast(podcast);
|
||||
}
|
||||
else
|
||||
db::Podcast::find(context.dbSession, processPodcast);
|
||||
db::Podcast::find(context.getDbSession(), processPodcast);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
Response handleGetNewestPodcasts(RequestContext& context)
|
||||
{
|
||||
std::size_t count{ getParameterAs<std::size_t>(context.parameters, "count").value_or(20) };
|
||||
std::size_t count{ getParameterAs<std::size_t>(context.getParameters(), "count").value_or(20) };
|
||||
count = std::min<std::size_t>(count, 100);
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& newestPodcastsNode{ response.createNode("newestPodcasts") };
|
||||
newestPodcastsNode.createEmptyArrayChild("episode");
|
||||
|
||||
{
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
db::PodcastEpisode::FindParameters findParameters;
|
||||
findParameters.setRange(db::Range{ .offset = 0, .size = count });
|
||||
|
||||
db::PodcastEpisode::find(context.dbSession, findParameters, [&](const db::PodcastEpisode::pointer& episode) {
|
||||
db::PodcastEpisode::find(context.getDbSession(), findParameters, [&](const db::PodcastEpisode::pointer& episode) {
|
||||
newestPodcastsNode.addArrayChild("episode", createPodcastEpisodeNode(episode));
|
||||
});
|
||||
}
|
||||
@@ -88,13 +88,13 @@ namespace lms::api::subsonic
|
||||
{
|
||||
core::Service<podcast::IPodcastService>::get()->refreshPodcasts();
|
||||
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
|
||||
Response handleCreatePodcastChannel(RequestContext& context)
|
||||
{
|
||||
// Mandatory parameters
|
||||
const std::string url{ getMandatoryParameterAs<std::string>(context.parameters, "url") };
|
||||
const std::string url{ getMandatoryParameterAs<std::string>(context.getParameters(), "url") };
|
||||
|
||||
if (url.empty() || !(url.starts_with("http://") || url.starts_with("https://")))
|
||||
throw BadParameterGenericError{ "Invalid url" };
|
||||
@@ -102,52 +102,52 @@ namespace lms::api::subsonic
|
||||
// no effect if podcast already exists
|
||||
core::Service<podcast::IPodcastService>::get()->addPodcast(url);
|
||||
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
|
||||
Response handleDeletePodcastChannel(RequestContext& context)
|
||||
{
|
||||
// Mandatory parameters
|
||||
const db::PodcastId podcastId{ getMandatoryParameterAs<db::PodcastId>(context.parameters, "id") };
|
||||
const db::PodcastId podcastId{ getMandatoryParameterAs<db::PodcastId>(context.getParameters(), "id") };
|
||||
|
||||
if (!core::Service<podcast::IPodcastService>::get()->removePodcast(podcastId))
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
|
||||
Response handleDeletePodcastEpisode(RequestContext& context)
|
||||
{
|
||||
// Mandatory parameters
|
||||
const db::PodcastEpisodeId episodeId{ getMandatoryParameterAs<db::PodcastEpisodeId>(context.parameters, "id") };
|
||||
const db::PodcastEpisodeId episodeId{ getMandatoryParameterAs<db::PodcastEpisodeId>(context.getParameters(), "id") };
|
||||
|
||||
if (!core::Service<podcast::IPodcastService>::get()->deletePodcastEpisode(episodeId))
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
|
||||
Response handleDownloadPodcastEpisode(RequestContext& context)
|
||||
{
|
||||
// Mandatory parameters
|
||||
const db::PodcastEpisodeId episodeId{ getMandatoryParameterAs<db::PodcastEpisodeId>(context.parameters, "id") };
|
||||
const db::PodcastEpisodeId episodeId{ getMandatoryParameterAs<db::PodcastEpisodeId>(context.getParameters(), "id") };
|
||||
|
||||
if (!core::Service<podcast::IPodcastService>::get()->downloadPodcastEpisode(episodeId))
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
|
||||
Response handleGetPodcastEpisode(RequestContext& context)
|
||||
{
|
||||
// Mandatory parameters
|
||||
const db::PodcastEpisodeId episodeId{ getMandatoryParameterAs<db::PodcastEpisodeId>(context.parameters, "id") };
|
||||
const db::PodcastEpisodeId episodeId{ getMandatoryParameterAs<db::PodcastEpisodeId>(context.getParameters(), "id") };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
const db::PodcastEpisode::pointer episode{ db::PodcastEpisode::find(context.dbSession, episodeId) };
|
||||
const db::PodcastEpisode::pointer episode{ db::PodcastEpisode::find(context.getDbSession(), episodeId) };
|
||||
if (!episode)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
|
||||
@@ -118,14 +118,14 @@ namespace lms::api::subsonic
|
||||
{
|
||||
// For now, no need to optimize all this
|
||||
// Find all the directories that match the name and that do not contain any track (considered by the legacy API as artists)
|
||||
const std::size_t artistCount{ getParameterAs<std::size_t>(context.parameters, "artistCount").value_or(20) };
|
||||
const std::size_t artistCount{ getParameterAs<std::size_t>(context.getParameters(), "artistCount").value_or(20) };
|
||||
if (artistCount == 0)
|
||||
return;
|
||||
|
||||
if (artistCount > defaultMaxCountSize)
|
||||
throw ParameterValueTooHighGenericError{ "artistCount", defaultMaxCountSize };
|
||||
|
||||
const std::size_t artistOffset{ getParameterAs<std::size_t>(context.parameters, "artistOffset").value_or(0) };
|
||||
const std::size_t artistOffset{ getParameterAs<std::size_t>(context.getParameters(), "artistOffset").value_or(0) };
|
||||
|
||||
Directory::FindParameters params;
|
||||
params.setKeywords(keywords);
|
||||
@@ -133,7 +133,7 @@ namespace lms::api::subsonic
|
||||
params.setWithNoTrack(true);
|
||||
params.setMediaLibrary(mediaLibrary);
|
||||
|
||||
Directory::find(context.dbSession, params, [&](const Directory::pointer& directory) {
|
||||
Directory::find(context.getDbSession(), params, [&](const Directory::pointer& directory) {
|
||||
Response::Node childNode;
|
||||
childNode.setAttribute("id", idToString(directory->getId()));
|
||||
childNode.setAttribute("name", directory->getName());
|
||||
@@ -147,14 +147,14 @@ namespace lms::api::subsonic
|
||||
{
|
||||
static ScanTracker<ArtistId> currentScansInProgress;
|
||||
|
||||
const std::size_t artistCount{ getParameterAs<std::size_t>(context.parameters, "artistCount").value_or(20) };
|
||||
const std::size_t artistCount{ getParameterAs<std::size_t>(context.getParameters(), "artistCount").value_or(20) };
|
||||
if (artistCount == 0)
|
||||
return;
|
||||
|
||||
if (artistCount > defaultMaxCountSize)
|
||||
throw ParameterValueTooHighGenericError{ "artistCount", defaultMaxCountSize };
|
||||
|
||||
const std::size_t artistOffset{ getParameterAs<std::size_t>(context.parameters, "artistOffset").value_or(0) };
|
||||
const std::size_t artistOffset{ getParameterAs<std::size_t>(context.getParameters(), "artistOffset").value_or(0) };
|
||||
|
||||
ArtistId lastRetrievedId;
|
||||
auto findArtists{ [&] {
|
||||
@@ -164,7 +164,7 @@ namespace lms::api::subsonic
|
||||
params.setRange(Range{ artistOffset, artistCount });
|
||||
params.setSortMethod(ArtistSortMethod::Id); // must be consistent with both methods
|
||||
|
||||
Artist::find(context.dbSession, params, [&](const Artist::pointer& artist) {
|
||||
Artist::find(context.getDbSession(), params, [&](const Artist::pointer& artist) {
|
||||
searchResultNode.addArrayChild("artist", createArtistNode(context, artist));
|
||||
lastRetrievedId = artist->getId();
|
||||
});
|
||||
@@ -177,9 +177,9 @@ namespace lms::api::subsonic
|
||||
else
|
||||
{
|
||||
ScanTracker<ArtistId>::ScanInfo scanInfo{
|
||||
.clientAddress = context.clientIpAddr,
|
||||
.clientName = context.clientInfo.name,
|
||||
.user = context.user->getId(),
|
||||
.clientAddress = context.getClientIpAddr(),
|
||||
.clientName = std::string{ context.getClientName() },
|
||||
.user = context.getUser()->getId(),
|
||||
.library = mediaLibrary,
|
||||
.offset = artistOffset
|
||||
};
|
||||
@@ -187,7 +187,7 @@ namespace lms::api::subsonic
|
||||
if (ArtistId cachedLastRetrievedId{ currentScansInProgress.extractLastRetrievedObjectId(scanInfo) }; cachedLastRetrievedId.isValid())
|
||||
{
|
||||
Artist::find(
|
||||
context.dbSession, cachedLastRetrievedId, artistCount, [&](const Artist::pointer& artist) {
|
||||
context.getDbSession(), cachedLastRetrievedId, artistCount, [&](const Artist::pointer& artist) {
|
||||
searchResultNode.addArrayChild("artist", createArtistNode(context, artist));
|
||||
},
|
||||
mediaLibrary);
|
||||
@@ -210,14 +210,14 @@ namespace lms::api::subsonic
|
||||
{
|
||||
static ScanTracker<ReleaseId> currentScansInProgress;
|
||||
|
||||
const std::size_t albumCount{ getParameterAs<std::size_t>(context.parameters, "albumCount").value_or(20) };
|
||||
const std::size_t albumCount{ getParameterAs<std::size_t>(context.getParameters(), "albumCount").value_or(20) };
|
||||
if (albumCount == 0)
|
||||
return;
|
||||
|
||||
if (albumCount > defaultMaxCountSize)
|
||||
throw ParameterValueTooHighGenericError{ "albumCount", defaultMaxCountSize };
|
||||
|
||||
const std::size_t albumOffset{ getParameterAs<std::size_t>(context.parameters, "albumOffset").value_or(0) };
|
||||
const std::size_t albumOffset{ getParameterAs<std::size_t>(context.getParameters(), "albumOffset").value_or(0) };
|
||||
|
||||
ReleaseId lastRetrievedId;
|
||||
|
||||
@@ -228,7 +228,7 @@ namespace lms::api::subsonic
|
||||
params.filters.setMediaLibrary(mediaLibrary);
|
||||
params.setSortMethod(ReleaseSortMethod::Id); // must be consistent with both methods
|
||||
|
||||
Release::find(context.dbSession, params, [&](const Release::pointer& release) {
|
||||
Release::find(context.getDbSession(), params, [&](const Release::pointer& release) {
|
||||
searchResultNode.addArrayChild("album", createAlbumNode(context, release, id3));
|
||||
lastRetrievedId = release->getId();
|
||||
});
|
||||
@@ -241,9 +241,9 @@ namespace lms::api::subsonic
|
||||
else
|
||||
{
|
||||
ScanTracker<ReleaseId>::ScanInfo scanInfo{
|
||||
.clientAddress = context.clientIpAddr,
|
||||
.clientName = context.clientInfo.name,
|
||||
.user = context.user->getId(),
|
||||
.clientAddress = context.getClientIpAddr(),
|
||||
.clientName = std::string{ context.getClientName() },
|
||||
.user = context.getUser()->getId(),
|
||||
.library = mediaLibrary,
|
||||
.offset = albumOffset
|
||||
};
|
||||
@@ -251,7 +251,7 @@ namespace lms::api::subsonic
|
||||
if (ReleaseId cachedLastRetrievedId{ currentScansInProgress.extractLastRetrievedObjectId(scanInfo) }; cachedLastRetrievedId.isValid())
|
||||
{
|
||||
Release::find(
|
||||
context.dbSession, cachedLastRetrievedId, albumCount, [&](const Release::pointer& release) {
|
||||
context.getDbSession(), cachedLastRetrievedId, albumCount, [&](const Release::pointer& release) {
|
||||
searchResultNode.addArrayChild("album", createAlbumNode(context, release, id3));
|
||||
},
|
||||
mediaLibrary);
|
||||
@@ -274,14 +274,14 @@ namespace lms::api::subsonic
|
||||
{
|
||||
static ScanTracker<TrackId> currentScansInProgress;
|
||||
|
||||
const std::size_t songCount{ getParameterAs<std::size_t>(context.parameters, "songCount").value_or(20) };
|
||||
const std::size_t songCount{ getParameterAs<std::size_t>(context.getParameters(), "songCount").value_or(20) };
|
||||
if (songCount == 0)
|
||||
return;
|
||||
|
||||
if (songCount > defaultMaxCountSize)
|
||||
throw ParameterValueTooHighGenericError{ "songCount", defaultMaxCountSize };
|
||||
|
||||
const std::size_t songOffset{ getParameterAs<std::size_t>(context.parameters, "songOffset").value_or(0) };
|
||||
const std::size_t songOffset{ getParameterAs<std::size_t>(context.getParameters(), "songOffset").value_or(0) };
|
||||
|
||||
TrackId lastRetrievedId;
|
||||
|
||||
@@ -292,7 +292,7 @@ namespace lms::api::subsonic
|
||||
params.filters.setMediaLibrary(mediaLibrary);
|
||||
params.setSortMethod(TrackSortMethod::Id); // must be consistent with both methods
|
||||
|
||||
Track::find(context.dbSession, params, [&](const Track::pointer& track) {
|
||||
Track::find(context.getDbSession(), params, [&](const Track::pointer& track) {
|
||||
searchResultNode.addArrayChild("song", createSongNode(context, track, id3));
|
||||
lastRetrievedId = track->getId();
|
||||
});
|
||||
@@ -305,9 +305,9 @@ namespace lms::api::subsonic
|
||||
else
|
||||
{
|
||||
ScanTracker<TrackId>::ScanInfo scanInfo{
|
||||
.clientAddress = context.clientIpAddr,
|
||||
.clientName = context.clientInfo.name,
|
||||
.user = context.user->getId(),
|
||||
.clientAddress = context.getClientIpAddr(),
|
||||
.clientName = std::string{ context.getClientName() },
|
||||
.user = context.getUser()->getId(),
|
||||
.library = mediaLibrary,
|
||||
.offset = songOffset
|
||||
};
|
||||
@@ -315,7 +315,7 @@ namespace lms::api::subsonic
|
||||
if (TrackId cachedLastRetrievedId{ currentScansInProgress.extractLastRetrievedObjectId(scanInfo) }; cachedLastRetrievedId.isValid())
|
||||
{
|
||||
Track::find(
|
||||
context.dbSession, cachedLastRetrievedId, songCount, [&](const Track::pointer& track) {
|
||||
context.getDbSession(), cachedLastRetrievedId, songCount, [&](const Track::pointer& track) {
|
||||
searchResultNode.addArrayChild("song", createSongNode(context, track, id3));
|
||||
},
|
||||
mediaLibrary);
|
||||
@@ -337,24 +337,24 @@ namespace lms::api::subsonic
|
||||
Response handleSearchRequestCommon(RequestContext& context, bool id3)
|
||||
{
|
||||
// Mandatory params
|
||||
const std::string queryString{ getMandatoryParameterAs<std::string>(context.parameters, "query") };
|
||||
const std::string queryString{ getMandatoryParameterAs<std::string>(context.getParameters(), "query") };
|
||||
std::string_view query{ queryString };
|
||||
|
||||
// Optional params
|
||||
const MediaLibraryId mediaLibrary{ getParameterAs<MediaLibraryId>(context.parameters, "musicFolderId").value_or(MediaLibraryId{}) };
|
||||
const MediaLibraryId mediaLibrary{ getParameterAs<MediaLibraryId>(context.getParameters(), "musicFolderId").value_or(MediaLibraryId{}) };
|
||||
|
||||
// Symfonium adds extra ""
|
||||
if (context.clientInfo.name == "Symfonium")
|
||||
if (context.getClientName() == "Symfonium")
|
||||
query = core::stringUtils::stringTrim(query, "\"");
|
||||
|
||||
std::vector<std::string_view> keywords;
|
||||
if (!query.empty())
|
||||
keywords = core::stringUtils::splitString(query, ' ');
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& searchResultNode{ response.createNode(id3 ? "searchResult3" : "searchResult2") };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
if (id3)
|
||||
findRequestedArtists(context, keywords, mediaLibrary, searchResultNode);
|
||||
|
||||
@@ -4,12 +4,12 @@ namespace lms::api::subsonic
|
||||
{
|
||||
Response handlePingRequest(RequestContext& context)
|
||||
{
|
||||
return Response::createOkResponse(context.serverProtocolVersion);
|
||||
return Response::createOkResponse(context.getServerProtocolVersion());
|
||||
}
|
||||
|
||||
Response handleGetLicenseRequest(RequestContext& context)
|
||||
{
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
|
||||
Response::Node& licenseNode{ response.createNode("license") };
|
||||
licenseNode.setAttribute("licenseExpires", "2035-09-03T14:46:43");
|
||||
@@ -21,7 +21,7 @@ namespace lms::api::subsonic
|
||||
|
||||
Response handleGetOpenSubsonicExtensions(RequestContext& context)
|
||||
{
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
|
||||
{
|
||||
Response::Node& transcodeOffsetNode{ response.createArrayNode("openSubsonicExtensions") };
|
||||
|
||||
@@ -16,24 +16,24 @@ namespace lms::api::subsonic
|
||||
{
|
||||
void checkUserIsMySelfOrAdmin(RequestContext& context, const std::string& username)
|
||||
{
|
||||
if (context.user->getLoginName() != username && !context.user->isAdmin())
|
||||
if (context.getUser()->getLoginName() != username && !context.getUser()->isAdmin())
|
||||
throw UserNotAuthorizedError{};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Response handleGetUserRequest(RequestContext& context)
|
||||
{
|
||||
std::string username{ getMandatoryParameterAs<std::string>(context.parameters, "username") };
|
||||
std::string username{ getMandatoryParameterAs<std::string>(context.getParameters(), "username") };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
|
||||
checkUserIsMySelfOrAdmin(context, username);
|
||||
|
||||
const User::pointer user{ User::find(context.dbSession, username) };
|
||||
const User::pointer user{ User::find(context.getDbSession(), username) };
|
||||
if (!user)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
response.addNode("user", createUserNode(context, user));
|
||||
|
||||
return response;
|
||||
@@ -41,11 +41,11 @@ namespace lms::api::subsonic
|
||||
|
||||
Response handleGetUsersRequest(RequestContext& context)
|
||||
{
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
Response response{ Response::createOkResponse(context.getServerProtocolVersion()) };
|
||||
Response::Node& usersNode{ response.createNode("users") };
|
||||
|
||||
auto transaction{ context.dbSession.createReadTransaction() };
|
||||
User::find(context.dbSession, User::FindParameters{}, [&](const User::pointer& user) {
|
||||
auto transaction{ context.getDbSession().createReadTransaction() };
|
||||
User::find(context.getDbSession(), User::FindParameters{}, [&](const User::pointer& user) {
|
||||
usersNode.addArrayChild("user", createUserNode(context, user));
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user