Refactored request context handling

This commit is contained in:
emeric
2025-10-01 22:11:32 +02:00
parent c62ac1d109
commit 0ccd095534
27 changed files with 594 additions and 473 deletions
@@ -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 });