diff --git a/src/libs/subsonic/impl/SubsonicResource.cpp b/src/libs/subsonic/impl/SubsonicResource.cpp index d8abd57b..0f4f627c 100644 --- a/src/libs/subsonic/impl/SubsonicResource.cpp +++ b/src/libs/subsonic/impl/SubsonicResource.cpp @@ -953,50 +953,6 @@ handleGetArtistInfo2Request(RequestContext& context) return handleGetArtistInfoRequestCommon(context, true /* id3 */); } -static -Response -handleGetArtistsRequest(RequestContext& context) -{ - Response response {Response::createOkResponse(context.serverProtocolVersion)}; - - Response::Node& artistsNode {response.createNode("artists")}; - artistsNode.setAttribute("ignoredArticles", ""); - artistsNode.setAttribute("lastModified", reportedDummyDateULong); - - Response::Node& indexNode {artistsNode.createArrayChild("index")}; - indexNode.setAttribute("name", "?"); - - auto transaction {context.dbSession.createSharedTransaction()}; - - User::pointer user {User::find(context.dbSession, context.userId)}; - if (!user) - throw UserNotAuthorizedError {}; - - Artist::FindParameters findParameters; - - findParameters.setSortMethod(ArtistSortMethod::BySortName); - switch (user->getSubsonicArtistListMode()) - { - case SubsonicArtistListMode::AllArtists: - break; - case SubsonicArtistListMode::ReleaseArtists: - findParameters.setLinkType(TrackArtistLinkType::ReleaseArtist); - break; - case SubsonicArtistListMode::TrackArtists: - findParameters.setLinkType(TrackArtistLinkType::Artist); - break; - } - - const RangeResults artists {Artist::find(context.dbSession, findParameters)}; - for (const ArtistId artistId : artists.results) - { - const auto artist {Artist::find(context.dbSession, artistId)}; - indexNode.addArrayChild("artist", artistToResponseNode(user, artist, true /* id3 */)); - } - - return response; -} - static Response handleGetMusicDirectoryRequest(RequestContext& context) @@ -1079,6 +1035,88 @@ handleGetMusicFoldersRequest(RequestContext& context) return response; } +static +Response +handleGetArtistsRequestCommon(RequestContext& context, bool id3) +{ + Response response {Response::createOkResponse(context.serverProtocolVersion)}; + + Response::Node& artistsNode {response.createNode(id3 ? "artists" : "indexes")}; + artistsNode.setAttribute("ignoredArticles", ""); + artistsNode.setAttribute("lastModified", reportedDummyDateULong); + + auto transaction {context.dbSession.createSharedTransaction()}; + + User::pointer user {User::find(context.dbSession, context.userId)}; + if (!user) + throw UserNotAuthorizedError {}; + + Artist::FindParameters parameters; + parameters.setSortMethod(ArtistSortMethod::BySortName); + switch (user->getSubsonicArtistListMode()) + { + case SubsonicArtistListMode::AllArtists: + break; + case SubsonicArtistListMode::ReleaseArtists: + parameters.setLinkType(TrackArtistLinkType::ReleaseArtist); + break; + case SubsonicArtistListMode::TrackArtists: + parameters.setLinkType(TrackArtistLinkType::Artist); + break; + } + + Response::Node* currentIndexNode {}; + char currentIndex{}; + + Response::Node* unknownIndexNode {}; + auto getOrCreateUnknownIndexNode {[&] + { + if (!unknownIndexNode) + { + unknownIndexNode = &artistsNode.createArrayChild("index"); + unknownIndexNode->setAttribute("name", "?"); + } + + return unknownIndexNode; + }}; + + auto getOrCreateIndexNode {[&](char first) + { + if (!currentIndexNode || currentIndex != first) + { + currentIndexNode = &artistsNode.createArrayChild("index"); + currentIndexNode->setAttribute("name", std::string {first}); + currentIndex = first; + } + + return currentIndexNode; + }}; + + const RangeResults artists {Artist::find(context.dbSession, parameters)}; + for (const ArtistId artistId : artists.results) + { + const Artist::pointer artist {Artist::find(context.dbSession, artistId)}; + const std::string& sortName {artist->getSortName()}; + + Response::Node* indexNode{}; + if (sortName.empty() || !std::isalpha(sortName[0])) + indexNode = getOrCreateUnknownIndexNode(); + else + indexNode = getOrCreateIndexNode(std::toupper(sortName[0])); + + indexNode->addArrayChild("artist", artistToResponseNode(user, artist, id3)); + } + + return response; +} + +static +Response +handleGetIndexesRequest(RequestContext& context) +{ + return handleGetArtistsRequestCommon(context, false /* no id3 */); +} + static Response handleGetGenresRequest(RequestContext& context) @@ -1103,45 +1141,9 @@ handleGetGenresRequest(RequestContext& context) static Response -handleGetIndexesRequest(RequestContext& context) +handleGetArtistsRequest(RequestContext& context) { - Response response {Response::createOkResponse(context.serverProtocolVersion)}; - - Response::Node& artistsNode {response.createNode("indexes")}; - artistsNode.setAttribute("ignoredArticles", ""); - artistsNode.setAttribute("lastModified", reportedDummyDateULong); - - Response::Node& indexNode {artistsNode.createArrayChild("index")}; - indexNode.setAttribute("name", "?"); - - auto transaction {context.dbSession.createSharedTransaction()}; - - User::pointer user {User::find(context.dbSession, context.userId)}; - if (!user) - throw UserNotAuthorizedError {}; - - Artist::FindParameters parameters; - parameters.setSortMethod(ArtistSortMethod::BySortName); - switch (user->getSubsonicArtistListMode()) - { - case SubsonicArtistListMode::AllArtists: - break; - case SubsonicArtistListMode::ReleaseArtists: - parameters.setLinkType(TrackArtistLinkType::ReleaseArtist); - break; - case SubsonicArtistListMode::TrackArtists: - parameters.setLinkType(TrackArtistLinkType::Artist); - break; - } - - const RangeResults artists {Artist::find(context.dbSession, parameters)}; - for (const ArtistId artistId : artists.results) - { - const Artist::pointer artist {Artist::find(context.dbSession, artistId)}; - indexNode.addArrayChild("artist", artistToResponseNode(user, artist, false /* no id3 */)); - } - - return response; + return handleGetArtistsRequestCommon(context, true /* id3 */); } static @@ -1501,38 +1503,14 @@ handleStarRequest(RequestContext& context) { StarParameters params {getStarParameters(context.parameters)}; - auto transaction {context.dbSession.createSharedTransaction()}; - - User::pointer user {User::find(context.dbSession, context.userId)}; - if (!user) - throw UserNotAuthorizedError {}; - for (const ArtistId id : params.artistIds) - { - Artist::pointer artist {Artist::find(context.dbSession, id)}; - if (!artist) - continue; - - Service::get()->star(user->getId(), artist->getId()); - } + Service::get()->star(context.userId, id); for (const ReleaseId id : params.releaseIds) - { - Release::pointer release {Release::find(context.dbSession, id)}; - if (!release) - continue; - - Service::get()->star(user->getId(), release->getId()); - } + Service::get()->star(context.userId, id); for (const TrackId id : params.trackIds) - { - Track::pointer track {Track::find(context.dbSession, id)}; - if (!track) - continue; - - Service::get()->star(user->getId(), track->getId()); - } + Service::get()->star(context.userId, id); return Response::createOkResponse(context.serverProtocolVersion); } @@ -1557,33 +1535,14 @@ handleUnstarRequest(RequestContext& context) { StarParameters params {getStarParameters(context.parameters)}; - auto transaction {context.dbSession.createSharedTransaction()}; - - User::pointer user {User::find(context.dbSession, context.userId)}; - if (!user) - throw RequestedDataNotFoundError {}; - - for (const ArtistId artistId : params.artistIds) - Service::get()->unstar(context.userId, artistId); + for (const ArtistId id : params.artistIds) + Service::get()->unstar(context.userId, id); for (const ReleaseId id : params.releaseIds) - { - Release::pointer release {Release::find(context.dbSession, id)}; - if (!release) - continue; - - Service::get()->unstar(user->getId(), release->getId()); - } + Service::get()->unstar(context.userId, id); for (const TrackId id : params.trackIds) - { - Track::pointer track {Track::find(context.dbSession, id)}; - if (!track) - continue; - - Service::get()->unstar(user->getId(), track->getId()); - } - + Service::get()->unstar(context.userId, id); return Response::createOkResponse(context.serverProtocolVersion); } diff --git a/src/libs/utils/impl/RecursiveSharedMutex.cpp b/src/libs/utils/impl/RecursiveSharedMutex.cpp index 9dec11de..a763f4b3 100644 --- a/src/libs/utils/impl/RecursiveSharedMutex.cpp +++ b/src/libs/utils/impl/RecursiveSharedMutex.cpp @@ -128,7 +128,7 @@ bool RecursiveSharedMutex::isSharedLocked() { const auto thisThreadId {std::this_thread::get_id()}; - if (_uniqueOwner == thisThreadId ) + if (_uniqueOwner == thisThreadId ) return true; std::scoped_lock lock {_sharedCountMutex};