From 00d6ef57f75168eb947eec74f325b372fd90f04a Mon Sep 17 00:00:00 2001 From: emeric Date: Tue, 23 Jun 2026 23:12:35 +0200 Subject: [PATCH 01/22] Updated readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 16e4499a..2270e3bf 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ A [demo instance](http://lms-demo.poupon.dev) is available. Note the administrat * [ListenBrainz](https://listenbrainz.org) support for: * Scrobbling and synchronizing listens * Synchronizing 'love' feedbacks +* [Last.fm](https://www.last.fm) support for scrobbling listens * Recommendation engine * Multi-library support * ReplayGain support From 2fe4296fa537343d0c4b855e6601b4917c964f27 Mon Sep 17 00:00:00 2001 From: emeric Date: Sat, 27 Jun 2026 09:55:24 +0200 Subject: [PATCH 02/22] Added a sentinel when UI limit is hit + a message when nothing found, fixes #358 --- approot/messages.xml | 2 + approot/messages_es.xml | 2 + approot/messages_fr.xml | 2 + approot/messages_it.xml | 2 + approot/messages_pl.xml | 2 + approot/messages_zh.xml | 2 + approot/misc.xml | 1 + src/libs/database/impl/Utils.hpp | 54 +- src/libs/database/impl/objects/Artist.cpp | 19 +- src/libs/database/impl/objects/Cluster.cpp | 14 +- src/libs/database/impl/objects/Directory.cpp | 8 +- src/libs/database/impl/objects/Genre.cpp | 6 +- src/libs/database/impl/objects/Grouping.cpp | 6 +- src/libs/database/impl/objects/Image.cpp | 2 +- src/libs/database/impl/objects/Language.cpp | 6 +- src/libs/database/impl/objects/Listen.cpp | 126 +++- src/libs/database/impl/objects/Medium.cpp | 2 +- src/libs/database/impl/objects/Mood.cpp | 6 +- src/libs/database/impl/objects/Release.cpp | 19 +- .../database/impl/objects/StarredTrack.cpp | 2 +- src/libs/database/impl/objects/Track.cpp | 21 +- .../database/impl/objects/TrackBookmark.cpp | 2 +- .../impl/objects/TrackEmbeddedImage.cpp | 2 +- src/libs/database/impl/objects/TrackList.cpp | 8 +- .../database/impl/objects/TrackLyrics.cpp | 2 +- .../impl/objects/TrackMusicNNEmbeddings.cpp | 2 +- src/libs/database/impl/objects/User.cpp | 2 +- src/libs/database/include/database/Types.hpp | 36 -- .../include/database/objects/Artist.hpp | 16 +- .../include/database/objects/Cluster.hpp | 14 +- .../include/database/objects/Directory.hpp | 8 +- .../include/database/objects/Genre.hpp | 6 +- .../include/database/objects/Grouping.hpp | 6 +- .../include/database/objects/Image.hpp | 2 +- .../include/database/objects/Language.hpp | 6 +- .../include/database/objects/Listen.hpp | 29 +- .../include/database/objects/Medium.hpp | 2 +- .../include/database/objects/Mood.hpp | 6 +- .../include/database/objects/Release.hpp | 18 +- .../include/database/objects/StarredTrack.hpp | 2 +- .../include/database/objects/Track.hpp | 13 +- .../database/objects/TrackBookmark.hpp | 2 +- .../database/objects/TrackEmbeddedImage.hpp | 2 +- .../include/database/objects/TrackList.hpp | 4 +- .../include/database/objects/TrackLyrics.hpp | 2 +- .../objects/TrackMusicNNEmbeddings.hpp | 2 +- .../include/database/objects/User.hpp | 2 +- src/libs/database/test/Artist.cpp | 229 ++++--- src/libs/database/test/Cluster.cpp | 180 +++--- src/libs/database/test/Common.cpp | 71 --- src/libs/database/test/DatabaseTest.cpp | 18 +- src/libs/database/test/Directory.cpp | 16 +- src/libs/database/test/Genre.cpp | 44 +- src/libs/database/test/Grouping.cpp | 44 +- src/libs/database/test/Image.cpp | 36 +- src/libs/database/test/Language.cpp | 44 +- src/libs/database/test/Listen.cpp | 583 ++++++++++-------- src/libs/database/test/Mood.cpp | 44 +- src/libs/database/test/RatedArtist.cpp | 2 +- src/libs/database/test/RatedRelease.cpp | 2 +- src/libs/database/test/RatedTrack.cpp | 2 +- src/libs/database/test/Release.cpp | 267 ++++---- src/libs/database/test/StarredArtist.cpp | 64 +- src/libs/database/test/StarredRelease.cpp | 64 +- src/libs/database/test/StarredTrack.cpp | 64 +- src/libs/database/test/Track.cpp | 66 +- src/libs/database/test/TrackBookmark.cpp | 4 +- src/libs/database/test/TrackEmbeddedImage.cpp | 10 +- src/libs/database/test/TrackList.cpp | 48 +- .../services/artwork/impl/ArtworkService.cpp | 2 +- .../feedback/impl/FeedbackService.cpp | 18 +- .../listenbrainz/FeedbacksSynchronizer.cpp | 10 +- .../services/feedback/IFeedbackService.hpp | 6 +- .../AudioSimilarityEngine.impl.hpp | 4 +- .../recommendation/impl/tags/TagsEngine.cpp | 4 +- .../steps/ScanStepArtistReconciliation.cpp | 6 +- .../steps/ScanStepCheckForDuplicatedFiles.cpp | 4 +- .../impl/steps/ScanStepComputeGenreStats.cpp | 3 +- .../steps/ScanStepRemoveOrphanedDbEntries.cpp | 8 +- .../steps/ScanStepUpdateLibraryFields.cpp | 8 +- .../scrobbling/impl/ScrobblingService.cpp | 48 -- .../impl/lastfm/ScrobblingsSynchronizer.cpp | 4 +- .../impl/listenbrainz/ListensSynchronizer.cpp | 16 +- .../scrobbling/IScrobblingService.hpp | 6 +- .../impl/endpoints/AlbumSongLists.cpp | 10 +- .../subsonic/impl/endpoints/Bookmarks.cpp | 2 +- src/libs/subsonic/impl/endpoints/Browsing.cpp | 20 +- .../impl/endpoints/MediaRetrieval.cpp | 4 +- .../subsonic/impl/endpoints/Playlists.cpp | 4 +- src/libs/subsonic/impl/responses/Album.cpp | 2 +- src/lms/ui/PlayQueue.cpp | 10 +- src/lms/ui/Utils.cpp | 2 +- .../ui/admin/debug/PcmDecodingBenchmark.cpp | 2 +- .../ui/common/InfiniteScrollingContainer.cpp | 32 +- .../ui/common/InfiniteScrollingContainer.hpp | 8 +- src/lms/ui/explore/ArtistCollector.cpp | 158 ++--- src/lms/ui/explore/ArtistCollector.hpp | 9 +- src/lms/ui/explore/ArtistView.cpp | 6 +- src/lms/ui/explore/ArtistsView.cpp | 15 +- src/lms/ui/explore/ArtistsView.hpp | 2 +- src/lms/ui/explore/DatabaseCollectorBase.cpp | 22 +- src/lms/ui/explore/DatabaseCollectorBase.hpp | 3 +- src/lms/ui/explore/PlayQueueController.cpp | 12 +- src/lms/ui/explore/ReleaseCollector.cpp | 123 ++-- src/lms/ui/explore/ReleaseCollector.hpp | 8 +- src/lms/ui/explore/ReleaseView.cpp | 6 +- src/lms/ui/explore/ReleasesView.cpp | 26 +- src/lms/ui/explore/ReleasesView.hpp | 5 +- src/lms/ui/explore/TrackCollector.cpp | 126 ++-- src/lms/ui/explore/TrackCollector.hpp | 9 +- src/lms/ui/explore/TrackListView.cpp | 9 +- src/lms/ui/explore/TrackListsView.cpp | 4 +- src/lms/ui/explore/TracksView.cpp | 24 +- src/lms/ui/explore/TracksView.hpp | 4 +- src/lms/ui/resource/DownloadResource.cpp | 6 +- .../recommendation/LmsRecommendation.cpp | 14 +- 116 files changed, 1586 insertions(+), 1650 deletions(-) diff --git a/approot/messages.xml b/approot/messages.xml index 146bfdbe..81819ddc 100644 --- a/approot/messages.xml +++ b/approot/messages.xml @@ -14,6 +14,8 @@ Discard Edit This field must be in upper case +Display limit reached — refine your search to see more results +No results found Loading... Login Logout diff --git a/approot/messages_es.xml b/approot/messages_es.xml index 21ba6ad6..53be4490 100644 --- a/approot/messages_es.xml +++ b/approot/messages_es.xml @@ -14,6 +14,8 @@ Descartar Editar Este campo debe estar en mayúsculas +Límite de visualización alcanzado — refine su búsqueda para ver más resultados +No se han encontrado resultados Cargando... Usuario Salir diff --git a/approot/messages_fr.xml b/approot/messages_fr.xml index 44a7f588..69751f6c 100644 --- a/approot/messages_fr.xml +++ b/approot/messages_fr.xml @@ -14,6 +14,8 @@ Annuler Editer Ce champ doit être en majuscule +Limite d'affichage atteinte — affinez votre recherche pour voir plus de résultats +Aucun résultat Chargement... Login Quitter diff --git a/approot/messages_it.xml b/approot/messages_it.xml index 1ec58f23..3ea55b12 100644 --- a/approot/messages_it.xml +++ b/approot/messages_it.xml @@ -14,6 +14,8 @@ Annulla Modifica Questo campo deve essere in maiuscolo +Limite di visualizzazione raggiunto — affina la ricerca per vedere più risultati +Nessun risultato trovato Caricamento... Login Logout diff --git a/approot/messages_pl.xml b/approot/messages_pl.xml index f35671cd..1b4613f1 100644 --- a/approot/messages_pl.xml +++ b/approot/messages_pl.xml @@ -14,6 +14,8 @@ Odrzuć Zmień Wartość musi się zaczynać wielką literą +Osiągnięto limit wyświetlania — doprecyzuj wyszukiwanie, aby zobaczyć więcej wyników +Brak wyników Wczytywanie... Login Wyloguj diff --git a/approot/messages_zh.xml b/approot/messages_zh.xml index c0bc9f44..44cdfa56 100644 --- a/approot/messages_zh.xml +++ b/approot/messages_zh.xml @@ -14,6 +14,8 @@ 撤销 编辑 此字段必须为大写 +已达到显示上限 — 请精简搜索条件以查看更多结果 +未找到结果 加载中... 登陆 注销 diff --git a/approot/misc.xml b/approot/misc.xml index b62f3215..7a87c19a 100644 --- a/approot/misc.xml +++ b/approot/misc.xml @@ -9,6 +9,7 @@ + ${elements} ${loading-indicator} diff --git a/src/libs/database/impl/Utils.hpp b/src/libs/database/impl/Utils.hpp index 3d13303c..838cc39a 100644 --- a/src/libs/database/impl/Utils.hpp +++ b/src/libs/database/impl/Utils.hpp @@ -128,29 +128,10 @@ namespace lms::db::utils } template - RangeResults execRangeQuery(Query& query, const std::optional range) + std::vector execRangeQuery(Query& query, const std::optional range) { - RangeResults res; - - if (range) - { - res.range.offset = range->offset; - applyRange(query, Range{ range->offset, range->size + 1 }); - - res.results.reserve(range->size); - } - - // TODO optim useless last copy - res.results = utils::fetchQueryResults(query); - if (range && (res.results.size() == range->size + 1)) - { - res.moreResults = true; - res.results.pop_back(); - } - - res.range.size = res.results.size(); - - return res; + applyRange(query, range); + return utils::fetchQueryResults(query); } template @@ -162,35 +143,6 @@ namespace lms::db::utils forEachQueryResult(query, std::forward(func)); } - template - void forEachQueryRangeResult(Query& query, std::optional range, bool& moreResults, UnaryFunc&& func) - { - using ResultType = typename QueryResultType::type; - - if (range) - applyRange(query, Range{ range->offset, range->size + 1 }); - - moreResults = false; - - std::size_t count{}; - ScopedQueryProfiler queryProfiler{ query }; - const auto collection{ query.resultList() }; - auto it{ fetchFirstResult(collection) }; - while (it != collection.end()) - { - if (range && (count++ == static_cast(range->size))) - { - moreResults = true; - break; - } - - queryProfiler.suspend(); - func(*it); - queryProfiler.resume(); - fetchNextResult(it); - } - } - template void executeCommand(Wt::Dbo::Session& session, std::string_view command, const Args&... args) { diff --git a/src/libs/database/impl/objects/Artist.cpp b/src/libs/database/impl/objects/Artist.cpp index ea9e6b48..ffa512f8 100644 --- a/src/libs/database/impl/objects/Artist.cpp +++ b/src/libs/database/impl/objects/Artist.cpp @@ -135,14 +135,13 @@ namespace lms::db if (params.starringUser.isValid()) { - assert(params.feedbackBackend); query.join("starred_artist s_a ON s_a.artist_id = a.id") + .join("user u ON u.id = s_a.user_id") .where("s_a.user_id = ?") .bind(params.starringUser) - .where("s_a.backend = ?") - .bind(*params.feedbackBackend) .where("s_a.sync_state <> ?") - .bind(SyncState::PendingRemove); + .bind(SyncState::PendingRemove) + .where("s_a.backend = u.feedback_backend"); } if (params.filters.clusters.size() == 1) @@ -323,7 +322,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->query>("SELECT a FROM artist a").where("a.id = ?").bind(id)); } - RangeResults Artist::findIds(Session& session, const FindParameters& params) + std::vector Artist::findIds(Session& session, const FindParameters& params) { session.checkReadTransaction(); @@ -331,7 +330,7 @@ namespace lms::db return utils::execRangeQuery(query, params.range); } - RangeResults Artist::find(Session& session, const FindParameters& params) + std::vector Artist::find(Session& session, const FindParameters& params) { session.checkReadTransaction(); @@ -357,7 +356,7 @@ namespace lms::db return IdRange{ .first = std::get<0>(res), .last = std::get<1>(res) }; } - RangeResults Artist::findOrphanIds(Session& session, std::optional range) + std::vector Artist::findOrphanIds(Session& session, std::optional range) { // TODO extend with release artists session.checkReadTransaction(); @@ -388,7 +387,7 @@ AND NOT EXISTS ( return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT 1 FROM artist").where("id = ?").bind(id)) == 1; } - RangeResults Artist::findWithMBIDNameVariants(Session& session, ArtistId& lastRetrievedArtist, std::optional range) + std::vector Artist::findWithMBIDNameVariants(Session& session, ArtistId& lastRetrievedArtist, std::optional range) { session.checkReadTransaction(); @@ -407,8 +406,8 @@ AND NOT EXISTS ( auto results{ utils::execRangeQuery(query, range) }; - if (!results.results.empty()) - lastRetrievedArtist = results.results.back()->getId(); + if (!results.empty()) + lastRetrievedArtist = results.back()->getId(); return results; } diff --git a/src/libs/database/impl/objects/Cluster.cpp b/src/libs/database/impl/objects/Cluster.cpp index b574e798..2d57d9a4 100644 --- a/src/libs/database/impl/objects/Cluster.cpp +++ b/src/libs/database/impl/objects/Cluster.cpp @@ -130,7 +130,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM cluster")); } - RangeResults Cluster::findIds(Session& session, const FindParameters& params) + std::vector Cluster::findIds(Session& session, const FindParameters& params) { session.checkReadTransaction(); auto query{ createQuery(session, params) }; @@ -138,7 +138,7 @@ namespace lms::db return utils::execRangeQuery(query, params.range); } - RangeResults Cluster::find(Session& session, const FindParameters& params) + std::vector Cluster::find(Session& session, const FindParameters& params) { session.checkReadTransaction(); auto query{ createQuery>(session, params) }; @@ -154,7 +154,7 @@ namespace lms::db return utils::forEachQueryResult(query, _func); } - RangeResults Cluster::findOrphanIds(Session& session, std::optional range) + std::vector Cluster::findOrphanIds(Session& session, std::optional range) { session.checkReadTransaction(); auto query{ session.getDboSession()->query("SELECT DISTINCT c.id FROM cluster c WHERE NOT EXISTS(SELECT 1 FROM track_cluster t_c WHERE t_c.cluster_id = c.id)") }; @@ -188,7 +188,7 @@ namespace lms::db _tracks.insert(getDboPtr(track)); } - RangeResults Cluster::getTracks(std::optional range) const + std::vector Cluster::getTracks(std::optional range) const { assert(session()); @@ -217,7 +217,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM cluster_type")); } - RangeResults ClusterType::findOrphanIds(Session& session, std::optional range) + std::vector ClusterType::findOrphanIds(Session& session, std::optional range) { session.checkReadTransaction(); @@ -229,7 +229,7 @@ namespace lms::db return utils::execRangeQuery(query, range); } - RangeResults ClusterType::findUsed(Session& session, std::optional range) + std::vector ClusterType::findUsed(Session& session, std::optional range) { session.checkReadTransaction(); @@ -263,7 +263,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->find().where("id = ?").bind(id)); } - RangeResults ClusterType::findIds(Session& session, std::optional range) + std::vector ClusterType::findIds(Session& session, std::optional range) { session.checkReadTransaction(); diff --git a/src/libs/database/impl/objects/Directory.cpp b/src/libs/database/impl/objects/Directory.cpp index 47be8b9a..822ce273 100644 --- a/src/libs/database/impl/objects/Directory.cpp +++ b/src/libs/database/impl/objects/Directory.cpp @@ -173,7 +173,7 @@ namespace lms::db }); } - RangeResults Directory::find(Session& session, const FindParameters& params) + std::vector Directory::find(Session& session, const FindParameters& params) { auto query{ createQuery(session, params) }; return utils::execRangeQuery(query, params.range); @@ -187,7 +187,7 @@ namespace lms::db }); } - RangeResults Directory::findOrphanIds(Session& session, std::optional range) + std::vector Directory::findOrphanIds(Session& session, std::optional range) { session.checkReadTransaction(); @@ -208,7 +208,7 @@ namespace lms::db return utils::execRangeQuery(query, range); } - RangeResults Directory::findMismatchedLibrary(Session& session, std::optional range, const std::filesystem::path& rootPath, MediaLibraryId expectedLibraryId) + std::vector Directory::findMismatchedLibrary(Session& session, std::optional range, const std::filesystem::path& rootPath, MediaLibraryId expectedLibraryId) { session.checkReadTransaction(); @@ -219,7 +219,7 @@ namespace lms::db return utils::execRangeQuery(query, range); } - RangeResults Directory::findRootDirectories(Session& session, std::optional range) + std::vector Directory::findRootDirectories(Session& session, std::optional range) { auto query{ session.getDboSession()->query>("SELECT d from directory d").where("d.parent_directory_id IS NULL") }; return utils::execRangeQuery(query, range); diff --git a/src/libs/database/impl/objects/Genre.cpp b/src/libs/database/impl/objects/Genre.cpp index d2149ad3..8f546257 100644 --- a/src/libs/database/impl/objects/Genre.cpp +++ b/src/libs/database/impl/objects/Genre.cpp @@ -128,14 +128,14 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM genre")); } - RangeResults Genre::findIds(Session& session, const FindParameters& params) + std::vector Genre::findIds(Session& session, const FindParameters& params) { session.checkReadTransaction(); auto query{ createQuery(session, params) }; return utils::execRangeQuery(query, params.range); } - RangeResults Genre::find(Session& session, const FindParameters& params) + std::vector Genre::find(Session& session, const FindParameters& params) { session.checkReadTransaction(); auto query{ createQuery>(session, params) }; @@ -165,7 +165,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->find().where("name = ?").bind(name)); } - RangeResults Genre::findOrphanIds(Session& session, std::optional range) + std::vector Genre::findOrphanIds(Session& session, std::optional range) { session.checkReadTransaction(); auto query{ session.getDboSession()->query("SELECT g.id FROM genre g WHERE NOT EXISTS (SELECT 1 FROM track_genre t_g WHERE t_g.genre_id = g.id)") }; diff --git a/src/libs/database/impl/objects/Grouping.cpp b/src/libs/database/impl/objects/Grouping.cpp index 96f6683a..80590c5f 100644 --- a/src/libs/database/impl/objects/Grouping.cpp +++ b/src/libs/database/impl/objects/Grouping.cpp @@ -128,14 +128,14 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM grouping")); } - RangeResults Grouping::findIds(Session& session, const FindParameters& params) + std::vector Grouping::findIds(Session& session, const FindParameters& params) { session.checkReadTransaction(); auto query{ createQuery(session, params) }; return utils::execRangeQuery(query, params.range); } - RangeResults Grouping::find(Session& session, const FindParameters& params) + std::vector Grouping::find(Session& session, const FindParameters& params) { session.checkReadTransaction(); auto query{ createQuery>(session, params) }; @@ -165,7 +165,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->find().where("name = ?").bind(name)); } - RangeResults Grouping::findOrphanIds(Session& session, std::optional range) + std::vector Grouping::findOrphanIds(Session& session, std::optional range) { session.checkReadTransaction(); auto query{ session.getDboSession()->query("SELECT g.id FROM grouping g WHERE NOT EXISTS (SELECT 1 FROM track_grouping t_gr WHERE t_gr.grouping_id = g.id)") }; diff --git a/src/libs/database/impl/objects/Image.cpp b/src/libs/database/impl/objects/Image.cpp index 152b076a..dde98c30 100644 --- a/src/libs/database/impl/objects/Image.cpp +++ b/src/libs/database/impl/objects/Image.cpp @@ -105,7 +105,7 @@ namespace lms::db }); } - RangeResults Image::find(Session& session, const FindParameters& params) + std::vector Image::find(Session& session, const FindParameters& params) { session.checkReadTransaction(); diff --git a/src/libs/database/impl/objects/Language.cpp b/src/libs/database/impl/objects/Language.cpp index 9a3698c2..00230538 100644 --- a/src/libs/database/impl/objects/Language.cpp +++ b/src/libs/database/impl/objects/Language.cpp @@ -128,14 +128,14 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM language")); } - RangeResults Language::findIds(Session& session, const FindParameters& params) + std::vector Language::findIds(Session& session, const FindParameters& params) { session.checkReadTransaction(); auto query{ createQuery(session, params) }; return utils::execRangeQuery(query, params.range); } - RangeResults Language::find(Session& session, const FindParameters& params) + std::vector Language::find(Session& session, const FindParameters& params) { session.checkReadTransaction(); auto query{ createQuery>(session, params) }; @@ -165,7 +165,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->find().where("name = ?").bind(name)); } - RangeResults Language::findOrphanIds(Session& session, std::optional range) + std::vector Language::findOrphanIds(Session& session, std::optional range) { session.checkReadTransaction(); auto query{ session.getDboSession()->query("SELECT l.id FROM language l WHERE NOT EXISTS (SELECT 1 FROM track_language t_l WHERE t_l.language_id = l.id)") }; diff --git a/src/libs/database/impl/objects/Listen.cpp b/src/libs/database/impl/objects/Listen.cpp index 1736dd90..5370ddc7 100644 --- a/src/libs/database/impl/objects/Listen.cpp +++ b/src/libs/database/impl/objects/Listen.cpp @@ -23,10 +23,12 @@ #include #include "database/Session.hpp" +#include "database/objects/Artist.hpp" #include "database/objects/Genre.hpp" #include "database/objects/Grouping.hpp" #include "database/objects/Language.hpp" #include "database/objects/Mood.hpp" +#include "database/objects/Release.hpp" #include "database/objects/Track.hpp" #include "database/objects/User.hpp" @@ -46,10 +48,12 @@ namespace lms::db auto query{ session.getDboSession()->query("SELECT a.id from artist a").join("track_artist_link t_a_l ON t_a_l.artist_id = a.id").join("listen l ON l.track_id = t_a_l.track_id") }; if (params.user.isValid()) - query.where("l.user_id = ?").bind(params.user); - - if (params.backend) - query.where("l.backend = ?").bind(*params.backend); + { + query.join("user u ON u.id = l.user_id") + .where("l.user_id = ?") + .bind(params.user) + .where("l.backend = u.scrobbling_backend"); + } assert(!params.artist.isValid()); // poor check @@ -161,10 +165,12 @@ namespace lms::db auto query{ session.getDboSession()->query("SELECT r.id from release r").join("track t ON t.release_id = r.id").join("listen l ON l.track_id = t.id") }; if (params.user.isValid()) - query.where("l.user_id = ?").bind(params.user); - - if (params.backend) - query.where("l.backend = ?").bind(*params.backend); + { + query.join("user u ON u.id = l.user_id") + .where("l.user_id = ?") + .bind(params.user) + .where("l.backend = u.scrobbling_backend"); + } if (params.artist.isValid()) { @@ -244,10 +250,12 @@ namespace lms::db auto query{ session.getDboSession()->query("SELECT t.id from track t").join("listen l ON l.track_id = t.id") }; if (params.user.isValid()) - query.where("l.user_id = ?").bind(params.user); - - if (params.backend) - query.where("l.backend = ?").bind(*params.backend); + { + query.join("user u ON u.id = l.user_id") + .where("l.user_id = ?") + .bind(params.user) + .where("l.backend = u.scrobbling_backend"); + } if (params.artist.isValid()) { @@ -348,7 +356,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->query>("SELECT l from listen l").where("l.id = ?").bind(id)); } - RangeResults Listen::find(Session& session, const FindParameters& parameters) + std::vector Listen::find(Session& session, const FindParameters& parameters) { session.checkReadTransaction(); @@ -373,39 +381,88 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->find().where("user_id = ?").bind(userId).where("track_id = ?").bind(trackId).where("backend = ?").bind(backend).where("date_time = ?").bind(Wt::WDateTime::fromTime_t(dateTime.toTime_t()))); } - RangeResults Listen::getTopArtists(Session& session, const ArtistStatsFindParameters& params) + std::vector Listen::getTopArtists(Session& session, const ArtistStatsFindParameters& params) { session.checkReadTransaction(); - auto query{ createArtistsQuery(session, params) }; - - auto collection{ query - .orderBy("COUNT(a.id) DESC") - .groupBy("a.id") }; - + auto query{ createArtistsQuery(session, params).orderBy("COUNT(a.id) DESC").groupBy("a.id") }; return utils::execRangeQuery(query, params.range); } - RangeResults Listen::getTopReleases(Session& session, const StatsFindParameters& params) + std::vector Listen::getTopReleases(Session& session, const StatsFindParameters& params) + { + session.checkReadTransaction(); + auto query{ createReleasesQuery(session, params).orderBy("COUNT(r.id) DESC").groupBy("r.id") }; + return utils::execRangeQuery(query, params.range); + } + + std::vector Listen::getTopTracks(Session& session, const StatsFindParameters& params) + { + session.checkReadTransaction(); + auto query{ createTracksQuery(session, params).orderBy("COUNT(t.id) DESC").groupBy("t.id") }; + return utils::execRangeQuery(query, params.range); + } + + std::vector Listen::getRecentArtists(Session& session, const ArtistStatsFindParameters& params) + { + session.checkReadTransaction(); + auto query{ createArtistsQuery(session, params).groupBy("a.id").having("l.date_time = MAX(l.date_time)").orderBy("l.date_time DESC") }; + return utils::execRangeQuery(query, params.range); + } + + std::vector Listen::getRecentReleases(Session& session, const StatsFindParameters& params) + { + session.checkReadTransaction(); + auto query{ createReleasesQuery(session, params).groupBy("r.id").having("l.date_time = MAX(l.date_time)").orderBy("l.date_time DESC") }; + return utils::execRangeQuery(query, params.range); + } + + std::vector Listen::getRecentTracks(Session& session, const StatsFindParameters& params) + { + session.checkReadTransaction(); + auto query{ createTracksQuery(session, params).groupBy("t.id").having("l.date_time = MAX(l.date_time)").orderBy("l.date_time DESC") }; + return utils::execRangeQuery(query, params.range); + } + + void Listen::getTopArtists(Session& session, const ArtistStatsFindParameters& params, const std::function&)>& func) + { + session.checkReadTransaction(); + auto query{ createArtistsQuery(session, params) + .orderBy("COUNT(a.id) DESC") + .groupBy("a.id") }; + + utils::forEachQueryRangeResult(query, params.range, [&](const ArtistId& id) { + if (const auto artist{ Artist::find(session, id) }) + func(artist); + }); + } + + void Listen::getTopReleases(Session& session, const StatsFindParameters& params, const std::function&)>& func) { session.checkReadTransaction(); auto query{ createReleasesQuery(session, params) .orderBy("COUNT(r.id) DESC") .groupBy("r.id") }; - return utils::execRangeQuery(query, params.range); + utils::forEachQueryRangeResult(query, params.range, [&](const ReleaseId& id) { + if (const auto release{ Release::find(session, id) }) + func(release); + }); } - RangeResults Listen::getTopTracks(Session& session, const StatsFindParameters& params) + void Listen::getTopTracks(Session& session, const StatsFindParameters& params, const std::function&)>& func) { session.checkReadTransaction(); auto query{ createTracksQuery(session, params) .orderBy("COUNT(t.id) DESC") .groupBy("t.id") }; - return utils::execRangeQuery(query, params.range); + utils::forEachQueryRangeResult(query, params.range, [&](const TrackId& id) { + if (const auto track{ Track::find(session, id) }) + func(track); + }); } - RangeResults Listen::getRecentArtists(Session& session, const ArtistStatsFindParameters& params) + void Listen::getRecentArtists(Session& session, const ArtistStatsFindParameters& params, const std::function&)>& func) { session.checkReadTransaction(); auto query{ createArtistsQuery(session, params) @@ -413,10 +470,13 @@ namespace lms::db .having("l.date_time = MAX(l.date_time)") .orderBy("l.date_time DESC") }; - return utils::execRangeQuery(query, params.range); + utils::forEachQueryRangeResult(query, params.range, [&](const ArtistId& id) { + if (const auto artist{ Artist::find(session, id) }) + func(artist); + }); } - RangeResults Listen::getRecentReleases(Session& session, const StatsFindParameters& params) + void Listen::getRecentReleases(Session& session, const StatsFindParameters& params, const std::function&)>& func) { session.checkReadTransaction(); auto query{ createReleasesQuery(session, params) @@ -424,10 +484,13 @@ namespace lms::db .having("l.date_time = MAX(l.date_time)") .orderBy("l.date_time DESC") }; - return utils::execRangeQuery(query, params.range); + utils::forEachQueryRangeResult(query, params.range, [&](const ReleaseId& id) { + if (const auto release{ Release::find(session, id) }) + func(release); + }); } - RangeResults Listen::getRecentTracks(Session& session, const StatsFindParameters& params) + void Listen::getRecentTracks(Session& session, const StatsFindParameters& params, const std::function&)>& func) { session.checkReadTransaction(); auto query{ createTracksQuery(session, params) @@ -435,7 +498,10 @@ namespace lms::db .having("l.date_time = MAX(l.date_time)") .orderBy("l.date_time DESC") }; - return utils::execRangeQuery(query, params.range); + utils::forEachQueryRangeResult(query, params.range, [&](const TrackId& id) { + if (const auto track{ Track::find(session, id) }) + func(track); + }); } std::size_t Listen::getCount(Session& session, UserId userId, TrackId trackId) diff --git a/src/libs/database/impl/objects/Medium.cpp b/src/libs/database/impl/objects/Medium.cpp index b98fbb72..4c2cd5ac 100644 --- a/src/libs/database/impl/objects/Medium.cpp +++ b/src/libs/database/impl/objects/Medium.cpp @@ -110,7 +110,7 @@ namespace lms::db return IdRange{ .first = std::get<0>(res), .last = std::get<1>(res) }; } - RangeResults Medium::findOrphanIds(Session& session, std::optional range) + std::vector Medium::findOrphanIds(Session& session, std::optional range) { session.checkReadTransaction(); diff --git a/src/libs/database/impl/objects/Mood.cpp b/src/libs/database/impl/objects/Mood.cpp index 18430ba4..c2e5d478 100644 --- a/src/libs/database/impl/objects/Mood.cpp +++ b/src/libs/database/impl/objects/Mood.cpp @@ -128,14 +128,14 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM mood")); } - RangeResults Mood::findIds(Session& session, const FindParameters& params) + std::vector Mood::findIds(Session& session, const FindParameters& params) { session.checkReadTransaction(); auto query{ createQuery(session, params) }; return utils::execRangeQuery(query, params.range); } - RangeResults Mood::find(Session& session, const FindParameters& params) + std::vector Mood::find(Session& session, const FindParameters& params) { session.checkReadTransaction(); auto query{ createQuery>(session, params) }; @@ -165,7 +165,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->find().where("name = ?").bind(name)); } - RangeResults Mood::findOrphanIds(Session& session, std::optional range) + std::vector Mood::findOrphanIds(Session& session, std::optional range) { session.checkReadTransaction(); auto query{ session.getDboSession()->query("SELECT m.id FROM mood m WHERE NOT EXISTS (SELECT 1 FROM track_mood t_m WHERE t_m.mood_id = m.id)") }; diff --git a/src/libs/database/impl/objects/Release.cpp b/src/libs/database/impl/objects/Release.cpp index 71c5f402..62202405 100644 --- a/src/libs/database/impl/objects/Release.cpp +++ b/src/libs/database/impl/objects/Release.cpp @@ -150,14 +150,13 @@ namespace lms::db if (params.starringUser.isValid()) { - assert(params.feedbackBackend); query.join("starred_release s_r ON s_r.release_id = r.id") + .join("user u ON u.id = s_r.user_id") .where("s_r.user_id = ?") .bind(params.starringUser) - .where("s_r.backend = ?") - .bind(*params.feedbackBackend) .where("s_r.sync_state <> ?") - .bind(SyncState::PendingRemove); + .bind(SyncState::PendingRemove) + .where("s_r.backend = u.feedback_backend"); } if (params.artist.isValid()) @@ -356,7 +355,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->query>("SELECT c from country c").where("c.name = ?").bind(name)); } - RangeResults Country::findOrphanIds(Session& session, std::optional range) + std::vector Country::findOrphanIds(Session& session, std::optional range) { session.checkReadTransaction(); @@ -418,7 +417,7 @@ namespace lms::db }); } - RangeResults Label::findOrphanIds(Session& session, std::optional range) + std::vector Label::findOrphanIds(Session& session, std::optional range) { session.checkReadTransaction(); @@ -480,7 +479,7 @@ namespace lms::db }); } - RangeResults ReleaseType::findOrphanIds(Session& session, std::optional range) + std::vector ReleaseType::findOrphanIds(Session& session, std::optional range) { session.checkReadTransaction(); @@ -527,7 +526,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM release")); } - RangeResults Release::findOrphanIds(Session& session, std::optional range) + std::vector Release::findOrphanIds(Session& session, std::optional range) { session.checkReadTransaction(); @@ -574,7 +573,7 @@ namespace lms::db return IdRange{ .first = std::get<0>(res), .last = std::get<1>(res) }; } - RangeResults Release::find(Session& session, const FindParameters& params) + std::vector Release::find(Session& session, const FindParameters& params) { session.checkReadTransaction(); @@ -590,7 +589,7 @@ namespace lms::db utils::forEachQueryRangeResult(query, params.range, func); } - RangeResults Release::findIds(Session& session, const FindParameters& params) + std::vector Release::findIds(Session& session, const FindParameters& params) { session.checkReadTransaction(); diff --git a/src/libs/database/impl/objects/StarredTrack.cpp b/src/libs/database/impl/objects/StarredTrack.cpp index ed6ebecf..c21b2682 100644 --- a/src/libs/database/impl/objects/StarredTrack.cpp +++ b/src/libs/database/impl/objects/StarredTrack.cpp @@ -78,7 +78,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT 1 from starred_track").where("track_id = ?").bind(trackId).where("user_id = ?").bind(userId).where("backend = ?").bind(backend)); } - RangeResults StarredTrack::find(Session& session, const FindParameters& params) + std::vector StarredTrack::find(Session& session, const FindParameters& params) { session.checkReadTransaction(); diff --git a/src/libs/database/impl/objects/Track.cpp b/src/libs/database/impl/objects/Track.cpp index 2e95d3ce..1b01fd72 100644 --- a/src/libs/database/impl/objects/Track.cpp +++ b/src/libs/database/impl/objects/Track.cpp @@ -77,14 +77,13 @@ namespace lms::db if (params.starringUser.isValid()) { - assert(params.feedbackBackend); query.join("starred_track s_t ON s_t.track_id = t.id") + .join("user u ON u.id = s_t.user_id") .where("s_t.user_id = ?") .bind(params.starringUser) - .where("s_t.backend = ?") - .bind(*params.feedbackBackend) .where("s_t.sync_state <> ?") - .bind(SyncState::PendingRemove); + .bind(SyncState::PendingRemove) + .where("s_t.backend = u.feedback_backend"); } if (params.filters.clusters.size() == 1) @@ -435,7 +434,7 @@ namespace lms::db return utils::fetchQueryResults(session.getDboSession()->query>("SELECT t from track t").where("t.recording_mbid = ?").bind(mbid)); } - RangeResults Track::findIdsTrackMBIDDuplicates(Session& session, std::optional range) + std::vector Track::findIdsTrackMBIDDuplicates(Session& session, std::optional range) { session.checkReadTransaction(); @@ -564,7 +563,7 @@ namespace lms::db return _preferredMediaArtwork.id(); } - RangeResults Track::findIds(Session& session, const FindParameters& parameters) + std::vector Track::findIds(Session& session, const FindParameters& parameters) { session.checkReadTransaction(); @@ -572,7 +571,7 @@ namespace lms::db return utils::execRangeQuery(query, parameters.range); } - RangeResults Track::find(Session& session, const FindParameters& parameters) + std::vector Track::find(Session& session, const FindParameters& parameters) { session.checkReadTransaction(); @@ -588,14 +587,6 @@ namespace lms::db utils::forEachQueryRangeResult(query, params.range, func); } - void Track::find(Session& session, const FindParameters& params, bool& moreResults, const std::function& func) - { - session.checkReadTransaction(); - - auto query{ createQuery>(session, params) }; - utils::forEachQueryRangeResult(query, params.range, moreResults, func); - } - std::size_t Track::getCount(Session& session, const FindParameters& params) { session.checkReadTransaction(); diff --git a/src/libs/database/impl/objects/TrackBookmark.cpp b/src/libs/database/impl/objects/TrackBookmark.cpp index 7da5f4fc..5ca7f1a5 100644 --- a/src/libs/database/impl/objects/TrackBookmark.cpp +++ b/src/libs/database/impl/objects/TrackBookmark.cpp @@ -54,7 +54,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM track_bookmark")); } - RangeResults TrackBookmark::find(Session& session, UserId userId, std::optional range) + std::vector TrackBookmark::find(Session& session, UserId userId, std::optional range) { session.checkReadTransaction(); diff --git a/src/libs/database/impl/objects/TrackEmbeddedImage.cpp b/src/libs/database/impl/objects/TrackEmbeddedImage.cpp index 5a75f034..c800afdc 100644 --- a/src/libs/database/impl/objects/TrackEmbeddedImage.cpp +++ b/src/libs/database/impl/objects/TrackEmbeddedImage.cpp @@ -150,7 +150,7 @@ namespace lms::db return utils::fetchQuerySingleResult(query); } - RangeResults TrackEmbeddedImage::findOrphanIds(Session& session, std::optional range) + std::vector TrackEmbeddedImage::findOrphanIds(Session& session, std::optional range) { session.checkReadTransaction(); diff --git a/src/libs/database/impl/objects/TrackList.cpp b/src/libs/database/impl/objects/TrackList.cpp index bfdf6b5a..486aa5b9 100644 --- a/src/libs/database/impl/objects/TrackList.cpp +++ b/src/libs/database/impl/objects/TrackList.cpp @@ -182,7 +182,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->query>("select t_l from tracklist t_l").where("t_l.name = ?").bind(name).where("t_l.type = ?").bind(type).where("t_l.user_id = ?").bind(userId)); } - RangeResults TrackList::find(Session& session, const FindParameters& params) + std::vector TrackList::find(Session& session, const FindParameters& params) { session.checkReadTransaction(); auto query{ createQuery(session, params) }; @@ -218,13 +218,13 @@ namespace lms::db TrackListEntry::pointer res; auto entries = getEntries(Range{ pos, 1 }); - if (!entries.results.empty()) - res = entries.results.front(); + if (!entries.empty()) + res = entries.front(); return res; } - RangeResults> TrackList::getEntries(std::optional range) const + std::vector> TrackList::getEntries(std::optional range) const { assert(session()); diff --git a/src/libs/database/impl/objects/TrackLyrics.cpp b/src/libs/database/impl/objects/TrackLyrics.cpp index 666492a2..59576066 100644 --- a/src/libs/database/impl/objects/TrackLyrics.cpp +++ b/src/libs/database/impl/objects/TrackLyrics.cpp @@ -121,7 +121,7 @@ namespace lms::db }); } - RangeResults TrackLyrics::findOrphanIds(Session& session, std::optional range) + std::vector TrackLyrics::findOrphanIds(Session& session, std::optional range) { session.checkReadTransaction(); diff --git a/src/libs/database/impl/objects/TrackMusicNNEmbeddings.cpp b/src/libs/database/impl/objects/TrackMusicNNEmbeddings.cpp index 214afc43..a9c2a153 100644 --- a/src/libs/database/impl/objects/TrackMusicNNEmbeddings.cpp +++ b/src/libs/database/impl/objects/TrackMusicNNEmbeddings.cpp @@ -66,7 +66,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->find().where("track_id = ?").bind(trackId)); } - RangeResults TrackMusicNNEmbeddings::find(Session& session, std::optional range) + std::vector TrackMusicNNEmbeddings::find(Session& session, std::optional range) { session.checkReadTransaction(); diff --git a/src/libs/database/impl/objects/User.cpp b/src/libs/database/impl/objects/User.cpp index 1de617f3..050a5a68 100644 --- a/src/libs/database/impl/objects/User.cpp +++ b/src/libs/database/impl/objects/User.cpp @@ -61,7 +61,7 @@ namespace lms::db return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM user")); } - RangeResults User::find(Session& session, const FindParameters& params) + std::vector User::find(Session& session, const FindParameters& params) { session.checkReadTransaction(); diff --git a/src/libs/database/include/database/Types.hpp b/src/libs/database/include/database/Types.hpp index 46c1661d..849c79cd 100644 --- a/src/libs/database/include/database/Types.hpp +++ b/src/libs/database/include/database/Types.hpp @@ -38,8 +38,6 @@ namespace lms::db // Request: // size = 0 => means we don't want data - // Response (via RangeResults) - // size => results size struct Range { std::size_t offset{}; @@ -65,40 +63,6 @@ namespace lms::db } } - template - struct RangeResults - { - Range range; - std::vector results; - bool moreResults{}; - - RangeResults getSubRange(Range subRange) - { - assert(subRange.offset >= range.offset); - - if (!subRange.size) - subRange.size = range.size - (subRange.offset - range.offset); - - subRange.offset = std::min(subRange.offset, range.offset + range.size); - subRange.size = std::min(subRange.size, range.offset + range.size - subRange.offset); - - RangeResults subResults; - - auto itBegin{ std::cbegin(results) + subRange.offset - range.offset }; - auto itEnd{ itBegin + subRange.size }; - subResults.results.reserve(std::distance(itBegin, itEnd)); - std::copy(itBegin, itEnd, std::back_inserter(subResults.results)); - - subResults.range = subRange; - if (subRange.offset + subRange.size == range.offset + range.size) - subResults.moreResults = moreResults; - else - subResults.moreResults = true; - - return subResults; - } - }; - struct FileStats { std::size_t trackCount; diff --git a/src/libs/database/include/database/objects/Artist.hpp b/src/libs/database/include/database/objects/Artist.hpp index 8786c15f..e22cd63f 100644 --- a/src/libs/database/include/database/objects/Artist.hpp +++ b/src/libs/database/include/database/objects/Artist.hpp @@ -66,9 +66,8 @@ namespace lms::db ArtistSortMethod sortMethod{ ArtistSortMethod::None }; std::optional range; Wt::WDateTime writtenAfter; - UserId starringUser; // only artists starred by this user - std::optional feedbackBackend; // and for this feedback backend - TrackId track; // artists involved in this track + UserId starringUser; // only artists starred by this user (uses their current feedback backend) + TrackId track; // artists involved in this track FindParameters& setFilters(const Filters& _filters) { @@ -105,10 +104,9 @@ namespace lms::db writtenAfter = _after; return *this; } - FindParameters& setStarringUser(UserId _user, FeedbackBackend _feedbackBackend) + FindParameters& setStarringUser(UserId _user) { starringUser = _user; - feedbackBackend = _feedbackBackend; return *this; } FindParameters& setTrack(TrackId _track) @@ -127,13 +125,13 @@ namespace lms::db static std::vector find(Session& session, std::string_view name); // exact match on name field static void find(Session& session, ArtistId& lastRetrievedArtist, std::size_t count, const std::function& func, MediaLibraryId library = {}); static void find(Session& session, const IdRange& idRange, const std::function& func); - static RangeResults find(Session& session, const FindParameters& params); + static std::vector find(Session& session, const FindParameters& params); static void find(Session& session, const FindParameters& params, std::function func); static IdRange findNextIdRange(Session& session, ArtistId lastRetrievedId, std::size_t count); - static RangeResults findIds(Session& session, const FindParameters& params); - static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt); // No track related + static std::vector findIds(Session& session, const FindParameters& params); + static std::vector findOrphanIds(Session& session, std::optional range = std::nullopt); // No track related static bool exists(Session& session, ArtistId id); - static RangeResults findWithMBIDNameVariants(Session& session, ArtistId& lastRetrievedArtist, std::optional range = std::nullopt); + static std::vector findWithMBIDNameVariants(Session& session, ArtistId& lastRetrievedArtist, std::optional range = std::nullopt); // Updates static void updatePreferredArtwork(Session& session, ArtistId artistId, ArtworkId artworkId); diff --git a/src/libs/database/include/database/objects/Cluster.hpp b/src/libs/database/include/database/objects/Cluster.hpp index 6a53e9eb..29b80a3d 100644 --- a/src/libs/database/include/database/objects/Cluster.hpp +++ b/src/libs/database/include/database/objects/Cluster.hpp @@ -91,11 +91,11 @@ namespace lms::db // Find utility static std::size_t getCount(Session& session); - static RangeResults findIds(Session& session, const FindParameters& params); - static RangeResults find(Session& session, const FindParameters& params); + static std::vector findIds(Session& session, const FindParameters& params); + static std::vector find(Session& session, const FindParameters& params); static void find(Session& session, const FindParameters& params, std::function _func); static pointer find(Session& session, ClusterId id); - static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt); + static std::vector findOrphanIds(Session& session, std::optional range = std::nullopt); // May be very slow static std::size_t computeTrackCount(Session& session, ClusterId id); @@ -104,7 +104,7 @@ namespace lms::db // Accessors std::string_view getName() const { return _name; } ObjectPtr getType() const { return _clusterType; } - RangeResults getTracks(std::optional range = std::nullopt) const; + std::vector getTracks(std::optional range = std::nullopt) const; void addTrack(ObjectPtr track); template @@ -136,12 +136,12 @@ namespace lms::db // Getters static std::size_t getCount(Session& session); - static RangeResults findIds(Session& session, std::optional range = std::nullopt); + static std::vector findIds(Session& session, std::optional range = std::nullopt); static void find(Session& session, const std::function& func); static pointer find(Session& session, std::string_view name); static pointer find(Session& session, ClusterTypeId id); - static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt); - static RangeResults findUsed(Session& session, std::optional range = std::nullopt); + static std::vector findOrphanIds(Session& session, std::optional range = std::nullopt); + static std::vector findUsed(Session& session, std::optional range = std::nullopt); static void remove(Session& session, const std::string& name); diff --git a/src/libs/database/include/database/objects/Directory.hpp b/src/libs/database/include/database/objects/Directory.hpp index cbc46971..dd30df7c 100644 --- a/src/libs/database/include/database/objects/Directory.hpp +++ b/src/libs/database/include/database/objects/Directory.hpp @@ -122,11 +122,11 @@ namespace lms::db static pointer find(Session& session, DirectoryId id); static pointer find(Session& session, const std::filesystem::path& path); static void find(Session& session, DirectoryId& lastRetrievedDirectory, std::size_t count, const std::function& func); - static RangeResults find(Session& session, const FindParameters& params); + static std::vector find(Session& session, const FindParameters& params); static void find(Session& session, const FindParameters& params, const std::function& func); - static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt); - static RangeResults findMismatchedLibrary(Session& session, std::optional range, const std::filesystem::path& rootPath, MediaLibraryId expectedLibraryId); - static RangeResults findRootDirectories(Session& session, std::optional range = std::nullopt); + static std::vector findOrphanIds(Session& session, std::optional range = std::nullopt); + static std::vector findMismatchedLibrary(Session& session, std::optional range, const std::filesystem::path& rootPath, MediaLibraryId expectedLibraryId); + static std::vector findRootDirectories(Session& session, std::optional range = std::nullopt); // getters const std::filesystem::path& getAbsolutePath() const { return _absolutePath; } diff --git a/src/libs/database/include/database/objects/Genre.hpp b/src/libs/database/include/database/objects/Genre.hpp index 3c4ed88a..ec5080f1 100644 --- a/src/libs/database/include/database/objects/Genre.hpp +++ b/src/libs/database/include/database/objects/Genre.hpp @@ -82,12 +82,12 @@ namespace lms::db Genre() = default; static std::size_t getCount(Session& session); - static RangeResults findIds(Session& session, const FindParameters& params); - static RangeResults find(Session& session, const FindParameters& params); + static std::vector findIds(Session& session, const FindParameters& params); + static std::vector find(Session& session, const FindParameters& params); static void find(Session& session, const FindParameters& params, std::function func); static pointer find(Session& session, GenreId id); static pointer find(Session& session, std::string_view name); - static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt); + static std::vector findOrphanIds(Session& session, std::optional range = std::nullopt); static std::size_t computeTrackCount(Session& session, GenreId id); static std::size_t computeReleaseCount(Session& session, GenreId id); diff --git a/src/libs/database/include/database/objects/Grouping.hpp b/src/libs/database/include/database/objects/Grouping.hpp index 26d758c7..cd592a0d 100644 --- a/src/libs/database/include/database/objects/Grouping.hpp +++ b/src/libs/database/include/database/objects/Grouping.hpp @@ -82,12 +82,12 @@ namespace lms::db Grouping() = default; static std::size_t getCount(Session& session); - static RangeResults findIds(Session& session, const FindParameters& params); - static RangeResults find(Session& session, const FindParameters& params); + static std::vector findIds(Session& session, const FindParameters& params); + static std::vector find(Session& session, const FindParameters& params); static void find(Session& session, const FindParameters& params, std::function func); static pointer find(Session& session, GroupingId id); static pointer find(Session& session, std::string_view name); - static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt); + static std::vector findOrphanIds(Session& session, std::optional range = std::nullopt); std::string_view getName() const { return _name; } diff --git a/src/libs/database/include/database/objects/Image.hpp b/src/libs/database/include/database/objects/Image.hpp index fcbdd51d..5dcf1156 100644 --- a/src/libs/database/include/database/objects/Image.hpp +++ b/src/libs/database/include/database/objects/Image.hpp @@ -73,7 +73,7 @@ namespace lms::db static std::size_t getCount(Session& session); static pointer find(Session& session, ImageId id); static pointer find(Session& session, const std::filesystem::path& file); - static RangeResults find(Session& session, const FindParameters& params); + static std::vector find(Session& session, const FindParameters& params); static void find(Session& session, const FindParameters& parameters, const std::function& func); static void find(Session& session, ImageId& lastRetrievedId, std::size_t count, const std::function& func); static void findAbsoluteFilePath(Session& session, ImageId& lastRetrievedId, std::size_t count, const std::function& func); diff --git a/src/libs/database/include/database/objects/Language.hpp b/src/libs/database/include/database/objects/Language.hpp index b5db8178..b31d69d2 100644 --- a/src/libs/database/include/database/objects/Language.hpp +++ b/src/libs/database/include/database/objects/Language.hpp @@ -82,12 +82,12 @@ namespace lms::db Language() = default; static std::size_t getCount(Session& session); - static RangeResults findIds(Session& session, const FindParameters& params); - static RangeResults find(Session& session, const FindParameters& params); + static std::vector findIds(Session& session, const FindParameters& params); + static std::vector find(Session& session, const FindParameters& params); static void find(Session& session, const FindParameters& params, std::function func); static pointer find(Session& session, LanguageId id); static pointer find(Session& session, std::string_view name); - static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt); + static std::vector findOrphanIds(Session& session, std::optional range = std::nullopt); std::string_view getName() const { return _name; } diff --git a/src/libs/database/include/database/objects/Listen.hpp b/src/libs/database/include/database/objects/Listen.hpp index 15863d49..e15dbca9 100644 --- a/src/libs/database/include/database/objects/Listen.hpp +++ b/src/libs/database/include/database/objects/Listen.hpp @@ -19,6 +19,7 @@ #pragma once +#include #include #include @@ -36,6 +37,8 @@ namespace lms::db { + class Artist; + class Release; class Session; class Track; class User; @@ -78,13 +81,12 @@ namespace lms::db static std::size_t getCount(Session& session); static pointer find(Session& session, ListenId id); static pointer find(Session& session, UserId userId, TrackId trackId, ScrobblingBackend backend, const Wt::WDateTime& dateTime); - static RangeResults find(Session& session, const FindParameters& parameters); + static std::vector find(Session& session, const FindParameters& parameters); // Stats struct StatsFindParameters { UserId user; - std::optional backend; db::Filters filters; std::vector keywords; // if non empty, name must match all of these keywords std::optional range; @@ -95,11 +97,6 @@ namespace lms::db user = _user; return *this; } - StatsFindParameters& setScrobblingBackend(std::optional _backend) - { - backend = _backend; - return *this; - } StatsFindParameters& setFilters(const db::Filters& _filters) { filters = _filters; @@ -139,13 +136,19 @@ namespace lms::db } }; - static RangeResults getTopArtists(Session& session, const ArtistStatsFindParameters& params); - static RangeResults getTopReleases(Session& session, const StatsFindParameters& params); - static RangeResults getTopTracks(Session& session, const StatsFindParameters& params); + static std::vector getTopArtists(Session& session, const ArtistStatsFindParameters& params); + static std::vector getTopReleases(Session& session, const StatsFindParameters& params); + static std::vector getTopTracks(Session& session, const StatsFindParameters& params); + static std::vector getRecentArtists(Session& session, const ArtistStatsFindParameters& params); + static std::vector getRecentReleases(Session& session, const StatsFindParameters& params); + static std::vector getRecentTracks(Session& session, const StatsFindParameters& params); - static RangeResults getRecentArtists(Session& session, const ArtistStatsFindParameters& params); - static RangeResults getRecentReleases(Session& session, const StatsFindParameters& params); - static RangeResults getRecentTracks(Session& session, const StatsFindParameters& params); + static void getTopArtists(Session& session, const ArtistStatsFindParameters& params, const std::function&)>& func); + static void getTopReleases(Session& session, const StatsFindParameters& params, const std::function&)>& func); + static void getTopTracks(Session& session, const StatsFindParameters& params, const std::function&)>& func); + static void getRecentArtists(Session& session, const ArtistStatsFindParameters& params, const std::function&)>& func); + static void getRecentReleases(Session& session, const StatsFindParameters& params, const std::function&)>& func); + static void getRecentTracks(Session& session, const StatsFindParameters& params, const std::function&)>& func); static std::size_t getCount(Session& session, UserId userId, TrackId trackId); // for the current backend static std::size_t getCount(Session& session, UserId userId, ReleaseId trackId); // for the current backend diff --git a/src/libs/database/include/database/objects/Medium.hpp b/src/libs/database/include/database/objects/Medium.hpp index 55c3dff5..afa95e13 100644 --- a/src/libs/database/include/database/objects/Medium.hpp +++ b/src/libs/database/include/database/objects/Medium.hpp @@ -78,7 +78,7 @@ namespace lms::db static pointer find(Session& session, ReleaseId id, std::optional position); static void find(Session& session, const IdRange& idRange, const std::function& func); static IdRange findNextIdRange(Session& session, MediumId lastRetrievedId, std::size_t count); - static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt); + static std::vector findOrphanIds(Session& session, std::optional range = std::nullopt); // Updates static void updatePreferredArtwork(Session& session, MediumId mediumId, ArtworkId artworkId); diff --git a/src/libs/database/include/database/objects/Mood.hpp b/src/libs/database/include/database/objects/Mood.hpp index f12b4ea6..81f1f4c6 100644 --- a/src/libs/database/include/database/objects/Mood.hpp +++ b/src/libs/database/include/database/objects/Mood.hpp @@ -82,12 +82,12 @@ namespace lms::db Mood() = default; static std::size_t getCount(Session& session); - static RangeResults findIds(Session& session, const FindParameters& params); - static RangeResults find(Session& session, const FindParameters& params); + static std::vector findIds(Session& session, const FindParameters& params); + static std::vector find(Session& session, const FindParameters& params); static void find(Session& session, const FindParameters& params, std::function func); static pointer find(Session& session, MoodId id); static pointer find(Session& session, std::string_view name); - static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt); + static std::vector findOrphanIds(Session& session, std::optional range = std::nullopt); std::string_view getName() const { return _name; } diff --git a/src/libs/database/include/database/objects/Release.hpp b/src/libs/database/include/database/objects/Release.hpp index 95a0d1ae..468580cd 100644 --- a/src/libs/database/include/database/objects/Release.hpp +++ b/src/libs/database/include/database/objects/Release.hpp @@ -70,7 +70,7 @@ namespace lms::db static std::size_t getCount(Session& session); static pointer find(Session& session, CountryId id); static pointer find(Session& session, std::string_view name); - static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt); + static std::vector findOrphanIds(Session& session, std::optional range = std::nullopt); // Accessors std::string_view getName() const { return _name; } @@ -102,7 +102,7 @@ namespace lms::db static pointer find(Session& session, LabelId id); static pointer find(Session& session, std::string_view name); static void find(Session& session, LabelSortMethod sortMethod, std::function func); - static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt); + static std::vector findOrphanIds(Session& session, std::optional range = std::nullopt); // Accessors std::string_view getName() const { return _name; } @@ -134,7 +134,7 @@ namespace lms::db static pointer find(Session& session, ReleaseTypeId id); static pointer find(Session& session, std::string_view name); static void find(Session& session, ReleaseTypeSortMethod sortMethod, std::function func); - static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt); + static std::vector findOrphanIds(Session& session, std::optional range = std::nullopt); // Accessors std::string_view getName() const { return _name; } @@ -170,8 +170,7 @@ namespace lms::db Wt::WDateTime writtenAfter; std::optional dateRange; std::optional originalDateRange; - UserId starringUser; // only releases starred by this user - std::optional feedbackBackend; // and for this backend + UserId starringUser; // only releases starred by this user (uses their current feedback backend) ArtistId artist; // only releases by this release artist ArtistId trackArtist; // only releases that involved this track artist core::EnumSet trackArtistLinkTypes; // and for these link types, if set @@ -220,10 +219,9 @@ namespace lms::db originalDateRange = _originalDateRange; return *this; } - FindParameters& setStarringUser(UserId _user, FeedbackBackend _feedbackBackend) + FindParameters& setStarringUser(UserId _user) { starringUser = _user; - feedbackBackend = _feedbackBackend; return *this; } FindParameters& setArtist(ArtistId _artist) @@ -269,11 +267,11 @@ namespace lms::db static void find(Session& session, ReleaseId& lastRetrievedRelease, std::size_t count, const std::function& func, MediaLibraryId library = {}); static void find(Session& session, const IdRange& idRange, const std::function& func); static IdRange findNextIdRange(Session& session, ReleaseId lastRetrievedId, std::size_t count); - static RangeResults find(Session& session, const FindParameters& parameters); + static std::vector find(Session& session, const FindParameters& parameters); static void find(Session& session, const FindParameters& parameters, const std::function& func); - static RangeResults findIds(Session& session, const FindParameters& parameters); + static std::vector findIds(Session& session, const FindParameters& parameters); static std::size_t getCount(Session& session, const FindParameters& parameters); - static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt); // not track related + static std::vector findOrphanIds(Session& session, std::optional range = std::nullopt); // not track related // Updates static void updatePreferredArtwork(Session& session, ReleaseId id, ArtworkId artworkId); diff --git a/src/libs/database/include/database/objects/StarredTrack.hpp b/src/libs/database/include/database/objects/StarredTrack.hpp index 9a6b1c58..f0dbb1ca 100644 --- a/src/libs/database/include/database/objects/StarredTrack.hpp +++ b/src/libs/database/include/database/objects/StarredTrack.hpp @@ -73,7 +73,7 @@ namespace lms::db static pointer find(Session& session, TrackId trackId, UserId userId); // current feedback backend static pointer find(Session& session, TrackId trackId, UserId userId, FeedbackBackend backend); static bool exists(Session& session, TrackId trackId, UserId userId, FeedbackBackend backend); - static RangeResults find(Session& session, const FindParameters& findParams); + static std::vector find(Session& session, const FindParameters& findParams); // Accessors ObjectPtr getTrack() const { return _track; } diff --git a/src/libs/database/include/database/objects/Track.hpp b/src/libs/database/include/database/objects/Track.hpp index d9783b9f..5c84a60c 100644 --- a/src/libs/database/include/database/objects/Track.hpp +++ b/src/libs/database/include/database/objects/Track.hpp @@ -91,8 +91,7 @@ namespace lms::db TrackSortMethod sortMethod{ TrackSortMethod::None }; std::optional range; Wt::WDateTime writtenAfter; - UserId starringUser; // only tracks starred by this user - std::optional feedbackBackend; // and for this feedback backend + UserId starringUser; // only tracks starred by this user (uses their current feedback backend) ArtistId artist; // only tracks that involve this artist std::string artistName; // only tracks that involve this artist name core::EnumSet trackArtistLinkTypes; // and for these link types @@ -138,10 +137,9 @@ namespace lms::db writtenAfter = _after; return *this; } - FindParameters& setStarringUser(UserId _user, FeedbackBackend _feedbackBackend) + FindParameters& setStarringUser(UserId _user) { starringUser = _user; - feedbackBackend = _feedbackBackend; return *this; } FindParameters& setArtist(ArtistId _artist, core::EnumSet _trackArtistLinkTypes = {}) @@ -231,12 +229,11 @@ namespace lms::db static bool exists(Session& session, TrackId id); static std::vector findByRecordingMBID(Session& session, const core::UUID& MBID); static std::vector findByMBID(Session& session, const core::UUID& MBID); - static RangeResults findIds(Session& session, const FindParameters& params); - static RangeResults find(Session& session, const FindParameters& params); + static std::vector findIds(Session& session, const FindParameters& params); + static std::vector find(Session& session, const FindParameters& params); static void find(Session& session, const FindParameters& params, const std::function& func); - static void find(Session& session, const FindParameters& params, bool& moreResults, const std::function& func); static std::size_t getCount(Session& session, const FindParameters& params); - static RangeResults findIdsTrackMBIDDuplicates(Session& session, std::optional range = std::nullopt); + static std::vector findIdsTrackMBIDDuplicates(Session& session, std::optional range = std::nullopt); // Update utility functions static void updatePreferredArtwork(Session& session, TrackId trackId, ArtworkId artworkId); diff --git a/src/libs/database/include/database/objects/TrackBookmark.hpp b/src/libs/database/include/database/objects/TrackBookmark.hpp index 833747e8..062f3467 100644 --- a/src/libs/database/include/database/objects/TrackBookmark.hpp +++ b/src/libs/database/include/database/objects/TrackBookmark.hpp @@ -46,7 +46,7 @@ namespace lms::db // Find utility functions static std::size_t getCount(Session& session); static pointer find(Session& session, TrackBookmarkId id); - static RangeResults find(Session& session, UserId userId, std::optional range = std::nullopt); + static std::vector find(Session& session, UserId userId, std::optional range = std::nullopt); static pointer find(Session& session, UserId userId, TrackId trackId); // Setters diff --git a/src/libs/database/include/database/objects/TrackEmbeddedImage.hpp b/src/libs/database/include/database/objects/TrackEmbeddedImage.hpp index 2c4bf49f..d9cbfeea 100644 --- a/src/libs/database/include/database/objects/TrackEmbeddedImage.hpp +++ b/src/libs/database/include/database/objects/TrackEmbeddedImage.hpp @@ -100,7 +100,7 @@ namespace lms::db static pointer find(Session& session, TrackEmbeddedImageId id); static void find(Session& session, const FindParameters& params, const std::function& func); static pointer find(Session& session, std::size_t size, ImageHashType hash); - static RangeResults findOrphanIds(Session& session, std::optional range); + static std::vector findOrphanIds(Session& session, std::optional range); // getters ImageHashType getHash() const { return _hash; } diff --git a/src/libs/database/include/database/objects/TrackList.hpp b/src/libs/database/include/database/objects/TrackList.hpp index 14b2c412..685adfcc 100644 --- a/src/libs/database/include/database/objects/TrackList.hpp +++ b/src/libs/database/include/database/objects/TrackList.hpp @@ -116,7 +116,7 @@ namespace lms::db static std::size_t getCount(Session& session); static pointer find(Session& session, std::string_view name, TrackListType type, UserId userId); static pointer find(Session& session, TrackListId tracklistId); - static RangeResults find(Session& session, const FindParameters& params); + static std::vector find(Session& session, const FindParameters& params); static void find(Session& session, const FindParameters& params, const std::function& func); // Accessors @@ -139,7 +139,7 @@ namespace lms::db bool isEmpty() const; std::size_t getCount() const; ObjectPtr getEntry(std::size_t pos) const; - RangeResults> getEntries(std::optional range = {}) const; + std::vector> getEntries(std::optional range = {}) const; ObjectPtr getEntryByTrackAndDateTime(ObjectPtr track, const Wt::WDateTime& dateTime) const; std::vector getTrackIds() const; diff --git a/src/libs/database/include/database/objects/TrackLyrics.hpp b/src/libs/database/include/database/objects/TrackLyrics.hpp index ee7e35bf..e35c63bc 100644 --- a/src/libs/database/include/database/objects/TrackLyrics.hpp +++ b/src/libs/database/include/database/objects/TrackLyrics.hpp @@ -83,7 +83,7 @@ namespace lms::db static pointer find(Session& session, const std::filesystem::path& file); static void find(Session& session, const FindParameters& params, const std::function& func); static void find(Session& session, TrackLyricsId& lastRetrievedId, std::size_t count, const std::function& func); - static RangeResults findOrphanIds(Session& session, std::optional range); + static std::vector findOrphanIds(Session& session, std::optional range); static void findAbsoluteFilePath(Session& session, TrackLyricsId& lastRetrievedId, std::size_t count, const std::function& func); using SynchronizedLines = std::map; diff --git a/src/libs/database/include/database/objects/TrackMusicNNEmbeddings.hpp b/src/libs/database/include/database/objects/TrackMusicNNEmbeddings.hpp index ea99bbcb..2403b803 100644 --- a/src/libs/database/include/database/objects/TrackMusicNNEmbeddings.hpp +++ b/src/libs/database/include/database/objects/TrackMusicNNEmbeddings.hpp @@ -45,7 +45,7 @@ namespace lms::db static std::size_t getCount(Session& session); static pointer find(Session& session, TrackMusicNNEmbeddingsId id); static pointer find(Session& session, TrackId trackId); - static RangeResults find(Session& session, std::optional range = std::nullopt); + static std::vector find(Session& session, std::optional range = std::nullopt); static void find(Session& session, std::function func); static void removeAll(Session& session); diff --git a/src/libs/database/include/database/objects/User.hpp b/src/libs/database/include/database/objects/User.hpp index 79244d51..0b21556b 100644 --- a/src/libs/database/include/database/objects/User.hpp +++ b/src/libs/database/include/database/objects/User.hpp @@ -88,7 +88,7 @@ namespace lms::db static std::size_t getCount(Session& session); static pointer find(Session& session, UserId id); static pointer find(Session& session, std::string_view loginName); - static RangeResults find(Session& session, const FindParameters& params); + static std::vector find(Session& session, const FindParameters& params); static void find(Session& session, const FindParameters& params, const std::function& func); static pointer findDemoUser(Session& session); diff --git a/src/libs/database/test/Artist.cpp b/src/libs/database/test/Artist.cpp index 5a8f0e7f..c9271069 100644 --- a/src/libs/database/test/Artist.cpp +++ b/src/libs/database/test/Artist.cpp @@ -55,20 +55,20 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); artists = Artist::findOrphanIds(session); - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); } { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::find(session, Artist::FindParameters{}) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front()->getId(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front()->getId(), artist.getId()); } { @@ -181,10 +181,7 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}) }; - ASSERT_EQ(artists.results.size(), 0); - ASSERT_FALSE(artists.moreResults); - ASSERT_EQ(artists.range.offset, 0); - ASSERT_EQ(artists.range.size, 0); + ASSERT_EQ(artists.size(), 0); } ScopedArtist artist1{ session, "MyArtist1" }; @@ -195,43 +192,31 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}) }; - ASSERT_EQ(artists.results.size(), 3); - ASSERT_FALSE(artists.moreResults); - ASSERT_EQ(artists.range.offset, 0); - ASSERT_EQ(artists.range.size, 3); + ASSERT_EQ(artists.size(), 3); } { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setRange(Range{ 0, 1 })) }; - ASSERT_EQ(artists.results.size(), 1); - ASSERT_TRUE(artists.moreResults); - ASSERT_EQ(artists.range.offset, 0); - ASSERT_EQ(artists.range.size, 1); - EXPECT_EQ(artists.results[0], artist1.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist1.getId()); } { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setRange(Range{ 1, 1 })) }; - ASSERT_EQ(artists.results.size(), 1); - ASSERT_TRUE(artists.moreResults); - ASSERT_EQ(artists.range.offset, 1); - ASSERT_EQ(artists.range.size, 1); - EXPECT_EQ(artists.results[0], artist2.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist2.getId()); } { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setRange(Range{ 2, 1 })) }; - ASSERT_EQ(artists.results.size(), 1); - ASSERT_FALSE(artists.moreResults); - ASSERT_EQ(artists.range.offset, 2); - ASSERT_EQ(artists.range.size, 1); - EXPECT_EQ(artists.results[0], artist3.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist3.getId()); } } @@ -249,7 +234,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Artist::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(Artist::findOrphanIds(session).size(), 0); } { @@ -310,29 +295,29 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto tracks{ Track::findIds(session, Track::FindParameters{}.setName("MyTrackName").setArtistName("MyArtist")) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); } { auto transaction{ session.createReadTransaction() }; auto tracks{ Track::findIds(session, Track::FindParameters{}.setName("MyTrackName").setArtistName("MyArtistFoo")) }; - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } { auto transaction{ session.createReadTransaction() }; auto tracks{ Track::findIds(session, Track::FindParameters{}.setName("MyTrackNameFoo").setArtistName("MyArtist")) }; - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setTrack(track->getId())) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); } { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Artist::find(session, Artist::FindParameters{}.setReleaseArtistsOnly(true)).results.size(), 0); + EXPECT_EQ(Artist::find(session, Artist::FindParameters{}.setReleaseArtistsOnly(true)).size(), 0); } } @@ -343,7 +328,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Artist::findOrphanIds(session).results, std::vector{ artist.getId() }); + EXPECT_EQ(Artist::findOrphanIds(session), std::vector{ artist.getId() }); } { @@ -353,7 +338,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Artist::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(Artist::findOrphanIds(session).size(), 0); } } @@ -374,19 +359,19 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setTrack(track->getId())) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); } { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setMediaLibrary(library->getId()))) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); } { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setMediaLibrary(otherLibrary->getId()))) }; - EXPECT_EQ(artists.results.size(), 0); + EXPECT_EQ(artists.size(), 0); } } @@ -416,26 +401,26 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); } { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setMediaLibrary(library1->getId()))) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); } { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setMediaLibrary(library2->getId()))) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); } { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setMediaLibrary(otherLibrary->getId()))) }; - EXPECT_EQ(artists.results.size(), 0); + EXPECT_EQ(artists.size(), 0); } } @@ -460,15 +445,15 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); } { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setMediaLibrary(library->getId()))) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); } { @@ -479,8 +464,8 @@ namespace lms::db::tests params.setFilters(Filters{}.setMediaLibrary(library.getId())); auto artists{ Artist::findIds(session, params) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); } { @@ -491,7 +476,7 @@ namespace lms::db::tests params.setFilters(Filters{}.setMediaLibrary(library.getId())); auto artists{ Artist::findIds(session, params) }; - EXPECT_EQ(artists.results.size(), 0); + EXPECT_EQ(artists.size(), 0); } { @@ -502,8 +487,8 @@ namespace lms::db::tests params.setFilters(Filters{}.setMediaLibrary(library.getId())); auto artists{ Artist::findIds(session, params) }; - EXPECT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + EXPECT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); } } @@ -521,18 +506,18 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Artist::findOrphanIds(session, Range{}).results.size(), 0); + EXPECT_EQ(Artist::findOrphanIds(session, Range{}).size(), 0); } { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}).results.size(), 1); - EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setTrackArtistLinkType(TrackArtistLinkType::Artist)).results.size(), 1); - EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setTrackArtistLinkType(TrackArtistLinkType::Producer)).results.size(), 1); - EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setTrackArtistLinkType(TrackArtistLinkType::Writer)).results.size(), 1); - EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setTrackArtistLinkType(TrackArtistLinkType::Composer)).results.size(), 0); + EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}).size(), 1); + EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setTrackArtistLinkType(TrackArtistLinkType::Artist)).size(), 1); + EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setTrackArtistLinkType(TrackArtistLinkType::Producer)).size(), 1); + EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setTrackArtistLinkType(TrackArtistLinkType::Writer)).size(), 1); + EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setTrackArtistLinkType(TrackArtistLinkType::Composer)).size(), 0); - EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setReleaseArtistsOnly(true)).results.size(), 0); + EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setReleaseArtistsOnly(true)).size(), 0); } { @@ -549,17 +534,17 @@ namespace lms::db::tests EXPECT_EQ(track->getArtistLinks().size(), 3); auto tracks{ Track::findIds(session, Track::FindParameters{}.setArtist(artist.getId())) }; - EXPECT_EQ(tracks.results.size(), 1); + EXPECT_EQ(tracks.size(), 1); tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist.getId(), { TrackArtistLinkType::Producer })); - EXPECT_EQ(tracks.results.size(), 1); + EXPECT_EQ(tracks.size(), 1); tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist.getId(), { TrackArtistLinkType::Artist })); - EXPECT_EQ(tracks.results.size(), 1); + EXPECT_EQ(tracks.size(), 1); tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist.getId(), { TrackArtistLinkType::Writer })); - EXPECT_EQ(tracks.results.size(), 1); + EXPECT_EQ(tracks.size(), 1); tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist.getId(), { TrackArtistLinkType::Composer })); - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } { @@ -609,7 +594,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Artist::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(Artist::findOrphanIds(session).size(), 0); } { @@ -623,32 +608,32 @@ namespace lms::db::tests EXPECT_EQ(track->getArtists({}).size(), 2); EXPECT_EQ(track->getArtists({ TrackArtistLinkType::Artist }).size(), 2); EXPECT_EQ(track->getArtists({ TrackArtistLinkType::Arranger }).size(), 0); - EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}).results.size(), 2); - EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setSortMethod(ArtistSortMethod::Random)).results.size(), 2); + EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}).size(), 2); + EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setSortMethod(ArtistSortMethod::Random)).size(), 2); } { auto transaction{ session.createReadTransaction() }; auto tracks{ Track::findIds(session, Track::FindParameters{}.setArtist(artist1->getId())) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track->getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track->getId()); tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist2->getId())); - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track->getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track->getId()); tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist1->getId(), { TrackArtistLinkType::Arranger })); - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist1->getId(), { TrackArtistLinkType::Artist })); - EXPECT_EQ(tracks.results.size(), 1); + EXPECT_EQ(tracks.size(), 1); tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist2->getId(), { TrackArtistLinkType::Arranger })); - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist2->getId(), { TrackArtistLinkType::Artist })); - EXPECT_EQ(tracks.results.size(), 1); + EXPECT_EQ(tracks.size(), 1); } { @@ -697,7 +682,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Artist::find(session, Artist::FindParameters{}.setReleaseArtistsOnly(true)).results.size(), 0); + EXPECT_EQ(Artist::find(session, Artist::FindParameters{}.setReleaseArtistsOnly(true)).size(), 0); } { @@ -707,7 +692,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Artist::find(session, Artist::FindParameters{}.setReleaseArtistsOnly(true)).results.size(), 1); + EXPECT_EQ(Artist::find(session, Artist::FindParameters{}.setReleaseArtistsOnly(true)).size(), 1); } } @@ -734,8 +719,8 @@ namespace lms::db::tests params.setFilters(Filters{}.setCodec(core::media::Codec::FLAC)); const auto artists{ Artist::find(session, params) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front()->getId(), artist2.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front()->getId(), artist2.getId()); } } @@ -753,15 +738,15 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setKeywords({ "N" })).results.size(), 0); + EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setKeywords({ "N" })).size(), 0); const auto artistsByAAA{ Artist::findIds(session, Artist::FindParameters{}.setKeywords({ "A" })) }; - ASSERT_EQ(artistsByAAA.results.size(), 1); - EXPECT_EQ(artistsByAAA.results.front(), artist.getId()); + ASSERT_EQ(artistsByAAA.size(), 1); + EXPECT_EQ(artistsByAAA.front(), artist.getId()); const auto artistsByZZZ{ Artist::Artist::findIds(session, Artist::FindParameters{}.setKeywords({ "Z" })) }; - ASSERT_EQ(artistsByZZZ.results.size(), 1); - EXPECT_EQ(artistsByZZZ.results.front(), artist.getId()); + ASSERT_EQ(artistsByZZZ.size(), 1); + EXPECT_EQ(artistsByZZZ.front(), artist.getId()); EXPECT_EQ(Artist::find(session, "NNN").size(), 0); EXPECT_EQ(Artist::find(session, "AAA").size(), 1); @@ -804,27 +789,27 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; { const auto artists{ Artist::findIds(session, Artist::FindParameters{}.setKeywords({ "MyArtist" })) }; - EXPECT_EQ(artists.results.size(), 6); + EXPECT_EQ(artists.size(), 6); } { const auto artists{ Artist::findIds(session, Artist::FindParameters{}.setKeywords({ "MyArtist%" }).setSortMethod(ArtistSortMethod::Name)) }; - ASSERT_EQ(artists.results.size(), 2); - EXPECT_EQ(artists.results[0], artist1.getId()); - EXPECT_EQ(artists.results[1], artist4.getId()); + ASSERT_EQ(artists.size(), 2); + EXPECT_EQ(artists[0], artist1.getId()); + EXPECT_EQ(artists[1], artist4.getId()); } { const auto artists{ Artist::findIds(session, Artist::FindParameters{}.setKeywords({ "%MyArtist" }).setSortMethod(ArtistSortMethod::Name)) }; - ASSERT_EQ(artists.results.size(), 2); - EXPECT_EQ(artists.results[0], artist2.getId()); - EXPECT_EQ(artists.results[1], artist5.getId()); + ASSERT_EQ(artists.size(), 2); + EXPECT_EQ(artists[0], artist2.getId()); + EXPECT_EQ(artists[1], artist5.getId()); } { const auto artists{ Artist::findIds(session, Artist::FindParameters{}.setKeywords({ "_MyArtist" }).setSortMethod(ArtistSortMethod::Name)) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results[0], artist3.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist3.getId()); } } } @@ -934,13 +919,13 @@ namespace lms::db::tests auto allArtistsByName{ Artist::findIds(session, Artist::FindParameters{}.setSortMethod(ArtistSortMethod::Name)) }; auto allArtistsBySortName{ Artist::findIds(session, Artist::FindParameters{}.setSortMethod(ArtistSortMethod::SortName)) }; - ASSERT_EQ(allArtistsByName.results.size(), 2); - EXPECT_EQ(allArtistsByName.results.front(), artistA.getId()); - EXPECT_EQ(allArtistsByName.results.back(), artistB.getId()); + ASSERT_EQ(allArtistsByName.size(), 2); + EXPECT_EQ(allArtistsByName.front(), artistA.getId()); + EXPECT_EQ(allArtistsByName.back(), artistB.getId()); - ASSERT_EQ(allArtistsBySortName.results.size(), 2); - EXPECT_EQ(allArtistsBySortName.results.front(), artistB.getId()); - EXPECT_EQ(allArtistsBySortName.results.back(), artistA.getId()); + ASSERT_EQ(allArtistsBySortName.size(), 2); + EXPECT_EQ(allArtistsBySortName.front(), artistB.getId()); + EXPECT_EQ(allArtistsBySortName.back(), artistA.getId()); } } @@ -955,7 +940,7 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto tracks{ Track::findIds(session, Track::FindParameters{}.setNonRelease(true).setArtist(artist->getId())) }; - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } { @@ -971,8 +956,8 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setArtist(artist.getId()).setNonRelease(true)) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track2.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track2.getId()); } } @@ -1033,11 +1018,11 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto artists{ Artist::findIds(session, Artist::FindParameters{}.setSortMethod(ArtistSortMethod::AddedDesc)) }; - ASSERT_EQ(artists.results.size(), 4); - EXPECT_EQ(artists.results[0], artistD.getId()); - EXPECT_EQ(artists.results[1], artistA.getId()); - EXPECT_EQ(artists.results[2], artistB.getId()); - EXPECT_EQ(artists.results[3], artistC.getId()); + ASSERT_EQ(artists.size(), 4); + EXPECT_EQ(artists[0], artistD.getId()); + EXPECT_EQ(artists[1], artistA.getId()); + EXPECT_EQ(artists[2], artistB.getId()); + EXPECT_EQ(artists[3], artistC.getId()); } } @@ -1073,11 +1058,11 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto artists{ Artist::findIds(session, Artist::FindParameters{}.setSortMethod(ArtistSortMethod::LastWrittenDesc)) }; - ASSERT_EQ(artists.results.size(), 4); - EXPECT_EQ(artists.results[0], artistA.getId()); - EXPECT_EQ(artists.results[1], artistD.getId()); - EXPECT_EQ(artists.results[2], artistB.getId()); - EXPECT_EQ(artists.results[3], artistC.getId()); + ASSERT_EQ(artists.size(), 4); + EXPECT_EQ(artists[0], artistA.getId()); + EXPECT_EQ(artists[1], artistD.getId()); + EXPECT_EQ(artists[2], artistB.getId()); + EXPECT_EQ(artists[3], artistC.getId()); } } @@ -1144,8 +1129,8 @@ namespace lms::db::tests ArtistId lastRetrievedArtist; const auto results{ Artist::findWithMBIDNameVariants(session, lastRetrievedArtist) }; - ASSERT_EQ(results.results.size(), 1); - EXPECT_EQ(results.results[0]->getId(), artistA.getId()); + ASSERT_EQ(results.size(), 1); + EXPECT_EQ(results[0]->getId(), artistA.getId()); EXPECT_EQ(lastRetrievedArtist, artistA.getId()); } } diff --git a/src/libs/database/test/Cluster.cpp b/src/libs/database/test/Cluster.cpp index 4936a6a5..1800c438 100644 --- a/src/libs/database/test/Cluster.cpp +++ b/src/libs/database/test/Cluster.cpp @@ -50,26 +50,26 @@ namespace lms::db::tests { const auto clusters{ Cluster::findIds(session, Cluster::FindParameters{}) }; - ASSERT_EQ(clusters.results.size(), 1); - EXPECT_EQ(clusters.results.front(), cluster.getId()); + ASSERT_EQ(clusters.size(), 1); + EXPECT_EQ(clusters.front(), cluster.getId()); } { const auto clusters{ Cluster::findOrphanIds(session) }; - ASSERT_EQ(clusters.results.size(), 1); - EXPECT_EQ(clusters.results.front(), cluster.getId()); + ASSERT_EQ(clusters.size(), 1); + EXPECT_EQ(clusters.front(), cluster.getId()); } auto clusterTypes{ ClusterType::findIds(session) }; - ASSERT_EQ(clusterTypes.results.size(), 1); - EXPECT_EQ(clusterTypes.results.front(), clusterType.getId()); + ASSERT_EQ(clusterTypes.size(), 1); + EXPECT_EQ(clusterTypes.front(), clusterType.getId()); clusterTypes = ClusterType::findUsed(session); - ASSERT_EQ(clusterTypes.results.size(), 1); - EXPECT_EQ(clusterTypes.results.front(), clusterType.getId()); + ASSERT_EQ(clusterTypes.size(), 1); + EXPECT_EQ(clusterTypes.front(), clusterType.getId()); clusterTypes = ClusterType::findOrphanIds(session); - EXPECT_EQ(clusterTypes.results.size(), 0); + EXPECT_EQ(clusterTypes.size(), 0); } } @@ -77,10 +77,10 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto clusterTypes{ ClusterType::findOrphanIds(session) }; - ASSERT_EQ(clusterTypes.results.size(), 1); - EXPECT_EQ(clusterTypes.results.front(), clusterType.getId()); + ASSERT_EQ(clusterTypes.size(), 1); + EXPECT_EQ(clusterTypes.front(), clusterType.getId()); - ASSERT_EQ(ClusterType::findUsed(session).results.size(), 0); + ASSERT_EQ(ClusterType::findUsed(session).size(), 0); } } @@ -155,10 +155,10 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Cluster::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(Cluster::findOrphanIds(session).size(), 0); auto clusterTypes{ ClusterType::findOrphanIds(session) }; - ASSERT_EQ(clusterTypes.results.size(), 1); - EXPECT_EQ(clusterTypes.results.front(), clusterType.getId()); + ASSERT_EQ(clusterTypes.size(), 1); + EXPECT_EQ(clusterTypes.front(), clusterType.getId()); } ScopedCluster cluster1{ session, clusterType.lockAndGet(), "MyCluster1" }; @@ -167,7 +167,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto clusters{ Cluster::findOrphanIds(session) }; - EXPECT_EQ(clusters.results.size(), 2); + EXPECT_EQ(clusters.size(), 2); EXPECT_EQ(track->getClusters().size(), 0); EXPECT_EQ(track->getClusterIds().size(), 0); EXPECT_EQ(Cluster::computeTrackCount(session, cluster1.getId()), 0); @@ -183,8 +183,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto clusters{ Cluster::findIds(session, Cluster::FindParameters{}.setTrack(track.getId())) }; - ASSERT_EQ(clusters.results.size(), 1); - EXPECT_EQ(clusters.results.front(), cluster1.getId()); + ASSERT_EQ(clusters.size(), 1); + EXPECT_EQ(clusters.front(), cluster1.getId()); EXPECT_EQ(Cluster::computeTrackCount(session, cluster1.getId()), 1); EXPECT_EQ(Cluster::computeTrackCount(session, cluster2.getId()), 0); } @@ -192,21 +192,21 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto clusters{ Cluster::findOrphanIds(session) }; - ASSERT_EQ(clusters.results.size(), 1); - EXPECT_EQ(clusters.results.front(), cluster2.getId()); + ASSERT_EQ(clusters.size(), 1); + EXPECT_EQ(clusters.front(), cluster2.getId()); - EXPECT_EQ(ClusterType::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(ClusterType::findOrphanIds(session).size(), 0); } { auto transaction{ session.createReadTransaction() }; auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster1.getId() }))) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); tracks = Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster2.getId() }))); - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } { @@ -236,7 +236,7 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setClusters(clusterIds))) }; - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } { @@ -249,7 +249,7 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setClusters(clusterIds))) }; - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); EXPECT_EQ(Cluster::computeTrackCount(session, cluster1.getId()), 1); EXPECT_EQ(Cluster::computeTrackCount(session, cluster2.getId()), 0); } @@ -264,8 +264,8 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setClusters(clusterIds))) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); EXPECT_EQ(Cluster::computeTrackCount(session, cluster1.getId()), 1); EXPECT_EQ(Cluster::computeTrackCount(session, cluster2.getId()), 1); } @@ -289,11 +289,11 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Cluster::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(Cluster::findOrphanIds(session).size(), 0); EXPECT_EQ(Cluster::computeTrackCount(session, cluster.getId()), tracks.size()); - for (TrackId trackId : cluster->getTracks().results) + for (TrackId trackId : cluster->getTracks()) { auto it{ std::find_if(std::cbegin(tracks), std::cend(tracks), [&](const ScopedTrack& track) { return trackId == track.getId(); }) }; EXPECT_TRUE(it != std::cend(tracks)); @@ -333,8 +333,8 @@ namespace lms::db::tests { { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Cluster::find(session, Cluster::FindParameters{}).results.size(), 0); - EXPECT_EQ(Cluster::find(session, Cluster::FindParameters{}.setClusterTypeName("Foo")).results.size(), 0); + EXPECT_EQ(Cluster::find(session, Cluster::FindParameters{}).size(), 0); + EXPECT_EQ(Cluster::find(session, Cluster::FindParameters{}.setClusterTypeName("Foo")).size(), 0); } ScopedClusterType clusterType{ session, "MyClusterType" }; @@ -342,18 +342,18 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - auto clusters{ Cluster::findIds(session, Cluster::FindParameters{}).results }; + auto clusters{ Cluster::findIds(session, Cluster::FindParameters{}) }; ASSERT_EQ(clusters.size(), 1); EXPECT_EQ(clusters.front(), cluster.getId()); - clusters = Cluster::findIds(session, Cluster::FindParameters{}.setClusterType(clusterType.getId())).results; + clusters = Cluster::findIds(session, Cluster::FindParameters{}.setClusterType(clusterType.getId())); ASSERT_EQ(clusters.size(), 1); EXPECT_EQ(clusters.front(), cluster.getId()); - clusters = Cluster::findIds(session, Cluster::FindParameters{}.setClusterTypeName("Foo")).results; + clusters = Cluster::findIds(session, Cluster::FindParameters{}.setClusterTypeName("Foo")); EXPECT_EQ(clusters.size(), 0); - clusters = Cluster::findIds(session, Cluster::FindParameters{}.setClusterTypeName("MyClusterType")).results; + clusters = Cluster::findIds(session, Cluster::FindParameters{}.setClusterTypeName("MyClusterType")); ASSERT_EQ(clusters.size(), 1); EXPECT_EQ(clusters.front(), cluster.getId()); } @@ -366,7 +366,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Cluster::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(Cluster::findOrphanIds(session).size(), 0); } ScopedClusterType clusterType{ session, "MyClusterType" }; @@ -375,9 +375,9 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - ASSERT_EQ(Cluster::findOrphanIds(session).results.size(), 2); - EXPECT_EQ(Release::find(session, Release::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ unusedCluster.getId() }))).results.size(), 0); - EXPECT_EQ(Release::find(session, Release::FindParameters{}).results.size(), 1); + ASSERT_EQ(Cluster::findOrphanIds(session).size(), 2); + EXPECT_EQ(Release::find(session, Release::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ unusedCluster.getId() }))).size(), 0); + EXPECT_EQ(Release::find(session, Release::FindParameters{}).size(), 1); EXPECT_EQ(Cluster::computeReleaseCount(session, cluster.getId()), 0); EXPECT_EQ(Cluster::computeReleaseCount(session, unusedCluster.getId()), 0); } @@ -394,8 +394,8 @@ namespace lms::db::tests { auto clusters{ Cluster::findOrphanIds(session) }; - ASSERT_EQ(clusters.results.size(), 1); - EXPECT_EQ(clusters.results.front(), unusedCluster.getId()); + ASSERT_EQ(clusters.size(), 1); + EXPECT_EQ(clusters.front(), unusedCluster.getId()); } EXPECT_EQ(Cluster::computeReleaseCount(session, cluster.getId()), 1); EXPECT_EQ(Cluster::computeReleaseCount(session, unusedCluster.getId()), 0); @@ -405,23 +405,23 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto clusters{ Cluster::findIds(session, Cluster::FindParameters{}.setRelease(release.getId())) }; - ASSERT_EQ(clusters.results.size(), 1); - EXPECT_EQ(clusters.results.front(), cluster.getId()); + ASSERT_EQ(clusters.size(), 1); + EXPECT_EQ(clusters.front(), cluster.getId()); } { auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster.getId() }))) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); } { auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ unusedCluster.getId() }))) }; - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } { @@ -451,10 +451,10 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(ClusterType::findOrphanIds(session).results.size(), 0); - EXPECT_EQ(Cluster::findOrphanIds(session).results.size(), 2); - EXPECT_EQ(Release::findOrphanIds(session).results.size(), 0); - EXPECT_EQ(Artist::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(ClusterType::findOrphanIds(session).size(), 0); + EXPECT_EQ(Cluster::findOrphanIds(session).size(), 2); + EXPECT_EQ(Release::findOrphanIds(session).size(), 0); + EXPECT_EQ(Artist::findOrphanIds(session).size(), 0); } { @@ -467,11 +467,11 @@ namespace lms::db::tests auto transaction{ session.createWriteTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster1.getId() }))) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); - EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster2.getId() }))).results.size(), 0); - EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster3.getId() }))).results.size(), 0); + EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster2.getId() }))).size(), 0); + EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster3.getId() }))).size(), 0); cluster2.get().modify()->addTrack(track.get()); } @@ -480,18 +480,18 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster1.getId() }))) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); artists = Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster2.getId() }))); - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); artists = Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster1.getId() }))); - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); - EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster3.getId() }))).results.size(), 0); + EXPECT_EQ(Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster3.getId() }))).size(), 0); } } @@ -512,17 +512,17 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Cluster::findOrphanIds(session).results.size(), 0); - EXPECT_EQ(Release::findOrphanIds(session).results.size(), 0); - EXPECT_EQ(Artist::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(Cluster::findOrphanIds(session).size(), 0); + EXPECT_EQ(Release::findOrphanIds(session).size(), 0); + EXPECT_EQ(Artist::findOrphanIds(session).size(), 0); } { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster.getId() }))) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); } } @@ -552,8 +552,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Cluster::findOrphanIds(session).results.size(), 0); - EXPECT_EQ(Artist::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(Cluster::findOrphanIds(session).size(), 0); + EXPECT_EQ(Artist::findOrphanIds(session).size(), 0); } { @@ -563,8 +563,8 @@ namespace lms::db::tests std::transform(std::cbegin(clusters), std::cend(clusters), std::back_inserter(clusterIds), [](const ScopedCluster& cluster) { return cluster.getId(); }); auto artists{ Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setClusters(clusterIds))) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); } } @@ -587,26 +587,26 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Cluster::findOrphanIds(session).results.size(), 0); - EXPECT_EQ(ClusterType::findOrphanIds(session).results.size(), 0); - EXPECT_EQ(Artist::findOrphanIds(session).results.size(), 0); - EXPECT_EQ(Release::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(Cluster::findOrphanIds(session).size(), 0); + EXPECT_EQ(ClusterType::findOrphanIds(session).size(), 0); + EXPECT_EQ(Artist::findOrphanIds(session).size(), 0); + EXPECT_EQ(Release::findOrphanIds(session).size(), 0); } { auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster.getId() }))) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results.front(), artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists.front(), artist.getId()); auto releases{ Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist.getId())) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); releases = Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist.getId()).setFilters(Filters{}.setClusters(std::initializer_list{ cluster.getId() }))); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); } } @@ -632,12 +632,12 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto releases{ Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist.getId())) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); releases = Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist.getId()).setFilters(Filters{}.setClusters(std::initializer_list{ cluster1.getId(), cluster2.getId() }))); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); } } @@ -743,17 +743,17 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto genres{ Cluster::find(session, Cluster::FindParameters{}.setTrack(track.getId()).setClusterTypeName("GENRE")) }; - ASSERT_EQ(genres.results.size(), 2); + ASSERT_EQ(genres.size(), 2); const auto moods{ Cluster::find(session, Cluster::FindParameters{}.setTrack(track.getId()).setClusterTypeName("MOOD")) }; - ASSERT_EQ(moods.results.size(), 1); - EXPECT_EQ(moods.results.front()->getId(), mood.getId()); + ASSERT_EQ(moods.size(), 1); + EXPECT_EQ(moods.front()->getId(), mood.getId()); const auto all{ Cluster::find(session, Cluster::FindParameters{}.setTrack(track.getId())) }; - EXPECT_EQ(all.results.size(), 3); + EXPECT_EQ(all.size(), 3); const auto none{ Cluster::find(session, Cluster::FindParameters{}.setTrack(track.getId()).setClusterTypeName("GROUPING")) }; - EXPECT_EQ(none.results.size(), 0); + EXPECT_EQ(none.size(), 0); } } diff --git a/src/libs/database/test/Common.cpp b/src/libs/database/test/Common.cpp index a7e3df7d..af3f22d1 100644 --- a/src/libs/database/test/Common.cpp +++ b/src/libs/database/test/Common.cpp @@ -74,26 +74,6 @@ namespace lms::db::tests session.fullAnalyze(); } - TEST_F(DatabaseFixture, Common_subRangeEmpty) - { - RangeResults results; - results.range = Range{ 0, 0 }; - results.results = {}; - results.moreResults = false; - - { - auto subRange{ results.getSubRange(Range{ 0, 0 }) }; - EXPECT_FALSE(subRange.moreResults); - ASSERT_EQ(subRange.results.size(), 0); - EXPECT_EQ(subRange.range, Range{}); - } - { - auto subRange{ results.getSubRange(Range{ 0, 1 }) }; - EXPECT_FALSE(subRange.moreResults); - ASSERT_EQ(subRange.results.size(), 0); - } - } - TEST_F(DatabaseFixture, Common_subRangeForeach) { struct TestCase @@ -155,55 +135,4 @@ namespace lms::db::tests } } - TEST_F(DatabaseFixture, Common_subRange) - { - RangeResults results; - results.range = Range{ 0, 2 }; - results.results = { 5, 6 }; - results.moreResults = false; - - { - auto subRange{ results.getSubRange(Range{ 0, 1 }) }; - EXPECT_TRUE(subRange.moreResults); - ASSERT_EQ(subRange.results.size(), 1); - EXPECT_EQ(subRange.results.front(), 5); - } - { - auto subRange{ results.getSubRange(Range{ 1, 1 }) }; - EXPECT_FALSE(subRange.moreResults); - ASSERT_EQ(subRange.results.size(), 1); - EXPECT_EQ(subRange.results.front(), 6); - } - { - auto subRange{ results.getSubRange(Range{ 0, 2 }) }; - EXPECT_FALSE(subRange.moreResults); - ASSERT_EQ(subRange.results.size(), 2); - EXPECT_EQ(subRange.results.front(), 5); - EXPECT_EQ(subRange.results.back(), 6); - } - { - auto subRange{ results.getSubRange(Range{}) }; - EXPECT_FALSE(subRange.moreResults); - ASSERT_EQ(subRange.results.size(), 2); - EXPECT_EQ(subRange.results.front(), 5); - EXPECT_EQ(subRange.results.back(), 6); - EXPECT_EQ(subRange.range, results.range); - } - - { - auto subRange{ results.getSubRange(Range{ 1, 0 }) }; - EXPECT_FALSE(subRange.moreResults); - ASSERT_EQ(subRange.results.size(), 1); - EXPECT_EQ(subRange.results.front(), 6); - const Range expectedRange{ 1, 1 }; - EXPECT_EQ(subRange.range, expectedRange); - } - { - auto subRange{ results.getSubRange(Range{ 3, 2 }) }; - EXPECT_FALSE(subRange.moreResults); - ASSERT_EQ(subRange.results.size(), 0); - const Range expectedRange{ 2, 0 }; - EXPECT_EQ(subRange.range, expectedRange); - } - } } // namespace lms::db::tests \ No newline at end of file diff --git a/src/libs/database/test/DatabaseTest.cpp b/src/libs/database/test/DatabaseTest.cpp index 99ac564a..ea8369bc 100644 --- a/src/libs/database/test/DatabaseTest.cpp +++ b/src/libs/database/test/DatabaseTest.cpp @@ -42,19 +42,19 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_TRUE(Release::findOrphanIds(session).results.empty()); - EXPECT_TRUE(Artist::findOrphanIds(session).results.empty()); + EXPECT_TRUE(Release::findOrphanIds(session).empty()); + EXPECT_TRUE(Artist::findOrphanIds(session).empty()); } { auto transaction{ session.createReadTransaction() }; auto releases{ Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist.getId())) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); const auto releaseTracks{ Track::find(session, Track::FindParameters{}.setRelease(release.getId())) }; - EXPECT_EQ(releaseTracks.results.size(), nbTracks); + EXPECT_EQ(releaseTracks.size(), nbTracks); } } @@ -75,8 +75,8 @@ namespace lms::db::tests auto transaction{ session.createWriteTransaction() }; auto releases{ Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist.getId())) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); auto artists{ release->getTrackArtists() }; ASSERT_EQ(artists.size(), 1); @@ -88,7 +88,7 @@ namespace lms::db::tests { { auto transaction{ session.createReadTransaction() }; - EXPECT_TRUE(User::find(session, User::FindParameters{}).results.empty()); + EXPECT_TRUE(User::find(session, User::FindParameters{}).empty()); EXPECT_EQ(User::getCount(session), 0); } @@ -97,7 +97,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(User::find(session, User::FindParameters{}).results.size(), 1); + EXPECT_EQ(User::find(session, User::FindParameters{}).size(), 1); EXPECT_EQ(User::getCount(session), 1); } } diff --git a/src/libs/database/test/Directory.cpp b/src/libs/database/test/Directory.cpp index 6246cd1d..ab4c573d 100644 --- a/src/libs/database/test/Directory.cpp +++ b/src/libs/database/test/Directory.cpp @@ -148,7 +148,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - const auto directories{ Directory::findOrphanIds(session).results }; + const auto directories{ Directory::findOrphanIds(session) }; EXPECT_EQ(directories.size(), 2); } @@ -161,7 +161,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - const auto directories{ Directory::findOrphanIds(session).results }; + const auto directories{ Directory::findOrphanIds(session) }; ASSERT_EQ(directories.size(), 1); EXPECT_EQ(directories.front(), child.getId()); } @@ -182,7 +182,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - const auto directories{ Directory::findRootDirectories(session).results }; + const auto directories{ Directory::findRootDirectories(session) }; ASSERT_EQ(directories.size(), 2); EXPECT_EQ(directories[0]->getId(), parent1.getId()); EXPECT_EQ(directories[1]->getId(), parent2.getId()); @@ -209,7 +209,7 @@ namespace lms::db::tests Directory::FindParameters params; params.setWithNoTrack(true); - auto res{ Directory::find(session, params).results }; + auto res{ Directory::find(session, params) }; ASSERT_EQ(res.size(), 3); EXPECT_EQ(res[0]->getId(), parent.getId()); @@ -228,7 +228,7 @@ namespace lms::db::tests Directory::FindParameters params; params.setWithNoTrack(true); - auto res{ Directory::find(session, params).results }; + auto res{ Directory::find(session, params) }; ASSERT_EQ(res.size(), 2); EXPECT_EQ(res[0]->getId(), parent.getId()); EXPECT_EQ(res[1]->getId(), child1.getId()); @@ -247,7 +247,7 @@ namespace lms::db::tests Directory::FindParameters params; params.setKeywords({ "foo" }); - auto res{ Directory::find(session, params).results }; + auto res{ Directory::find(session, params) }; ASSERT_EQ(res.size(), 2); EXPECT_EQ(res[0]->getId(), child1.getId()); @@ -267,7 +267,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - const auto res{ Directory::findMismatchedLibrary(session, std::nullopt, library->getPath(), library->getId()).results }; + const auto res{ Directory::findMismatchedLibrary(session, std::nullopt, library->getPath(), library->getId()) }; ASSERT_EQ(res.size(), 2); EXPECT_EQ(res[0], parent1.getId()); EXPECT_EQ(res[1], child1.getId()); @@ -283,7 +283,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - const auto res{ Directory::findMismatchedLibrary(session, std::nullopt, library->getPath(), library->getId()).results }; + const auto res{ Directory::findMismatchedLibrary(session, std::nullopt, library->getPath(), library->getId()) }; EXPECT_EQ(res.size(), 0); } } diff --git a/src/libs/database/test/Genre.cpp b/src/libs/database/test/Genre.cpp index 034a3095..9dbd7826 100644 --- a/src/libs/database/test/Genre.cpp +++ b/src/libs/database/test/Genre.cpp @@ -65,8 +65,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto orphans{ Genre::findOrphanIds(session) }; - ASSERT_EQ(orphans.results.size(), 1); - EXPECT_EQ(orphans.results.front(), genre.getId()); + ASSERT_EQ(orphans.size(), 1); + EXPECT_EQ(orphans.front(), genre.getId()); } } @@ -78,7 +78,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Genre::findOrphanIds(session).results.size(), 2); + EXPECT_EQ(Genre::findOrphanIds(session).size(), 2); EXPECT_EQ(track->getGenres().size(), 0); EXPECT_EQ(track->getGenreIds().size(), 0); EXPECT_EQ(Genre::computeTrackCount(session, genre1.getId()), 0); @@ -94,15 +94,15 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto genres{ Genre::findIds(session, Genre::FindParameters{}.setTrack(track.getId())) }; - ASSERT_EQ(genres.results.size(), 1); - EXPECT_EQ(genres.results.front(), genre1.getId()); + ASSERT_EQ(genres.size(), 1); + EXPECT_EQ(genres.front(), genre1.getId()); EXPECT_EQ(Genre::computeTrackCount(session, genre1.getId()), 1); EXPECT_EQ(Genre::computeTrackCount(session, genre2.getId()), 0); const auto orphans{ Genre::findOrphanIds(session) }; - ASSERT_EQ(orphans.results.size(), 1); - EXPECT_EQ(orphans.results.front(), genre2.getId()); + ASSERT_EQ(orphans.size(), 1); + EXPECT_EQ(orphans.front(), genre2.getId()); const auto trackGenres{ track->getGenres() }; ASSERT_EQ(trackGenres.size(), 1); @@ -116,11 +116,11 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setGenre(genre1.getId()))) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); const auto tracks2{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setGenre(genre2.getId()))) }; - EXPECT_EQ(tracks2.results.size(), 0); + EXPECT_EQ(tracks2.size(), 0); } } @@ -139,7 +139,7 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; EXPECT_EQ(Genre::computeTrackCount(session, genre1.getId()), 1); EXPECT_EQ(Genre::computeTrackCount(session, genre2.getId()), 1); - EXPECT_EQ(Genre::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(Genre::findOrphanIds(session).size(), 0); const auto trackGenres{ track->getGenres() }; EXPECT_EQ(trackGenres.size(), 2); @@ -148,12 +148,12 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setGenre(genre1.getId()))) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); const auto tracks2{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setGenre(genre2.getId()))) }; - ASSERT_EQ(tracks2.results.size(), 1); - EXPECT_EQ(tracks2.results.front(), track.getId()); + ASSERT_EQ(tracks2.size(), 1); + EXPECT_EQ(tracks2.front(), track.getId()); } } @@ -200,10 +200,10 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto genres{ Genre::findIds(session, Genre::FindParameters{}.setSortMethod(GenreSortMethod::Name)) }; - ASSERT_EQ(genres.results.size(), 3); - EXPECT_EQ(genres.results[0], g2.getId()); - EXPECT_EQ(genres.results[1], g3.getId()); - EXPECT_EQ(genres.results[2], g1.getId()); + ASSERT_EQ(genres.size(), 3); + EXPECT_EQ(genres[0], g2.getId()); + EXPECT_EQ(genres[1], g3.getId()); + EXPECT_EQ(genres[2], g1.getId()); } } @@ -225,9 +225,9 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto genres{ Genre::findIds(session, Genre::FindParameters{}.setSortMethod(GenreSortMethod::TrackCountDesc)) }; - ASSERT_EQ(genres.results.size(), 2); - EXPECT_EQ(genres.results[0], g1.getId()); - EXPECT_EQ(genres.results[1], g2.getId()); + ASSERT_EQ(genres.size(), 2); + EXPECT_EQ(genres[0], g1.getId()); + EXPECT_EQ(genres[1], g2.getId()); } } } // namespace lms::db::tests diff --git a/src/libs/database/test/Grouping.cpp b/src/libs/database/test/Grouping.cpp index dcd92973..52b5d644 100644 --- a/src/libs/database/test/Grouping.cpp +++ b/src/libs/database/test/Grouping.cpp @@ -63,8 +63,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto orphans{ Grouping::findOrphanIds(session) }; - ASSERT_EQ(orphans.results.size(), 1); - EXPECT_EQ(orphans.results.front(), grouping.getId()); + ASSERT_EQ(orphans.size(), 1); + EXPECT_EQ(orphans.front(), grouping.getId()); } } @@ -76,7 +76,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Grouping::findOrphanIds(session).results.size(), 2); + EXPECT_EQ(Grouping::findOrphanIds(session).size(), 2); EXPECT_EQ(track->getGroupings().size(), 0); EXPECT_EQ(track->getGroupingIds().size(), 0); } @@ -90,12 +90,12 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto groupings{ Grouping::findIds(session, Grouping::FindParameters{}.setTrack(track.getId())) }; - ASSERT_EQ(groupings.results.size(), 1); - EXPECT_EQ(groupings.results.front(), grouping1.getId()); + ASSERT_EQ(groupings.size(), 1); + EXPECT_EQ(groupings.front(), grouping1.getId()); const auto orphans{ Grouping::findOrphanIds(session) }; - ASSERT_EQ(orphans.results.size(), 1); - EXPECT_EQ(orphans.results.front(), grouping2.getId()); + ASSERT_EQ(orphans.size(), 1); + EXPECT_EQ(orphans.front(), grouping2.getId()); const auto trackGroupings{ track->getGroupings() }; ASSERT_EQ(trackGroupings.size(), 1); @@ -109,11 +109,11 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setGrouping(grouping1.getId()))) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); const auto tracks2{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setGrouping(grouping2.getId()))) }; - EXPECT_EQ(tracks2.results.size(), 0); + EXPECT_EQ(tracks2.size(), 0); } } @@ -130,7 +130,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Grouping::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(Grouping::findOrphanIds(session).size(), 0); const auto trackGroupings{ track->getGroupings() }; EXPECT_EQ(trackGroupings.size(), 2); @@ -139,12 +139,12 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setGrouping(grouping1.getId()))) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); const auto tracks2{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setGrouping(grouping2.getId()))) }; - ASSERT_EQ(tracks2.results.size(), 1); - EXPECT_EQ(tracks2.results.front(), track.getId()); + ASSERT_EQ(tracks2.size(), 1); + EXPECT_EQ(tracks2.front(), track.getId()); } } @@ -157,10 +157,10 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto groupings{ Grouping::findIds(session, Grouping::FindParameters{}.setSortMethod(GroupingSortMethod::Name)) }; - ASSERT_EQ(groupings.results.size(), 3); - EXPECT_EQ(groupings.results[0], g2.getId()); - EXPECT_EQ(groupings.results[1], g3.getId()); - EXPECT_EQ(groupings.results[2], g1.getId()); + ASSERT_EQ(groupings.size(), 3); + EXPECT_EQ(groupings[0], g2.getId()); + EXPECT_EQ(groupings[1], g3.getId()); + EXPECT_EQ(groupings[2], g1.getId()); } } @@ -182,9 +182,9 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto groupings{ Grouping::findIds(session, Grouping::FindParameters{}.setSortMethod(GroupingSortMethod::TrackCountDesc)) }; - ASSERT_EQ(groupings.results.size(), 2); - EXPECT_EQ(groupings.results[0], g1.getId()); - EXPECT_EQ(groupings.results[1], g2.getId()); + ASSERT_EQ(groupings.size(), 2); + EXPECT_EQ(groupings[0], g1.getId()); + EXPECT_EQ(groupings[1], g2.getId()); } } } // namespace lms::db::tests diff --git a/src/libs/database/test/Image.cpp b/src/libs/database/test/Image.cpp index 129e1dc2..f52a3134 100644 --- a/src/libs/database/test/Image.cpp +++ b/src/libs/database/test/Image.cpp @@ -83,7 +83,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Image::find(session, Image::FindParameters{}.setDirectory(directory.getId())).results.size(), 0); + EXPECT_EQ(Image::find(session, Image::FindParameters{}.setDirectory(directory.getId())).size(), 0); } { @@ -93,7 +93,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - const auto results{ Image::find(session, Image::FindParameters{}.setDirectory(directory.getId())).results }; + const auto results{ Image::find(session, Image::FindParameters{}.setDirectory(directory.getId())) }; ASSERT_EQ(results.size(), 1); EXPECT_EQ(results.front()->getId(), image.getId()); } @@ -138,8 +138,8 @@ namespace lms::db::tests Image::FindParameters params; params.setFileStem(fileStem); const auto results{ Image::find(session, params) }; - ASSERT_EQ(results.results.size(), 1); - EXPECT_EQ(results.results[0]->getId(), image.getId()); + ASSERT_EQ(results.size(), 1); + EXPECT_EQ(results[0]->getId(), image.getId()); } { @@ -147,8 +147,8 @@ namespace lms::db::tests Image::FindParameters params; params.setFileStem(fileStem, Image::FindParameters::ProcessWildcards{ true }); const auto results{ Image::find(session, params) }; - ASSERT_EQ(results.results.size(), 1); - EXPECT_EQ(results.results[0]->getId(), image.getId()); + ASSERT_EQ(results.size(), 1); + EXPECT_EQ(results[0]->getId(), image.getId()); } { @@ -156,7 +156,7 @@ namespace lms::db::tests Image::FindParameters params; params.setFileStem("nonexistent"); const auto results{ Image::find(session, params) }; - EXPECT_EQ(results.results.size(), 0); + EXPECT_EQ(results.size(), 0); } { @@ -164,7 +164,7 @@ namespace lms::db::tests Image::FindParameters params; params.setFileStem("ima*"); const auto results{ Image::find(session, params) }; - ASSERT_EQ(results.results.size(), 0); + ASSERT_EQ(results.size(), 0); } { @@ -172,8 +172,8 @@ namespace lms::db::tests Image::FindParameters params; params.setFileStem("ima*", Image::FindParameters::ProcessWildcards{ true }); const auto results{ Image::find(session, params) }; - ASSERT_EQ(results.results.size(), 1); - EXPECT_EQ(results.results[0]->getId(), image.getId()); + ASSERT_EQ(results.size(), 1); + EXPECT_EQ(results[0]->getId(), image.getId()); } { @@ -181,8 +181,8 @@ namespace lms::db::tests Image::FindParameters params; params.setFileStem("*ge", Image::FindParameters::ProcessWildcards{ true }); const auto results{ Image::find(session, params) }; - ASSERT_EQ(results.results.size(), 1); - EXPECT_EQ(results.results[0]->getId(), image.getId()); + ASSERT_EQ(results.size(), 1); + EXPECT_EQ(results[0]->getId(), image.getId()); } { @@ -190,8 +190,8 @@ namespace lms::db::tests Image::FindParameters params; params.setFileStem("*g*", Image::FindParameters::ProcessWildcards{ true }); const auto results{ Image::find(session, params) }; - ASSERT_EQ(results.results.size(), 1); - EXPECT_EQ(results.results[0]->getId(), image.getId()); + ASSERT_EQ(results.size(), 1); + EXPECT_EQ(results[0]->getId(), image.getId()); } { @@ -199,8 +199,8 @@ namespace lms::db::tests Image::FindParameters params; params.setFileStem("*", Image::FindParameters::ProcessWildcards{ true }); const auto results{ Image::find(session, params) }; - ASSERT_EQ(results.results.size(), 1); - EXPECT_EQ(results.results[0]->getId(), image.getId()); + ASSERT_EQ(results.size(), 1); + EXPECT_EQ(results[0]->getId(), image.getId()); } { @@ -208,7 +208,7 @@ namespace lms::db::tests Image::FindParameters params; params.setFileStem("ima%"); const auto results{ Image::find(session, params) }; - ASSERT_EQ(results.results.size(), 0); + ASSERT_EQ(results.size(), 0); } { @@ -216,7 +216,7 @@ namespace lms::db::tests Image::FindParameters params; params.setFileStem("ima%", Image::FindParameters::ProcessWildcards{ true }); const auto results{ Image::find(session, params) }; - ASSERT_EQ(results.results.size(), 0); + ASSERT_EQ(results.size(), 0); } } diff --git a/src/libs/database/test/Language.cpp b/src/libs/database/test/Language.cpp index dcf73d96..0139968f 100644 --- a/src/libs/database/test/Language.cpp +++ b/src/libs/database/test/Language.cpp @@ -63,8 +63,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto orphans{ Language::findOrphanIds(session) }; - ASSERT_EQ(orphans.results.size(), 1); - EXPECT_EQ(orphans.results.front(), language.getId()); + ASSERT_EQ(orphans.size(), 1); + EXPECT_EQ(orphans.front(), language.getId()); } } @@ -76,7 +76,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Language::findOrphanIds(session).results.size(), 2); + EXPECT_EQ(Language::findOrphanIds(session).size(), 2); EXPECT_EQ(track->getLanguages().size(), 0); EXPECT_EQ(track->getLanguageIds().size(), 0); } @@ -90,12 +90,12 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto languages{ Language::findIds(session, Language::FindParameters{}.setTrack(track.getId())) }; - ASSERT_EQ(languages.results.size(), 1); - EXPECT_EQ(languages.results.front(), language1.getId()); + ASSERT_EQ(languages.size(), 1); + EXPECT_EQ(languages.front(), language1.getId()); const auto orphans{ Language::findOrphanIds(session) }; - ASSERT_EQ(orphans.results.size(), 1); - EXPECT_EQ(orphans.results.front(), language2.getId()); + ASSERT_EQ(orphans.size(), 1); + EXPECT_EQ(orphans.front(), language2.getId()); const auto trackLanguages{ track->getLanguages() }; ASSERT_EQ(trackLanguages.size(), 1); @@ -109,11 +109,11 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setLanguage(language1.getId()))) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); const auto tracks2{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setLanguage(language2.getId()))) }; - EXPECT_EQ(tracks2.results.size(), 0); + EXPECT_EQ(tracks2.size(), 0); } } @@ -130,7 +130,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Language::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(Language::findOrphanIds(session).size(), 0); const auto trackLanguages{ track->getLanguages() }; EXPECT_EQ(trackLanguages.size(), 2); @@ -139,12 +139,12 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setLanguage(language1.getId()))) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); const auto tracks2{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setLanguage(language2.getId()))) }; - ASSERT_EQ(tracks2.results.size(), 1); - EXPECT_EQ(tracks2.results.front(), track.getId()); + ASSERT_EQ(tracks2.size(), 1); + EXPECT_EQ(tracks2.front(), track.getId()); } } @@ -157,10 +157,10 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto languages{ Language::findIds(session, Language::FindParameters{}.setSortMethod(LanguageSortMethod::Name)) }; - ASSERT_EQ(languages.results.size(), 3); - EXPECT_EQ(languages.results[0], l2.getId()); - EXPECT_EQ(languages.results[1], l3.getId()); - EXPECT_EQ(languages.results[2], l1.getId()); + ASSERT_EQ(languages.size(), 3); + EXPECT_EQ(languages[0], l2.getId()); + EXPECT_EQ(languages[1], l3.getId()); + EXPECT_EQ(languages[2], l1.getId()); } } @@ -182,9 +182,9 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto languages{ Language::findIds(session, Language::FindParameters{}.setSortMethod(LanguageSortMethod::TrackCountDesc)) }; - ASSERT_EQ(languages.results.size(), 2); - EXPECT_EQ(languages.results[0], l1.getId()); - EXPECT_EQ(languages.results[1], l2.getId()); + ASSERT_EQ(languages.size(), 2); + EXPECT_EQ(languages[0], l1.getId()); + EXPECT_EQ(languages[1], l2.getId()); } } } // namespace lms::db::tests diff --git a/src/libs/database/test/Listen.cpp b/src/libs/database/test/Listen.cpp index 2b7dfbdb..bbe503b2 100644 --- a/src/libs/database/test/Listen.cpp +++ b/src/libs/database/test/Listen.cpp @@ -69,7 +69,7 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto listens{ Listen::find(session, Listen::FindParameters{}.setUser(user->getId()).setScrobblingBackend(ScrobblingBackend::ListenBrainz)) }; - EXPECT_EQ(listens.results.size(), 0); + EXPECT_EQ(listens.size(), 0); } { @@ -77,18 +77,17 @@ namespace lms::db::tests { auto listens{ Listen::find(session, Listen::FindParameters{}.setUser(user->getId()).setScrobblingBackend(ScrobblingBackend::Internal)) }; - EXPECT_EQ(listens.moreResults, false); - ASSERT_EQ(listens.results.size(), 1); - EXPECT_EQ(listens.results.front(), listen->getId()); + ASSERT_EQ(listens.size(), 1); + EXPECT_EQ(listens.front(), listen->getId()); } { auto listens{ Listen::find(session, Listen::FindParameters{}.setUser(user->getId()).setScrobblingBackend(ScrobblingBackend::Internal).setSyncState(SyncState::PendingAdd)) }; - EXPECT_EQ(listens.results.size(), 1); + EXPECT_EQ(listens.size(), 1); } { auto listens{ Listen::find(session, Listen::FindParameters{}.setUser(user->getId()).setScrobblingBackend(ScrobblingBackend::Internal).setSyncState(SyncState::Synchronized)) }; - EXPECT_EQ(listens.results.size(), 0); + EXPECT_EQ(listens.size(), 0); } } } @@ -105,10 +104,10 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto listens{ Listen::find(session, Listen::FindParameters{}.setUser(user->getId()).setScrobblingBackend(ScrobblingBackend::Internal)) }; - ASSERT_EQ(listens.results.size(), 3); - EXPECT_EQ(listens.results[0], listen1.getId()); - EXPECT_EQ(listens.results[1], listen2.getId()); - EXPECT_EQ(listens.results[2], listen3.getId()); + ASSERT_EQ(listens.size(), 3); + EXPECT_EQ(listens[0], listen1.getId()); + EXPECT_EQ(listens[1], listen2.getId()); + EXPECT_EQ(listens[2], listen3.getId()); } } @@ -157,11 +156,9 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); const auto artists{ Listen::getTopArtists(session, params) }; - EXPECT_EQ(artists.results.size(), 0); - EXPECT_EQ(artists.moreResults, false); + EXPECT_EQ(artists.size(), 0); } ScopedTrack track2{ session }; @@ -179,32 +176,37 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto artists{ Listen::getTopArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results[0], artist1->getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist1->getId()); + } + { + auto transaction{ session.createWriteTransaction() }; + user.lockAndGet().modify()->setScrobblingBackend(ScrobblingBackend::ListenBrainz); } { auto transaction{ session.createReadTransaction() }; Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::ListenBrainz); auto artists{ Listen::getTopArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 0); + ASSERT_EQ(artists.size(), 0); } { auto transaction{ session.createReadTransaction() }; Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::ListenBrainz); params.setTrackArtistLinkType(TrackArtistLinkType::Producer); auto artists{ Listen::getTopArtists(session, params) }; - EXPECT_EQ(artists.results.size(), 0); + EXPECT_EQ(artists.size(), 0); + } + { + auto transaction{ session.createWriteTransaction() }; + user.lockAndGet().modify()->setScrobblingBackend(ScrobblingBackend::Internal); } { @@ -216,11 +218,10 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster->getId() }); auto artists{ Listen::getTopArtists(session, params) }; - EXPECT_EQ(artists.results.size(), 0); + EXPECT_EQ(artists.size(), 0); } } } @@ -245,10 +246,9 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto artists{ Listen::getTopArtists(session, params) }; - EXPECT_EQ(artists.results.size(), 0); + EXPECT_EQ(artists.size(), 0); } ScopedListen listen1{ session, user.lockAndGet(), track1.lockAndGet(), ScrobblingBackend::Internal, dateTime.addSecs(1) }; @@ -257,11 +257,10 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto artists{ Listen::getTopArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results[0], artist1->getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist1->getId()); } ScopedListen listen2{ session, user.lockAndGet(), track2.lockAndGet(), ScrobblingBackend::Internal, dateTime.addSecs(2) }; @@ -271,25 +270,22 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto artists{ Listen::getTopArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 2); - EXPECT_EQ(artists.results[0], artist2->getId()); - EXPECT_EQ(artists.results[1], artist1->getId()); + ASSERT_EQ(artists.size(), 2); + EXPECT_EQ(artists[0], artist2->getId()); + EXPECT_EQ(artists[1], artist1->getId()); } { auto transaction{ session.createReadTransaction() }; Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.setRange(Range{ 0, 1 }); auto artists{ Listen::getTopArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.moreResults, true); - EXPECT_EQ(artists.results[0], artist2->getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist2->getId()); } } @@ -313,11 +309,10 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster.getId() }); auto artists{ Listen::getTopArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 0); + ASSERT_EQ(artists.size(), 0); } { auto transaction{ session.createWriteTransaction() }; @@ -328,12 +323,11 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster.getId() }); auto artists{ Listen::getTopArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results[0], artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist.getId()); } } @@ -352,12 +346,10 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user.getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setMediaLibrary(library.getId()); const auto artists{ Listen::getTopArtists(session, params) }; - EXPECT_EQ(artists.results.size(), 0); - EXPECT_EQ(artists.moreResults, false); + EXPECT_EQ(artists.size(), 0); } { @@ -372,34 +364,31 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user.getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto artists{ Listen::getTopArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results[0], artist->getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist->getId()); } { auto transaction{ session.createReadTransaction() }; Listen::ArtistStatsFindParameters params; params.setUser(user.getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setMediaLibrary(library.getId()); auto artists{ Listen::getTopArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results[0], artist->getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist->getId()); } { auto transaction{ session.createReadTransaction() }; Listen::ArtistStatsFindParameters params; params.setUser(user.getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setMediaLibrary(otherLibrary.getId()); auto artists{ Listen::getTopArtists(session, params) }; - EXPECT_EQ(artists.results.size(), 0); + EXPECT_EQ(artists.size(), 0); } } @@ -419,11 +408,9 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto releases{ Listen::getTopReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } ScopedListen listen{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime }; @@ -433,23 +420,23 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto releases{ Listen::getTopReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results[0], release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases[0], release.getId()); + } + { + auto transaction{ session.createWriteTransaction() }; + user.lockAndGet().modify()->setScrobblingBackend(ScrobblingBackend::ListenBrainz); } { auto transaction{ session.createReadTransaction() }; Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::ListenBrainz); auto releases{ Listen::getTopReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } } @@ -474,12 +461,10 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto releases{ Listen::getTopReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results[0], release1.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases[0], release1.getId()); } ScopedListen listen2{ session, user.lockAndGet(), track2.lockAndGet(), ScrobblingBackend::Internal, dateTime }; ScopedListen listen3{ session, user.lockAndGet(), track2.lockAndGet(), ScrobblingBackend::Internal, dateTime }; @@ -488,13 +473,11 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto releases{ Listen::getTopReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results[0], release2.getId()); - EXPECT_EQ(releases.results[1], release1.getId()); + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases[0], release2.getId()); + EXPECT_EQ(releases[1], release1.getId()); } ScopedListen listen4{ session, user.lockAndGet(), track1.lockAndGet(), ScrobblingBackend::Internal, dateTime }; ScopedListen listen5{ session, user.lockAndGet(), track1.lockAndGet(), ScrobblingBackend::Internal, dateTime }; @@ -503,13 +486,11 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto releases{ Listen::getTopReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results[0], release1.getId()); - EXPECT_EQ(releases.results[1], release2.getId()); + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases[0], release1.getId()); + EXPECT_EQ(releases[1], release2.getId()); } } @@ -533,11 +514,10 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster.getId() }); auto releases{ Listen::getTopReleases(session, params) }; - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } { auto transaction{ session.createWriteTransaction() }; @@ -549,12 +529,11 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster.getId() }); auto releases{ Listen::getTopReleases(session, params) }; - EXPECT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results[0], release.getId()); + EXPECT_EQ(releases.size(), 1); + EXPECT_EQ(releases[0], release.getId()); } } @@ -578,12 +557,10 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setMediaLibrary(library.getId()); auto releases{ Listen::getTopReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } ScopedListen listen{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime }; @@ -593,25 +570,21 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setMediaLibrary(library.getId()); auto releases{ Listen::getTopReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results[0], release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases[0], release.getId()); } { auto transaction{ session.createReadTransaction() }; Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setMediaLibrary(otherLibrary.getId()); auto releases{ Listen::getTopReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } } @@ -626,11 +599,9 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto tracks{ Listen::getTopTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 0); + ASSERT_EQ(tracks.size(), 0); } ScopedListen listen{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime }; @@ -640,23 +611,23 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto tracks{ Listen::getTopTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results[0], track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks[0], track.getId()); + } + { + auto transaction{ session.createWriteTransaction() }; + user.lockAndGet().modify()->setScrobblingBackend(ScrobblingBackend::ListenBrainz); } { auto transaction{ session.createReadTransaction() }; Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::ListenBrainz); auto tracks{ Listen::getTopTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } } @@ -672,12 +643,10 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.setArtist(artist->getId()); auto tracks{ Listen::getTopTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 0); + ASSERT_EQ(tracks.size(), 0); } ScopedListen listen{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime }; @@ -687,11 +656,10 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.setArtist(artist->getId()); auto tracks{ Listen::getTopTracks(session, params) }; - ASSERT_EQ(tracks.results.size(), 0); + ASSERT_EQ(tracks.size(), 0); } { @@ -704,13 +672,11 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.setArtist(artist->getId()); auto tracks{ Listen::getTopTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results[0], track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks[0], track.getId()); } } @@ -727,12 +693,10 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto tracks{ Listen::getTopTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results[0], track1.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks[0], track1.getId()); } ScopedListen listen2{ session, user.lockAndGet(), track2.lockAndGet(), ScrobblingBackend::Internal, dateTime }; ScopedListen listen3{ session, user.lockAndGet(), track2.lockAndGet(), ScrobblingBackend::Internal, dateTime }; @@ -741,13 +705,11 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto tracks{ Listen::getTopTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 2); - EXPECT_EQ(tracks.results[0], track2.getId()); - EXPECT_EQ(tracks.results[1], track1.getId()); + ASSERT_EQ(tracks.size(), 2); + EXPECT_EQ(tracks[0], track2.getId()); + EXPECT_EQ(tracks[1], track1.getId()); } ScopedListen listen4{ session, user.lockAndGet(), track1.lockAndGet(), ScrobblingBackend::Internal, dateTime }; ScopedListen listen5{ session, user.lockAndGet(), track1.lockAndGet(), ScrobblingBackend::Internal, dateTime }; @@ -756,13 +718,11 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto tracks{ Listen::getTopTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 2); - EXPECT_EQ(tracks.results[0], track1.getId()); - EXPECT_EQ(tracks.results[1], track2.getId()); + ASSERT_EQ(tracks.size(), 2); + EXPECT_EQ(tracks[0], track1.getId()); + EXPECT_EQ(tracks[1], track2.getId()); } } @@ -780,11 +740,10 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster.getId() }); auto tracks{ Listen::getTopTracks(session, params) }; - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } { auto transaction{ session.createWriteTransaction() }; @@ -796,12 +755,11 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster.getId() }); auto tracks{ Listen::getTopTracks(session, params) }; - EXPECT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results[0], track.getId()); + EXPECT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks[0], track.getId()); } } @@ -818,12 +776,10 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user.getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setMediaLibrary(library.getId()); auto tracks{ Listen::getTopTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 0); + ASSERT_EQ(tracks.size(), 0); } { @@ -838,25 +794,21 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setMediaLibrary(library.getId()); auto tracks{ Listen::getTopTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results[0], track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks[0], track.getId()); } { auto transaction{ session.createReadTransaction() }; Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setMediaLibrary(otherLibrary.getId()); auto tracks{ Listen::getTopTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } } @@ -878,12 +830,10 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.setReleaseArtistsOnly(true); auto artists{ Listen::getRecentArtists(session, params) }; - EXPECT_EQ(artists.results.size(), 0); - EXPECT_EQ(artists.moreResults, false); + EXPECT_EQ(artists.size(), 0); } const Wt::WDateTime dateTime{ Wt::WDate{ 2000, 1, 2 }, Wt::WTime{ 12, 0, 1 } }; @@ -894,12 +844,11 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.setReleaseArtistsOnly(true); auto artists{ Listen::getRecentArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results[0], artist->getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist->getId()); } } @@ -919,11 +868,9 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto artists{ Listen::getRecentArtists(session, params) }; - EXPECT_EQ(artists.results.size(), 0); - EXPECT_EQ(artists.moreResults, false); + EXPECT_EQ(artists.size(), 0); } const Wt::WDateTime dateTime{ Wt::WDate{ 2000, 1, 2 }, Wt::WTime{ 12, 0, 1 } }; @@ -934,11 +881,10 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto artists{ Listen::getRecentArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results[0], artist->getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist->getId()); } { @@ -946,34 +892,38 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.setReleaseArtistsOnly(true); auto artists{ Listen::getRecentArtists(session, params) }; - EXPECT_EQ(artists.results.size(), 0); - EXPECT_EQ(artists.moreResults, false); + EXPECT_EQ(artists.size(), 0); } + { + auto transaction{ session.createWriteTransaction() }; + user.lockAndGet().modify()->setScrobblingBackend(ScrobblingBackend::ListenBrainz); + } { auto transaction{ session.createReadTransaction() }; Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::ListenBrainz); auto artists{ Listen::getRecentArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 0); + ASSERT_EQ(artists.size(), 0); + } + { + auto transaction{ session.createWriteTransaction() }; + user.lockAndGet().modify()->setScrobblingBackend(ScrobblingBackend::Internal); } { auto transaction{ session.createReadTransaction() }; Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.setTrackArtistLinkType(TrackArtistLinkType::Producer); auto artists{ Listen::getRecentArtists(session, params) }; - EXPECT_EQ(artists.results.size(), 0); + EXPECT_EQ(artists.size(), 0); } { ScopedClusterType clusterType{ session, "MyType" }; @@ -984,11 +934,10 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster->getId() }); auto artists{ Listen::getRecentArtists(session, params) }; - EXPECT_EQ(artists.results.size(), 0); + EXPECT_EQ(artists.size(), 0); } } } @@ -1013,10 +962,9 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto artists{ Listen::getRecentArtists(session, params) }; - EXPECT_EQ(artists.results.size(), 0); + EXPECT_EQ(artists.size(), 0); } ScopedListen listen1{ session, user.lockAndGet(), track1.lockAndGet(), ScrobblingBackend::Internal, dateTime.addSecs(1) }; @@ -1025,11 +973,10 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto artists{ Listen::getRecentArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results[0], artist1->getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist1->getId()); } ScopedListen listen2{ session, user.lockAndGet(), track2.lockAndGet(), ScrobblingBackend::Internal, dateTime.addSecs(2) }; { @@ -1037,12 +984,11 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto artists{ Listen::getRecentArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 2); - EXPECT_EQ(artists.results[0], artist2->getId()); - EXPECT_EQ(artists.results[1], artist1->getId()); + ASSERT_EQ(artists.size(), 2); + EXPECT_EQ(artists[0], artist2->getId()); + EXPECT_EQ(artists[1], artist1->getId()); } ScopedListen listen3{ session, user.lockAndGet(), track1.lockAndGet(), ScrobblingBackend::Internal, dateTime.addSecs(-1) }; { @@ -1050,13 +996,11 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.setRange(Range{ 0, 1 }); auto artists{ Listen::getRecentArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.moreResults, true); - EXPECT_EQ(artists.results[0], artist2->getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist2->getId()); } } @@ -1080,11 +1024,10 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster.getId() }); auto artists{ Listen::getRecentArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 0); + ASSERT_EQ(artists.size(), 0); } { auto transaction{ session.createWriteTransaction() }; @@ -1095,12 +1038,11 @@ namespace lms::db::tests Listen::ArtistStatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster.getId() }); auto artists{ Listen::getRecentArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results[0], artist.getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist.getId()); } } @@ -1128,8 +1070,8 @@ namespace lms::db::tests params.filters.setMediaLibrary(library.getId()); auto artists{ Listen::getRecentArtists(session, params) }; - ASSERT_EQ(artists.results.size(), 1); - EXPECT_EQ(artists.results[0], artist->getId()); + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist->getId()); } { auto transaction{ session.createReadTransaction() }; @@ -1138,7 +1080,7 @@ namespace lms::db::tests params.filters.setMediaLibrary(otherLibrary.getId()); auto artists{ Listen::getRecentArtists(session, params) }; - EXPECT_EQ(artists.results.size(), 0); + EXPECT_EQ(artists.size(), 0); } } @@ -1158,11 +1100,9 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto releases{ Listen::getRecentReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - ASSERT_EQ(releases.results.size(), 0); + ASSERT_EQ(releases.size(), 0); } const Wt::WDateTime dateTime{ Wt::WDate{ 2000, 1, 2 }, Wt::WTime{ 12, 0, 1 } }; @@ -1173,23 +1113,23 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto releases{ Listen::getRecentReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results[0], release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases[0], release.getId()); + } + { + auto transaction{ session.createWriteTransaction() }; + user.lockAndGet().modify()->setScrobblingBackend(ScrobblingBackend::ListenBrainz); } { auto transaction{ session.createReadTransaction() }; Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::ListenBrainz); auto releases{ Listen::getRecentReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } } @@ -1324,12 +1264,10 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto releases{ Listen::getRecentReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results[0], release2.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases[0], release2.getId()); } ScopedListen listen2{ session, user.lockAndGet(), track1.lockAndGet(), ScrobblingBackend::Internal, dateTime.addSecs(1) }; @@ -1338,13 +1276,11 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto releases{ Listen::getRecentReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results[0], release1.getId()); - EXPECT_EQ(releases.results[1], release2.getId()); + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases[0], release1.getId()); + EXPECT_EQ(releases[1], release2.getId()); } ScopedListen listen3{ session, user.lockAndGet(), track2.lockAndGet(), ScrobblingBackend::Internal, dateTime.addSecs(2) }; @@ -1353,13 +1289,11 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto releases{ Listen::getRecentReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results[0], release2.getId()); - EXPECT_EQ(releases.results[1], release1.getId()); + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases[0], release2.getId()); + EXPECT_EQ(releases[1], release1.getId()); } ScopedListen listen4{ session, user.lockAndGet(), track1.lockAndGet(), ScrobblingBackend::Internal, dateTime.addSecs(-1) }; @@ -1368,13 +1302,11 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto releases{ Listen::getRecentReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results[0], release2.getId()); - EXPECT_EQ(releases.results[1], release1.getId()); + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases[0], release2.getId()); + EXPECT_EQ(releases[1], release1.getId()); } } @@ -1395,11 +1327,10 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster.getId() }); auto releases{ Listen::getRecentReleases(session, params) }; - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } const Wt::WDateTime dateTime{ Wt::WDate{ 2000, 1, 2 }, Wt::WTime{ 12, 0, 1 } }; @@ -1410,11 +1341,10 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster.getId() }); auto releases{ Listen::getRecentReleases(session, params) }; - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } { @@ -1426,12 +1356,11 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster.getId() }); auto releases{ Listen::getRecentReleases(session, params) }; - EXPECT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results[0], release.getId()); + EXPECT_EQ(releases.size(), 1); + EXPECT_EQ(releases[0], release.getId()); } } @@ -1459,9 +1388,8 @@ namespace lms::db::tests params.filters.setMediaLibrary(library.getId()); auto releases{ Listen::getRecentReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results[0], release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases[0], release.getId()); } { auto transaction{ session.createReadTransaction() }; @@ -1470,8 +1398,7 @@ namespace lms::db::tests params.filters.setMediaLibrary(otherLibrary.getId()); auto releases{ Listen::getRecentReleases(session, params) }; - EXPECT_EQ(releases.moreResults, false); - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } } @@ -1485,11 +1412,9 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto tracks{ Listen::getRecentTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 0); + ASSERT_EQ(tracks.size(), 0); } const Wt::WDateTime dateTime{ Wt::WDate{ 2000, 1, 2 }, Wt::WTime{ 12, 0, 1 } }; @@ -1500,24 +1425,24 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto tracks{ Listen::getRecentTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results[0], track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks[0], track.getId()); } + { + auto transaction{ session.createWriteTransaction() }; + user.lockAndGet().modify()->setScrobblingBackend(ScrobblingBackend::ListenBrainz); + } { auto transaction{ session.createReadTransaction() }; Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::ListenBrainz); auto tracks{ Listen::getRecentTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } } @@ -1543,9 +1468,8 @@ namespace lms::db::tests params.filters.setMediaLibrary(library.getId()); auto tracks{ Listen::getRecentTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results[0], track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks[0], track.getId()); } { @@ -1555,8 +1479,7 @@ namespace lms::db::tests params.filters.setMediaLibrary(otherLibrary.getId()); auto tracks{ Listen::getRecentTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } } @@ -1701,12 +1624,10 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto tracks{ Listen::getRecentTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results[0], track2.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks[0], track2.getId()); } ScopedListen listen2{ session, user.lockAndGet(), track1.lockAndGet(), ScrobblingBackend::Internal, dateTime.addSecs(1) }; @@ -1715,13 +1636,11 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto tracks{ Listen::getRecentTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 2); - EXPECT_EQ(tracks.results[0], track1.getId()); - EXPECT_EQ(tracks.results[1], track2.getId()); + ASSERT_EQ(tracks.size(), 2); + EXPECT_EQ(tracks[0], track1.getId()); + EXPECT_EQ(tracks[1], track2.getId()); } ScopedListen listen3{ session, user.lockAndGet(), track2.lockAndGet(), ScrobblingBackend::Internal, dateTime.addSecs(2) }; @@ -1730,13 +1649,11 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto tracks{ Listen::getRecentTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 2); - EXPECT_EQ(tracks.results[0], track2.getId()); - EXPECT_EQ(tracks.results[1], track1.getId()); + ASSERT_EQ(tracks.size(), 2); + EXPECT_EQ(tracks[0], track2.getId()); + EXPECT_EQ(tracks[1], track1.getId()); } ScopedListen listen4{ session, user.lockAndGet(), track1.lockAndGet(), ScrobblingBackend::Internal, dateTime.addSecs(-1) }; @@ -1745,13 +1662,11 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); auto tracks{ Listen::getRecentTracks(session, params) }; - EXPECT_EQ(tracks.moreResults, false); - ASSERT_EQ(tracks.results.size(), 2); - EXPECT_EQ(tracks.results[0], track2.getId()); - EXPECT_EQ(tracks.results[1], track1.getId()); + ASSERT_EQ(tracks.size(), 2); + EXPECT_EQ(tracks[0], track2.getId()); + EXPECT_EQ(tracks[1], track1.getId()); } } @@ -1820,11 +1735,10 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster.getId() }); auto tracks{ Listen::getRecentTracks(session, params) }; - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } { auto transaction{ session.createWriteTransaction() }; @@ -1836,12 +1750,161 @@ namespace lms::db::tests Listen::StatsFindParameters params; params.setUser(user->getId()); - params.setScrobblingBackend(ScrobblingBackend::Internal); params.filters.setClusters(std::initializer_list{ cluster.getId() }); auto tracks{ Listen::getRecentTracks(session, params) }; - EXPECT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results[0], track.getId()); + EXPECT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks[0], track.getId()); + } + } + + TEST_F(DatabaseFixture, Listen_getTopArtists_callback) + { + ScopedTrack track{ session }; + ScopedUser user{ session, "MyUser" }; + ScopedArtist artist{ session, "MyArtist" }; + const Wt::WDateTime dateTime{ Wt::WDate{ 2000, 1, 2 }, Wt::WTime{ 12, 0, 1 } }; + ScopedListen listen{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime }; + + { + auto transaction{ session.createWriteTransaction() }; + session.create(track.get(), artist.get(), TrackArtistLinkType::Artist); + } + + { + auto transaction{ session.createReadTransaction() }; + + std::vector ids; + Listen::ArtistStatsFindParameters params; + params.setUser(user->getId()); + Listen::getTopArtists(session, params, [&](const Artist::pointer& a) { + ids.push_back(a->getId()); + }); + ASSERT_EQ(ids.size(), 1); + EXPECT_EQ(ids[0], artist->getId()); + } + } + + TEST_F(DatabaseFixture, Listen_getTopReleases_callback) + { + ScopedTrack track{ session }; + ScopedUser user{ session, "MyUser" }; + ScopedRelease release{ session, "MyRelease" }; + const Wt::WDateTime dateTime{ Wt::WDate{ 2000, 1, 2 }, Wt::WTime{ 12, 0, 1 } }; + ScopedListen listen{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime }; + + { + auto transaction{ session.createWriteTransaction() }; + track.get().modify()->setRelease(release.get()); + } + + { + auto transaction{ session.createReadTransaction() }; + + std::vector ids; + Listen::StatsFindParameters params; + params.setUser(user->getId()); + Listen::getTopReleases(session, params, [&](const Release::pointer& r) { + ids.push_back(r->getId()); + }); + ASSERT_EQ(ids.size(), 1); + EXPECT_EQ(ids[0], release->getId()); + } + } + + TEST_F(DatabaseFixture, Listen_getTopTracks_callback) + { + ScopedTrack track{ session }; + ScopedUser user{ session, "MyUser" }; + const Wt::WDateTime dateTime{ Wt::WDate{ 2000, 1, 2 }, Wt::WTime{ 12, 0, 1 } }; + ScopedListen listen{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime }; + + { + auto transaction{ session.createReadTransaction() }; + + std::vector ids; + Listen::StatsFindParameters params; + params.setUser(user->getId()); + Listen::getTopTracks(session, params, [&](const Track::pointer& t) { + ids.push_back(t->getId()); + }); + ASSERT_EQ(ids.size(), 1); + EXPECT_EQ(ids[0], track->getId()); + } + } + + TEST_F(DatabaseFixture, Listen_getRecentArtists_callback) + { + ScopedTrack track{ session }; + ScopedUser user{ session, "MyUser" }; + ScopedArtist artist{ session, "MyArtist" }; + const Wt::WDateTime dateTime{ Wt::WDate{ 2000, 1, 2 }, Wt::WTime{ 12, 0, 1 } }; + ScopedListen listen{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime }; + + { + auto transaction{ session.createWriteTransaction() }; + session.create(track.get(), artist.get(), TrackArtistLinkType::Artist); + } + + { + auto transaction{ session.createReadTransaction() }; + + std::vector ids; + Listen::ArtistStatsFindParameters params; + params.setUser(user->getId()); + Listen::getRecentArtists(session, params, [&](const Artist::pointer& a) { + ids.push_back(a->getId()); + }); + ASSERT_EQ(ids.size(), 1); + EXPECT_EQ(ids[0], artist->getId()); + } + } + + TEST_F(DatabaseFixture, Listen_getRecentReleases_callback) + { + ScopedTrack track{ session }; + ScopedUser user{ session, "MyUser" }; + ScopedRelease release{ session, "MyRelease" }; + const Wt::WDateTime dateTime{ Wt::WDate{ 2000, 1, 2 }, Wt::WTime{ 12, 0, 1 } }; + ScopedListen listen{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime }; + + { + auto transaction{ session.createWriteTransaction() }; + track.get().modify()->setRelease(release.get()); + } + + { + auto transaction{ session.createReadTransaction() }; + + std::vector ids; + Listen::StatsFindParameters params; + params.setUser(user->getId()); + Listen::getRecentReleases(session, params, [&](const Release::pointer& r) { + ids.push_back(r->getId()); + }); + ASSERT_EQ(ids.size(), 1); + EXPECT_EQ(ids[0], release->getId()); + } + } + + TEST_F(DatabaseFixture, Listen_getRecentTracks_callback) + { + ScopedTrack track{ session }; + ScopedUser user{ session, "MyUser" }; + const Wt::WDateTime dateTime{ Wt::WDate{ 2000, 1, 2 }, Wt::WTime{ 12, 0, 1 } }; + ScopedListen listen{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime }; + + { + auto transaction{ session.createReadTransaction() }; + + std::vector ids; + Listen::StatsFindParameters params; + params.setUser(user->getId()); + Listen::getRecentTracks(session, params, [&](const Track::pointer& t) { + ids.push_back(t->getId()); + }); + ASSERT_EQ(ids.size(), 1); + EXPECT_EQ(ids[0], track->getId()); } } } // namespace lms::db::tests \ No newline at end of file diff --git a/src/libs/database/test/Mood.cpp b/src/libs/database/test/Mood.cpp index b3545237..bb0d1ecb 100644 --- a/src/libs/database/test/Mood.cpp +++ b/src/libs/database/test/Mood.cpp @@ -63,8 +63,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto orphans{ Mood::findOrphanIds(session) }; - ASSERT_EQ(orphans.results.size(), 1); - EXPECT_EQ(orphans.results.front(), mood.getId()); + ASSERT_EQ(orphans.size(), 1); + EXPECT_EQ(orphans.front(), mood.getId()); } } @@ -76,7 +76,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Mood::findOrphanIds(session).results.size(), 2); + EXPECT_EQ(Mood::findOrphanIds(session).size(), 2); EXPECT_EQ(track->getMoods().size(), 0); EXPECT_EQ(track->getMoodIds().size(), 0); } @@ -90,12 +90,12 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto moods{ Mood::findIds(session, Mood::FindParameters{}.setTrack(track.getId())) }; - ASSERT_EQ(moods.results.size(), 1); - EXPECT_EQ(moods.results.front(), mood1.getId()); + ASSERT_EQ(moods.size(), 1); + EXPECT_EQ(moods.front(), mood1.getId()); const auto orphans{ Mood::findOrphanIds(session) }; - ASSERT_EQ(orphans.results.size(), 1); - EXPECT_EQ(orphans.results.front(), mood2.getId()); + ASSERT_EQ(orphans.size(), 1); + EXPECT_EQ(orphans.front(), mood2.getId()); const auto trackMoods{ track->getMoods() }; ASSERT_EQ(trackMoods.size(), 1); @@ -109,11 +109,11 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setMood(mood1.getId()))) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); const auto tracks2{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setMood(mood2.getId()))) }; - EXPECT_EQ(tracks2.results.size(), 0); + EXPECT_EQ(tracks2.size(), 0); } } @@ -130,7 +130,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Mood::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(Mood::findOrphanIds(session).size(), 0); const auto trackMoods{ track->getMoods() }; EXPECT_EQ(trackMoods.size(), 2); @@ -139,12 +139,12 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setMood(mood1.getId()))) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); const auto tracks2{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setMood(mood2.getId()))) }; - ASSERT_EQ(tracks2.results.size(), 1); - EXPECT_EQ(tracks2.results.front(), track.getId()); + ASSERT_EQ(tracks2.size(), 1); + EXPECT_EQ(tracks2.front(), track.getId()); } } @@ -157,10 +157,10 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto moods{ Mood::findIds(session, Mood::FindParameters{}.setSortMethod(MoodSortMethod::Name)) }; - ASSERT_EQ(moods.results.size(), 3); - EXPECT_EQ(moods.results[0], m2.getId()); - EXPECT_EQ(moods.results[1], m3.getId()); - EXPECT_EQ(moods.results[2], m1.getId()); + ASSERT_EQ(moods.size(), 3); + EXPECT_EQ(moods[0], m2.getId()); + EXPECT_EQ(moods[1], m3.getId()); + EXPECT_EQ(moods[2], m1.getId()); } } @@ -182,9 +182,9 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto moods{ Mood::findIds(session, Mood::FindParameters{}.setSortMethod(MoodSortMethod::TrackCountDesc)) }; - ASSERT_EQ(moods.results.size(), 2); - EXPECT_EQ(moods.results[0], m1.getId()); - EXPECT_EQ(moods.results[1], m2.getId()); + ASSERT_EQ(moods.size(), 2); + EXPECT_EQ(moods[0], m1.getId()); + EXPECT_EQ(moods[1], m2.getId()); } } } // namespace lms::db::tests diff --git a/src/libs/database/test/RatedArtist.cpp b/src/libs/database/test/RatedArtist.cpp index 38ddacdc..43e5b826 100644 --- a/src/libs/database/test/RatedArtist.cpp +++ b/src/libs/database/test/RatedArtist.cpp @@ -39,7 +39,7 @@ namespace lms::db::tests EXPECT_EQ(RatedArtist::getCount(session), 0); auto artists{ Artist::findIds(session, Artist::FindParameters{}) }; - EXPECT_EQ(artists.results.size(), 1); + EXPECT_EQ(artists.size(), 1); } ScopedRatedArtist ratedArtist{ session, artist.lockAndGet(), user.lockAndGet() }; diff --git a/src/libs/database/test/RatedRelease.cpp b/src/libs/database/test/RatedRelease.cpp index ee4c66e0..5ff6bb31 100644 --- a/src/libs/database/test/RatedRelease.cpp +++ b/src/libs/database/test/RatedRelease.cpp @@ -39,7 +39,7 @@ namespace lms::db::tests EXPECT_EQ(RatedRelease::getCount(session), 0); auto releases{ Release::findIds(session, Release::FindParameters{}) }; - EXPECT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.size(), 1); } ScopedRatedRelease ratedRelease{ session, release.lockAndGet(), user.lockAndGet() }; diff --git a/src/libs/database/test/RatedTrack.cpp b/src/libs/database/test/RatedTrack.cpp index 13ed38b5..a68360c3 100644 --- a/src/libs/database/test/RatedTrack.cpp +++ b/src/libs/database/test/RatedTrack.cpp @@ -39,7 +39,7 @@ namespace lms::db::tests EXPECT_EQ(RatedTrack::getCount(session), 0); auto tracks{ Track::findIds(session, Track::FindParameters{}) }; - EXPECT_EQ(tracks.results.size(), 1); + EXPECT_EQ(tracks.size(), 1); } ScopedRatedTrack ratedTrack{ session, track.lockAndGet(), user.lockAndGet() }; diff --git a/src/libs/database/test/Release.cpp b/src/libs/database/test/Release.cpp index 9f5e3932..3eb5b69a 100644 --- a/src/libs/database/test/Release.cpp +++ b/src/libs/database/test/Release.cpp @@ -57,21 +57,21 @@ namespace lms::db::tests { const auto releases{ Release::findOrphanIds(session) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); } { const auto releases{ Release::findIds(session, Release::FindParameters{}) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); EXPECT_EQ(release->getDuration(), std::chrono::seconds{ 0 }); } { const auto releases{ Release::find(session, Release::FindParameters{}) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front()->getId(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front()->getId(), release.getId()); } { @@ -280,11 +280,11 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Release::findOrphanIds(session).results.size(), 0); + EXPECT_EQ(Release::findOrphanIds(session).size(), 0); const auto tracks{ Track::findIds(session, Track::FindParameters{}.setRelease(release.getId())) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); } { @@ -297,18 +297,18 @@ namespace lms::db::tests { auto transaction{ session.createWriteTransaction() }; auto tracks{ Track::findIds(session, Track::FindParameters{}.setName("MyTrackName").setReleaseName("MyReleaseName")) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); } { auto transaction{ session.createWriteTransaction() }; auto tracks{ Track::findIds(session, Track::FindParameters{}.setName("MyTrackName").setReleaseName("MyReleaseFoo")) }; - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } { auto transaction{ session.createWriteTransaction() }; auto tracks{ Track::findIds(session, Track::FindParameters{}.setName("MyTrackFoo").setReleaseName("MyReleaseName")) }; - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } } @@ -316,11 +316,11 @@ namespace lms::db::tests auto transaction{ session.createWriteTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setRelease(release.getId())) }; - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); auto releases{ Release::findOrphanIds(session) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); } } @@ -340,13 +340,13 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto releases{ Release::findIds(session, Release::FindParameters{}.setFilters(Filters{}.setMediaLibrary(library->getId()))) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); } { auto transaction{ session.createReadTransaction() }; auto releases{ Release::findIds(session, Release::FindParameters{}.setFilters(Filters{}.setMediaLibrary(otherLibrary->getId()))) }; - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } } @@ -383,35 +383,35 @@ namespace lms::db::tests { const auto releases{ Release::findIds(session, Release::FindParameters{}.setKeywords({ "Release" })) }; - EXPECT_EQ(releases.results.size(), 6); + EXPECT_EQ(releases.size(), 6); } { const auto releases{ Release::findIds(session, Release::FindParameters{}.setKeywords({ "MyRelease" })) }; - ASSERT_EQ(releases.results.size(), 5); - EXPECT_TRUE(std::none_of(std::cbegin(releases.results), std::cend(releases.results), [&](const ReleaseId releaseId) { return releaseId == release6.getId(); })); + ASSERT_EQ(releases.size(), 5); + EXPECT_TRUE(std::none_of(std::cbegin(releases), std::cend(releases), [&](const ReleaseId releaseId) { return releaseId == release6.getId(); })); } { const auto releases{ Release::findIds(session, Release::FindParameters{}.setKeywords({ "MyRelease%" })) }; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results[0], release2.getId()); - EXPECT_EQ(releases.results[1], release4.getId()); + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases[0], release2.getId()); + EXPECT_EQ(releases[1], release4.getId()); } { const auto releases{ Release::findIds(session, Release::FindParameters{}.setKeywords({ "%MyRelease" })) }; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results[0], release3.getId()); - EXPECT_EQ(releases.results[1], release5.getId()); + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases[0], release3.getId()); + EXPECT_EQ(releases[1], release5.getId()); } { const auto releases{ Release::findIds(session, Release::FindParameters{}.setKeywords({ "Foo%MyRelease" })) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results[0], release5.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases[0], release5.getId()); } { const auto releases{ Release::findIds(session, Release::FindParameters{}.setKeywords({ "MyRelease%Foo" })) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results[0], release4.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases[0], release4.getId()); } } } @@ -508,8 +508,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Track::findIds(session, Track::FindParameters{}.setRelease(release1.getId())).results.size(), 0); - EXPECT_EQ(Track::findIds(session, Track::FindParameters{}.setRelease(release2.getId())).results.size(), 0); + EXPECT_EQ(Track::findIds(session, Track::FindParameters{}.setRelease(release1.getId())).size(), 0); + EXPECT_EQ(Track::findIds(session, Track::FindParameters{}.setRelease(release2.getId())).size(), 0); } { @@ -538,16 +538,16 @@ namespace lms::db::tests { const auto tracks{ Track::findIds(session, Track::FindParameters{}.setRelease(release1.getId()).setSortMethod(TrackSortMethod::Release)) }; - ASSERT_EQ(tracks.results.size(), 2); - EXPECT_EQ(tracks.results[0], track1A.getId()); - EXPECT_EQ(tracks.results[1], track1B.getId()); + ASSERT_EQ(tracks.size(), 2); + EXPECT_EQ(tracks[0], track1A.getId()); + EXPECT_EQ(tracks[1], track1B.getId()); } { const auto tracks{ Track::findIds(session, Track::FindParameters{}.setRelease(release2.getId()).setSortMethod(TrackSortMethod::Release)) }; - ASSERT_EQ(tracks.results.size(), 2); - EXPECT_EQ(tracks.results[0], track2A.getId()); - EXPECT_EQ(tracks.results[1], track2B.getId()); + ASSERT_EQ(tracks.size(), 2); + EXPECT_EQ(tracks[0], track2A.getId()); + EXPECT_EQ(tracks[1], track2B.getId()); } } } @@ -568,7 +568,7 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setDateRange(YearRange{ -3000, 3000 })) }; - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } { @@ -595,15 +595,15 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto releases{ Release::findIds(session, Release::FindParameters{}.setDateRange(YearRange{ 1950, 2000 })) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release1.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release1.getId()); releases = Release::findIds(session, Release::FindParameters{}.setDateRange(YearRange{ 1994, 1994 })); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release1.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release1.getId()); releases = Release::findIds(session, Release::FindParameters{}.setDateRange(YearRange{ 1993, 1993 })); - ASSERT_EQ(releases.results.size(), 0); + ASSERT_EQ(releases.size(), 0); } } @@ -624,7 +624,7 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setOriginalDateRange(YearRange{ -3000, 3000 })) }; - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } { @@ -649,15 +649,15 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto releases = Release::findIds(session, Release::FindParameters{}.setOriginalDateRange(YearRange{ 1950, 2000 })); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release1.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release1.getId()); releases = Release::findIds(session, Release::FindParameters{}.setOriginalDateRange(YearRange{ 1993, 1993 })); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release1.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release1.getId()); releases = Release::findIds(session, Release::FindParameters{}.setOriginalDateRange(YearRange{ 1994, 1994 })); - ASSERT_EQ(releases.results.size(), 0); + ASSERT_EQ(releases.size(), 0); } } @@ -677,7 +677,7 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setDateRange(YearRange{ 0, 3000 })) }; - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } { @@ -701,15 +701,15 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto releases{ Release::findIds(session, Release::FindParameters{}.setDateRange(YearRange{ 1950, 2000 })) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release1.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release1.getId()); releases = Release::findIds(session, Release::FindParameters{}.setDateRange(YearRange{ 1994, 1994 })); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release1.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release1.getId()); releases = Release::findIds(session, Release::FindParameters{}.setDateRange(YearRange{ 1993, 1993 })); - ASSERT_EQ(releases.results.size(), 0); + ASSERT_EQ(releases.size(), 0); } } @@ -729,19 +729,19 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}) }; - EXPECT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.size(), 1); } { auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setWrittenAfter(dateTime.addSecs(-1))) }; - EXPECT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.size(), 1); } { auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setWrittenAfter(dateTime.addSecs(+1))) }; - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } } @@ -760,12 +760,12 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto releases{ Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist.getId(), { TrackArtistLinkType::Artist })) }; - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); EXPECT_EQ(Release::getCount(session, Release::FindParameters{}.setTrackArtist(artist.getId(), { TrackArtistLinkType::Artist })), 0); EXPECT_EQ(Release::getCount(session, Release::FindParameters{}.setTrackArtist(artist.getId())), 0); releases = Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist2.getId(), { TrackArtistLinkType::Artist })); - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); EXPECT_EQ(Release::getCount(session, Release::FindParameters{}.setTrackArtist(artist2.getId(), { TrackArtistLinkType::Artist })), 0); EXPECT_EQ(Release::getCount(session, Release::FindParameters{}.setTrackArtist(artist2.getId())), 0); } @@ -782,39 +782,39 @@ namespace lms::db::tests EXPECT_EQ(Release::getCount(session, Release::FindParameters{}), 1); auto releases{ Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist.getId(), { TrackArtistLinkType::Artist })) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); EXPECT_EQ(Release::getCount(session, Release::FindParameters{}.setTrackArtist(artist.getId(), { TrackArtistLinkType::Artist })), 1); EXPECT_EQ(Release::getCount(session, Release::FindParameters{}.setTrackArtist(artist.getId(), { TrackArtistLinkType::Remixer })), 0); releases = Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist.getId(), { TrackArtistLinkType::Artist, TrackArtistLinkType::Mixer })); - EXPECT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + EXPECT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); EXPECT_EQ(Release::getCount(session, Release::FindParameters{}.setTrackArtist(artist.getId(), { TrackArtistLinkType::Artist, TrackArtistLinkType::Mixer })), 1); releases = Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist2.getId(), { TrackArtistLinkType::Artist })); - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); releases = Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist2.getId())); - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); releases = Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist.getId(), { TrackArtistLinkType::Writer, TrackArtistLinkType::Artist })); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); releases = Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist.getId())); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); EXPECT_EQ(Release::getCount(session, Release::FindParameters{}.setTrackArtist(artist.getId())), 1); EXPECT_EQ(release->getTrackArtists().size(), 1); EXPECT_EQ(release->getTrackArtists(TrackArtistLinkType::Artist).size(), 1); EXPECT_EQ(release->getTrackArtists(TrackArtistLinkType::Conductor).size(), 0); releases = Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist.getId(), { TrackArtistLinkType::Composer })); - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); releases = Release::findIds(session, Release::FindParameters{}.setTrackArtist(artist.getId(), { TrackArtistLinkType::Composer, TrackArtistLinkType::Mixer })); - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } { @@ -850,7 +850,7 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setArtist(artist1.getId())) }; - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); EXPECT_EQ(Release::getCount(session, Release::FindParameters{}.setArtist(artist1.getId())), 0); EXPECT_EQ(release->getTrackArtists(TrackArtistLinkType::Conductor).size(), 0); EXPECT_EQ(release->getArtistLinks().size(), 0); @@ -907,8 +907,8 @@ namespace lms::db::tests EXPECT_EQ(Release::getCount(session, Release::FindParameters{}), 1); const auto releases{ Release::findIds(session, Release::FindParameters{}.setArtist(artist1.getId())) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release.getId()); EXPECT_EQ(Release::getCount(session, Release::FindParameters{}.setTrackArtist(artist1.getId())), 0); EXPECT_EQ(Release::getCount(session, Release::FindParameters{}.setArtist(artist1.getId())), 1); EXPECT_EQ(Release::getCount(session, Release::FindParameters{}.setTrackArtist(artist2.getId())), 0); @@ -999,8 +999,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto labels{ Label::findOrphanIds(session) }; - ASSERT_EQ(labels.results.size(), 1); - EXPECT_EQ(labels.results.front(), label.getId()); + ASSERT_EQ(labels.size(), 1); + EXPECT_EQ(labels.front(), label.getId()); } ScopedRelease release{ session, "MyRelease" }; @@ -1013,7 +1013,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto labels{ Label::findOrphanIds(session) }; - EXPECT_EQ(labels.results.size(), 0); + EXPECT_EQ(labels.size(), 0); } { @@ -1024,8 +1024,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto labels{ Label::findOrphanIds(session) }; - ASSERT_EQ(labels.results.size(), 1); - EXPECT_EQ(labels.results.front(), label.getId()); + ASSERT_EQ(labels.size(), 1); + EXPECT_EQ(labels.front(), label.getId()); } } @@ -1071,8 +1071,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto countries{ Country::findOrphanIds(session) }; - ASSERT_EQ(countries.results.size(), 1); - EXPECT_EQ(countries.results.front(), country.getId()); + ASSERT_EQ(countries.size(), 1); + EXPECT_EQ(countries.front(), country.getId()); } ScopedRelease release{ session, "MyRelease" }; @@ -1085,7 +1085,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto countries{ Country::findOrphanIds(session) }; - EXPECT_EQ(countries.results.size(), 0); + EXPECT_EQ(countries.size(), 0); } { @@ -1096,8 +1096,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto countries{ Country::findOrphanIds(session) }; - ASSERT_EQ(countries.results.size(), 1); - EXPECT_EQ(countries.results.front(), country.getId()); + ASSERT_EQ(countries.size(), 1); + EXPECT_EQ(countries.front(), country.getId()); } } @@ -1126,8 +1126,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto releaseTypes{ ReleaseType::findOrphanIds(session) }; - ASSERT_EQ(releaseTypes.results.size(), 1); - EXPECT_EQ(releaseTypes.results.front(), releaseType.getId()); + ASSERT_EQ(releaseTypes.size(), 1); + EXPECT_EQ(releaseTypes.front(), releaseType.getId()); } ScopedRelease release{ session, "MyRelease" }; @@ -1140,7 +1140,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto releaseTypes{ ReleaseType::findOrphanIds(session) }; - EXPECT_EQ(releaseTypes.results.size(), 0); + EXPECT_EQ(releaseTypes.size(), 0); } { @@ -1151,8 +1151,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto releaseTypes{ ReleaseType::findOrphanIds(session) }; - ASSERT_EQ(releaseTypes.results.size(), 1); - EXPECT_EQ(releaseTypes.results.front(), releaseType.getId()); + ASSERT_EQ(releaseTypes.size(), 1); + EXPECT_EQ(releaseTypes.front(), releaseType.getId()); } } @@ -1191,7 +1191,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - auto releases{ Release::find(session, Release::FindParameters{}.setReleaseType("Foo")).results }; + auto releases{ Release::find(session, Release::FindParameters{}.setReleaseType("Foo")) }; EXPECT_EQ(releases.size(), 0); } @@ -1205,10 +1205,10 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - auto releases{ Release::find(session, Release::FindParameters{}.setReleaseType("Foo")).results }; + auto releases{ Release::find(session, Release::FindParameters{}.setReleaseType("Foo")) }; EXPECT_EQ(releases.size(), 0); - releases = Release::find(session, Release::FindParameters{}.setReleaseType("album")).results; + releases = Release::find(session, Release::FindParameters{}.setReleaseType("album")); ASSERT_EQ(releases.size(), 1); EXPECT_EQ(releases.front()->getId(), release.getId()); } @@ -1244,51 +1244,51 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setSortMethod(ReleaseSortMethod::Name)) }; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results.front(), release1.getId()); - EXPECT_EQ(releases.results.back(), release2.getId()); + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases.front(), release1.getId()); + EXPECT_EQ(releases.back(), release2.getId()); } { auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setSortMethod(ReleaseSortMethod::Random)) }; - ASSERT_EQ(releases.results.size(), 2); + ASSERT_EQ(releases.size(), 2); } { auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setSortMethod(ReleaseSortMethod::DateAsc)) }; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results.front(), release2.getId()); - EXPECT_EQ(releases.results.back(), release1.getId()); + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases.front(), release2.getId()); + EXPECT_EQ(releases.back(), release1.getId()); } { auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setSortMethod(ReleaseSortMethod::DateDesc)) }; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results.front(), release1.getId()); - EXPECT_EQ(releases.results.back(), release2.getId()); + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases.front(), release1.getId()); + EXPECT_EQ(releases.back(), release2.getId()); } { auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setSortMethod(ReleaseSortMethod::OriginalDate)) }; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results.front(), release1.getId()); - EXPECT_EQ(releases.results.back(), release2.getId()); + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases.front(), release1.getId()); + EXPECT_EQ(releases.back(), release2.getId()); } { auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setSortMethod(ReleaseSortMethod::OriginalDateDesc)) }; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results.front(), release2.getId()); - EXPECT_EQ(releases.results.back(), release1.getId()); + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases.front(), release2.getId()); + EXPECT_EQ(releases.back(), release1.getId()); } } @@ -1392,8 +1392,8 @@ namespace lms::db::tests params.setFilters(Filters{}.setCodec(core::media::Codec::MP3)); auto releases{ Release::findIds(session, params) }; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release2.getId()); + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases.front(), release2.getId()); } } @@ -1491,11 +1491,11 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setSortMethod(ReleaseSortMethod::AddedDesc)) }; - ASSERT_EQ(releases.results.size(), 4); - EXPECT_EQ(releases.results[0], releaseA.getId()); - EXPECT_EQ(releases.results[1], releaseD.getId()); - EXPECT_EQ(releases.results[2], releaseB.getId()); - EXPECT_EQ(releases.results[3], releaseC.getId()); + ASSERT_EQ(releases.size(), 4); + EXPECT_EQ(releases[0], releaseA.getId()); + EXPECT_EQ(releases[1], releaseD.getId()); + EXPECT_EQ(releases[2], releaseB.getId()); + EXPECT_EQ(releases[3], releaseC.getId()); } } @@ -1531,11 +1531,11 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto releases{ Release::findIds(session, Release::FindParameters{}.setSortMethod(ReleaseSortMethod::LastWrittenDesc)) }; - ASSERT_EQ(releases.results.size(), 4); - EXPECT_EQ(releases.results[0], releaseA.getId()); - EXPECT_EQ(releases.results[1], releaseD.getId()); - EXPECT_EQ(releases.results[2], releaseB.getId()); - EXPECT_EQ(releases.results[3], releaseC.getId()); + ASSERT_EQ(releases.size(), 4); + EXPECT_EQ(releases[0], releaseA.getId()); + EXPECT_EQ(releases[1], releaseD.getId()); + EXPECT_EQ(releases[2], releaseB.getId()); + EXPECT_EQ(releases[3], releaseC.getId()); } } @@ -1610,7 +1610,7 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto releases{ Release::find(session, Release::FindParameters{}.setReleaseGroupMBID(groupMBID)) }; - EXPECT_EQ(releases.results.size(), 0); + EXPECT_EQ(releases.size(), 0); } { @@ -1622,8 +1622,8 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto releases{ Release::find(session, Release::FindParameters{}.setReleaseGroupMBID(groupMBID)) }; - EXPECT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results[0]->getId(), release->getId()); + EXPECT_EQ(releases.size(), 1); + EXPECT_EQ(releases[0]->getId(), release->getId()); } } @@ -1642,18 +1642,18 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto releases{ Release::find(session, Release::FindParameters{}.setSortMethod(ReleaseSortMethod::Name)) }; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results[0]->getId(), release1->getId()); - EXPECT_EQ(releases.results[1]->getId(), release2->getId()); + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases[0]->getId(), release1->getId()); + EXPECT_EQ(releases[1]->getId(), release2->getId()); } { auto transaction{ session.createReadTransaction() }; const auto releases{ Release::find(session, Release::FindParameters{}.setSortMethod(ReleaseSortMethod::SortName)) }; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results[0]->getId(), release2->getId()); - EXPECT_EQ(releases.results[1]->getId(), release1->getId()); + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases[0]->getId(), release2->getId()); + EXPECT_EQ(releases[1]->getId(), release1->getId()); } } @@ -1726,4 +1726,5 @@ namespace lms::db::tests EXPECT_EQ(mediums[1]->getId(), medium2.getId()); } } + } // namespace lms::db::tests \ No newline at end of file diff --git a/src/libs/database/test/StarredArtist.cpp b/src/libs/database/test/StarredArtist.cpp index f85af565..fcfee416 100644 --- a/src/libs/database/test/StarredArtist.cpp +++ b/src/libs/database/test/StarredArtist.cpp @@ -39,7 +39,7 @@ namespace lms::db::tests EXPECT_EQ(StarredArtist::getCount(session), 0); auto artists{ Artist::findIds(session, Artist::FindParameters{}) }; - EXPECT_EQ(artists.results.size(), 1); + EXPECT_EQ(artists.size(), 1); } ScopedStarredArtist starredArtist{ session, artist.lockAndGet(), user.lockAndGet(), FeedbackBackend::Internal }; @@ -55,13 +55,13 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto artists{ Artist::findIds(session, Artist::FindParameters{}) }; - EXPECT_EQ(artists.results.size(), 1); + EXPECT_EQ(artists.size(), 1); - artists = Artist::findIds(session, Artist::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal)); - EXPECT_EQ(artists.results.size(), 1); + artists = Artist::findIds(session, Artist::FindParameters{}.setStarringUser(user.getId())); + EXPECT_EQ(artists.size(), 1); - artists = Artist::findIds(session, Artist::FindParameters{}.setStarringUser(user2.getId(), FeedbackBackend::Internal)); - EXPECT_EQ(artists.results.size(), 0); + artists = Artist::findIds(session, Artist::FindParameters{}.setStarringUser(user2.getId())); + EXPECT_EQ(artists.size(), 0); } { @@ -97,12 +97,12 @@ namespace lms::db::tests { auto transaction{ session.createWriteTransaction() }; - auto artists{ Artist::findIds(session, Artist::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal)) }; - EXPECT_EQ(artists.results.size(), 1); + auto artists{ Artist::findIds(session, Artist::FindParameters{}.setStarringUser(user.getId())) }; + EXPECT_EQ(artists.size(), 1); starredArtist.get().modify()->setSyncState(SyncState::PendingRemove); - artists = Artist::findIds(session, Artist::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal)); - EXPECT_EQ(artists.results.size(), 0); + artists = Artist::findIds(session, Artist::FindParameters{}.setStarringUser(user.getId())); + EXPECT_EQ(artists.size(), 0); } } @@ -120,8 +120,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - auto artists{ Artist::find(session, Artist::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal)) }; - EXPECT_EQ(artists.results.size(), 2); + auto artists{ Artist::find(session, Artist::FindParameters{}.setStarringUser(user.getId())) }; + EXPECT_EQ(artists.size(), 2); } { @@ -130,10 +130,10 @@ namespace lms::db::tests starredArtist1.get().modify()->setDateTime(dateTime); starredArtist2.get().modify()->setDateTime(dateTime.addSecs(-1)); - auto artists{ Artist::findIds(session, Artist::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal).setSortMethod(ArtistSortMethod::StarredDateDesc)) }; - ASSERT_EQ(artists.results.size(), 2); - EXPECT_EQ(artists.results[0], starredArtist1->getArtist()->getId()); - EXPECT_EQ(artists.results[1], starredArtist2->getArtist()->getId()); + auto artists{ Artist::findIds(session, Artist::FindParameters{}.setStarringUser(user.getId()).setSortMethod(ArtistSortMethod::StarredDateDesc)) }; + ASSERT_EQ(artists.size(), 2); + EXPECT_EQ(artists[0], starredArtist1->getArtist()->getId()); + EXPECT_EQ(artists[1], starredArtist2->getArtist()->getId()); } { auto transaction{ session.createWriteTransaction() }; @@ -141,10 +141,34 @@ namespace lms::db::tests starredArtist1.get().modify()->setDateTime(dateTime); starredArtist2.get().modify()->setDateTime(dateTime.addSecs(1)); - auto artists{ Artist::findIds(session, Artist::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal).setSortMethod(ArtistSortMethod::StarredDateDesc)) }; - ASSERT_EQ(artists.results.size(), 2); - EXPECT_EQ(artists.results[0], starredArtist2->getArtist()->getId()); - EXPECT_EQ(artists.results[1], starredArtist1->getArtist()->getId()); + auto artists{ Artist::findIds(session, Artist::FindParameters{}.setStarringUser(user.getId()).setSortMethod(ArtistSortMethod::StarredDateDesc)) }; + ASSERT_EQ(artists.size(), 2); + EXPECT_EQ(artists[0], starredArtist2->getArtist()->getId()); + EXPECT_EQ(artists[1], starredArtist1->getArtist()->getId()); + } + } + TEST_F(DatabaseFixture, StarredArtist_currentBackend) + { + ScopedArtist artist{ session, "MyArtist" }; + ScopedUser user{ session, "MyUser" }; + ScopedStarredArtist starredArtist{ session, artist.lockAndGet(), user.lockAndGet(), FeedbackBackend::Internal }; + + { + auto transaction{ session.createReadTransaction() }; + auto artists{ Artist::findIds(session, Artist::FindParameters{}.setStarringUser(user.getId())) }; + ASSERT_EQ(artists.size(), 1); + EXPECT_EQ(artists[0], artist->getId()); + } + + { + auto transaction{ session.createWriteTransaction() }; + user.get().modify()->setFeedbackBackend(FeedbackBackend::ListenBrainz); + } + + { + auto transaction{ session.createReadTransaction() }; + auto artists{ Artist::findIds(session, Artist::FindParameters{}.setStarringUser(user.getId())) }; + EXPECT_EQ(artists.size(), 0); } } } // namespace lms::db::tests \ No newline at end of file diff --git a/src/libs/database/test/StarredRelease.cpp b/src/libs/database/test/StarredRelease.cpp index d8e66a35..ba06439d 100644 --- a/src/libs/database/test/StarredRelease.cpp +++ b/src/libs/database/test/StarredRelease.cpp @@ -39,7 +39,7 @@ namespace lms::db::tests EXPECT_EQ(StarredRelease::getCount(session), 0); auto releases{ Release::find(session, Release::FindParameters{}) }; - EXPECT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.size(), 1); } ScopedStarredRelease starredRelease{ session, release.lockAndGet(), user.lockAndGet(), FeedbackBackend::Internal }; @@ -55,13 +55,13 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto releases{ Release::find(session, Release::FindParameters{}) }; - EXPECT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.size(), 1); - releases = Release::find(session, Release::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal)); - EXPECT_EQ(releases.results.size(), 1); + releases = Release::find(session, Release::FindParameters{}.setStarringUser(user.getId())); + EXPECT_EQ(releases.size(), 1); - releases = Release::find(session, Release::FindParameters{}.setStarringUser(user2.getId(), FeedbackBackend::Internal)); - EXPECT_EQ(releases.results.size(), 0); + releases = Release::find(session, Release::FindParameters{}.setStarringUser(user2.getId())); + EXPECT_EQ(releases.size(), 0); } { @@ -86,12 +86,12 @@ namespace lms::db::tests { auto transaction{ session.createWriteTransaction() }; - auto releases{ Release::find(session, Release::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal)) }; - EXPECT_EQ(releases.results.size(), 1); + auto releases{ Release::find(session, Release::FindParameters{}.setStarringUser(user.getId())) }; + EXPECT_EQ(releases.size(), 1); starredRelease.get().modify()->setSyncState(SyncState::PendingRemove); - releases = Release::find(session, Release::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal)); - EXPECT_EQ(releases.results.size(), 0); + releases = Release::find(session, Release::FindParameters{}.setStarringUser(user.getId())); + EXPECT_EQ(releases.size(), 0); } } @@ -109,8 +109,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - auto releases{ Release::findIds(session, Release::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal)) }; - EXPECT_EQ(releases.results.size(), 2); + auto releases{ Release::findIds(session, Release::FindParameters{}.setStarringUser(user.getId())) }; + EXPECT_EQ(releases.size(), 2); } { @@ -119,10 +119,10 @@ namespace lms::db::tests starredRelease1.get().modify()->setDateTime(dateTime); starredRelease2.get().modify()->setDateTime(dateTime.addSecs(-1)); - auto releases{ Release::findIds(session, Release::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal).setSortMethod(ReleaseSortMethod::StarredDateDesc)) }; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results[0], starredRelease1->getRelease()->getId()); - EXPECT_EQ(releases.results[1], starredRelease2->getRelease()->getId()); + auto releases{ Release::findIds(session, Release::FindParameters{}.setStarringUser(user.getId()).setSortMethod(ReleaseSortMethod::StarredDateDesc)) }; + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases[0], starredRelease1->getRelease()->getId()); + EXPECT_EQ(releases[1], starredRelease2->getRelease()->getId()); } { auto transaction{ session.createWriteTransaction() }; @@ -130,10 +130,34 @@ namespace lms::db::tests starredRelease1.get().modify()->setDateTime(dateTime); starredRelease2.get().modify()->setDateTime(dateTime.addSecs(1)); - auto releases{ Release::findIds(session, Release::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal).setSortMethod(ReleaseSortMethod::StarredDateDesc)) }; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results[0], starredRelease2->getRelease()->getId()); - EXPECT_EQ(releases.results[1], starredRelease1->getRelease()->getId()); + auto releases{ Release::findIds(session, Release::FindParameters{}.setStarringUser(user.getId()).setSortMethod(ReleaseSortMethod::StarredDateDesc)) }; + ASSERT_EQ(releases.size(), 2); + EXPECT_EQ(releases[0], starredRelease2->getRelease()->getId()); + EXPECT_EQ(releases[1], starredRelease1->getRelease()->getId()); + } + } + TEST_F(DatabaseFixture, StarredRelease_currentBackend) + { + ScopedRelease release{ session, "MyRelease" }; + ScopedUser user{ session, "MyUser" }; + ScopedStarredRelease starredRelease{ session, release.lockAndGet(), user.lockAndGet(), FeedbackBackend::Internal }; + + { + auto transaction{ session.createReadTransaction() }; + auto releases{ Release::findIds(session, Release::FindParameters{}.setStarringUser(user.getId())) }; + ASSERT_EQ(releases.size(), 1); + EXPECT_EQ(releases[0], release->getId()); + } + + { + auto transaction{ session.createWriteTransaction() }; + user.get().modify()->setFeedbackBackend(FeedbackBackend::ListenBrainz); + } + + { + auto transaction{ session.createReadTransaction() }; + auto releases{ Release::findIds(session, Release::FindParameters{}.setStarringUser(user.getId())) }; + EXPECT_EQ(releases.size(), 0); } } } // namespace lms::db::tests \ No newline at end of file diff --git a/src/libs/database/test/StarredTrack.cpp b/src/libs/database/test/StarredTrack.cpp index 0c0b4632..20b8d239 100644 --- a/src/libs/database/test/StarredTrack.cpp +++ b/src/libs/database/test/StarredTrack.cpp @@ -39,7 +39,7 @@ namespace lms::db::tests EXPECT_EQ(StarredTrack::getCount(session), 0); auto tracks{ Track::findIds(session, Track::FindParameters{}) }; - EXPECT_EQ(tracks.results.size(), 1); + EXPECT_EQ(tracks.size(), 1); } ScopedStarredTrack starredTrack{ session, track.lockAndGet(), user.lockAndGet(), FeedbackBackend::Internal }; @@ -55,13 +55,13 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto tracks{ Track::findIds(session, Track::FindParameters{}) }; - EXPECT_EQ(tracks.results.size(), 1); + EXPECT_EQ(tracks.size(), 1); - tracks = Track::findIds(session, Track::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal)); - EXPECT_EQ(tracks.results.size(), 1); + tracks = Track::findIds(session, Track::FindParameters{}.setStarringUser(user.getId())); + EXPECT_EQ(tracks.size(), 1); - tracks = Track::findIds(session, Track::FindParameters{}.setStarringUser(user2.getId(), FeedbackBackend::Internal)); - EXPECT_EQ(tracks.results.size(), 0); + tracks = Track::findIds(session, Track::FindParameters{}.setStarringUser(user2.getId())); + EXPECT_EQ(tracks.size(), 0); } { @@ -86,12 +86,12 @@ namespace lms::db::tests { auto transaction{ session.createWriteTransaction() }; - auto tracks{ Track::findIds(session, Track::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal)) }; - EXPECT_EQ(tracks.results.size(), 1); + auto tracks{ Track::findIds(session, Track::FindParameters{}.setStarringUser(user.getId())) }; + EXPECT_EQ(tracks.size(), 1); starredTrack.get().modify()->setSyncState(SyncState::PendingRemove); - tracks = Track::findIds(session, Track::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal)); - EXPECT_EQ(tracks.results.size(), 0); + tracks = Track::findIds(session, Track::FindParameters{}.setStarringUser(user.getId())); + EXPECT_EQ(tracks.size(), 0); } } @@ -109,8 +109,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - auto tracks{ Track::findIds(session, Track::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal)) }; - EXPECT_EQ(tracks.results.size(), 2); + auto tracks{ Track::findIds(session, Track::FindParameters{}.setStarringUser(user.getId())) }; + EXPECT_EQ(tracks.size(), 2); } { @@ -119,10 +119,10 @@ namespace lms::db::tests starredTrack1.get().modify()->setDateTime(dateTime); starredTrack2.get().modify()->setDateTime(dateTime.addSecs(-1)); - auto tracks{ Track::findIds(session, Track::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal).setSortMethod(TrackSortMethod::StarredDateDesc)) }; - ASSERT_EQ(tracks.results.size(), 2); - EXPECT_EQ(tracks.results[0], starredTrack1->getTrack()->getId()); - EXPECT_EQ(tracks.results[1], starredTrack2->getTrack()->getId()); + auto tracks{ Track::findIds(session, Track::FindParameters{}.setStarringUser(user.getId()).setSortMethod(TrackSortMethod::StarredDateDesc)) }; + ASSERT_EQ(tracks.size(), 2); + EXPECT_EQ(tracks[0], starredTrack1->getTrack()->getId()); + EXPECT_EQ(tracks[1], starredTrack2->getTrack()->getId()); } { auto transaction{ session.createWriteTransaction() }; @@ -130,10 +130,34 @@ namespace lms::db::tests starredTrack1.get().modify()->setDateTime(dateTime); starredTrack2.get().modify()->setDateTime(dateTime.addSecs(1)); - auto tracks{ Track::findIds(session, Track::FindParameters{}.setStarringUser(user.getId(), FeedbackBackend::Internal).setSortMethod(TrackSortMethod::StarredDateDesc)) }; - ASSERT_EQ(tracks.results.size(), 2); - EXPECT_EQ(tracks.results[0], starredTrack2->getTrack()->getId()); - EXPECT_EQ(tracks.results[1], starredTrack1->getTrack()->getId()); + auto tracks{ Track::findIds(session, Track::FindParameters{}.setStarringUser(user.getId()).setSortMethod(TrackSortMethod::StarredDateDesc)) }; + ASSERT_EQ(tracks.size(), 2); + EXPECT_EQ(tracks[0], starredTrack2->getTrack()->getId()); + EXPECT_EQ(tracks[1], starredTrack1->getTrack()->getId()); + } + } + TEST_F(DatabaseFixture, StarredTrack_currentBackend) + { + ScopedTrack track{ session }; + ScopedUser user{ session, "MyUser" }; + ScopedStarredTrack starredTrack{ session, track.lockAndGet(), user.lockAndGet(), FeedbackBackend::Internal }; + + { + auto transaction{ session.createReadTransaction() }; + auto tracks{ Track::findIds(session, Track::FindParameters{}.setStarringUser(user.getId())) }; + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks[0], track->getId()); + } + + { + auto transaction{ session.createWriteTransaction() }; + user.get().modify()->setFeedbackBackend(FeedbackBackend::ListenBrainz); + } + + { + auto transaction{ session.createReadTransaction() }; + auto tracks{ Track::findIds(session, Track::FindParameters{}.setStarringUser(user.getId())) }; + EXPECT_EQ(tracks.size(), 0); } } } // namespace lms::db::tests \ No newline at end of file diff --git a/src/libs/database/test/Track.cpp b/src/libs/database/test/Track.cpp index f68c7ebf..feaf7d94 100644 --- a/src/libs/database/test/Track.cpp +++ b/src/libs/database/test/Track.cpp @@ -37,8 +37,8 @@ namespace lms::db::tests { { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Track::find(session, Track::FindParameters{}).results.size(), 0); - EXPECT_EQ(Track::findIds(session, Track::FindParameters{}).results.size(), 0); + EXPECT_EQ(Track::find(session, Track::FindParameters{}).size(), 0); + EXPECT_EQ(Track::findIds(session, Track::FindParameters{}).size(), 0); EXPECT_EQ(Track::getCount(session), 0); EXPECT_FALSE(Track::exists(session, 0)); @@ -54,7 +54,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - EXPECT_EQ(Track::find(session, Track::FindParameters{}).results.size(), 1); + EXPECT_EQ(Track::find(session, Track::FindParameters{}).size(), 1); EXPECT_EQ(Track::getCount(session), 1); EXPECT_TRUE(Track::exists(session, track.getId())); auto myTrack{ Track::find(session, track.getId()) }; @@ -260,8 +260,8 @@ namespace lms::db::tests params.setFilters(Filters{}.setCodec(core::media::Codec::FLAC)); const auto tracks{ Track::find(session, params) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results[0]->getId(), track2.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks[0]->getId(), track2.getId()); } } @@ -291,13 +291,13 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setMediaLibrary(library->getId()))) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); } { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setMediaLibrary(otherLibrary->getId()))) }; - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } } @@ -320,7 +320,7 @@ namespace lms::db::tests EXPECT_FALSE(Track::exists(session, TrackId{ 42 })); EXPECT_EQ(Track::find(session, TrackId{ 42 }), Track::pointer{}); EXPECT_FALSE(Track::find(session, TrackId{ 42 })); - EXPECT_EQ(Track::find(session, Track::FindParameters{}).results.size(), 0); + EXPECT_EQ(Track::find(session, Track::FindParameters{}).size(), 0); { auto track{ Track::find(session, TrackId{ 42 }) }; EXPECT_TRUE(!track); @@ -366,24 +366,24 @@ namespace lms::db::tests { const auto tracks{ Track::findIds(session, Track::FindParameters{}.setKeywords({ "Track" })) }; - EXPECT_EQ(tracks.results.size(), 6); + EXPECT_EQ(tracks.size(), 6); } { const auto tracks{ Track::findIds(session, Track::FindParameters{}.setKeywords({ "MyTrack" })) }; - EXPECT_EQ(tracks.results.size(), 5); - EXPECT_TRUE(std::none_of(std::cbegin(tracks.results), std::cend(tracks.results), [&](const TrackId trackId) { return trackId == track6.getId(); })); + EXPECT_EQ(tracks.size(), 5); + EXPECT_TRUE(std::none_of(std::cbegin(tracks), std::cend(tracks), [&](const TrackId trackId) { return trackId == track6.getId(); })); } { const auto tracks{ Track::findIds(session, Track::FindParameters{}.setKeywords({ "MyTrack%" })) }; - ASSERT_EQ(tracks.results.size(), 2); - EXPECT_EQ(tracks.results[0], track2.getId()); - EXPECT_EQ(tracks.results[1], track3.getId()); + ASSERT_EQ(tracks.size(), 2); + EXPECT_EQ(tracks[0], track2.getId()); + EXPECT_EQ(tracks[1], track3.getId()); } { const auto tracks{ Track::findIds(session, Track::FindParameters{}.setKeywords({ "%MyTrack" })) }; - ASSERT_EQ(tracks.results.size(), 2); - EXPECT_EQ(tracks.results[0], track4.getId()); - EXPECT_EQ(tracks.results[1], track5.getId()); + ASSERT_EQ(tracks.size(), 2); + EXPECT_EQ(tracks[0], track4.getId()); + EXPECT_EQ(tracks[1], track5.getId()); } } } @@ -434,19 +434,19 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}) }; - EXPECT_EQ(tracks.results.size(), 1); + EXPECT_EQ(tracks.size(), 1); } { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setWrittenAfter(dateTime.addSecs(-1))) }; - EXPECT_EQ(tracks.results.size(), 1); + EXPECT_EQ(tracks.size(), 1); } { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setWrittenAfter(dateTime.addSecs(+1))) }; - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } } @@ -525,11 +525,11 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setSortMethod(TrackSortMethod::AddedDesc)) }; - ASSERT_EQ(tracks.results.size(), 4); - EXPECT_EQ(tracks.results[0], track4.getId()); - EXPECT_EQ(tracks.results[1], track1.getId()); - EXPECT_EQ(tracks.results[2], track2.getId()); - EXPECT_EQ(tracks.results[3], track3.getId()); + ASSERT_EQ(tracks.size(), 4); + EXPECT_EQ(tracks[0], track4.getId()); + EXPECT_EQ(tracks[1], track1.getId()); + EXPECT_EQ(tracks[2], track2.getId()); + EXPECT_EQ(tracks[3], track3.getId()); } } @@ -550,11 +550,11 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; const auto tracks{ Track::findIds(session, Track::FindParameters{}.setSortMethod(TrackSortMethod::LastWrittenDesc)) }; - ASSERT_EQ(tracks.results.size(), 4); - EXPECT_EQ(tracks.results[0], track4.getId()); - EXPECT_EQ(tracks.results[1], track1.getId()); - EXPECT_EQ(tracks.results[2], track2.getId()); - EXPECT_EQ(tracks.results[3], track3.getId()); + ASSERT_EQ(tracks.size(), 4); + EXPECT_EQ(tracks[0], track4.getId()); + EXPECT_EQ(tracks[1], track1.getId()); + EXPECT_EQ(tracks[2], track2.getId()); + EXPECT_EQ(tracks[3], track3.getId()); } } @@ -619,8 +619,8 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto results{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setGenre(genre.getId()).setMood(mood.getId()).setGrouping(grouping.getId()).setLanguage(language.getId()))) }; - ASSERT_EQ(results.results.size(), 1); - EXPECT_EQ(results.results.front(), track1.getId()); + ASSERT_EQ(results.size(), 1); + EXPECT_EQ(results.front(), track1.getId()); } } } // namespace lms::db::tests \ No newline at end of file diff --git a/src/libs/database/test/TrackBookmark.cpp b/src/libs/database/test/TrackBookmark.cpp index 5e4d8208..876135a5 100644 --- a/src/libs/database/test/TrackBookmark.cpp +++ b/src/libs/database/test/TrackBookmark.cpp @@ -50,8 +50,8 @@ namespace lms::db::tests EXPECT_EQ(TrackBookmark::getCount(session), 1); const auto bookmarks{ TrackBookmark::find(session, user.getId()) }; - ASSERT_EQ(bookmarks.results.size(), 1); - EXPECT_EQ(bookmarks.results.front(), bookmark.getId()); + ASSERT_EQ(bookmarks.size(), 1); + EXPECT_EQ(bookmarks.front(), bookmark.getId()); } { auto transaction{ session.createReadTransaction() }; diff --git a/src/libs/database/test/TrackEmbeddedImage.cpp b/src/libs/database/test/TrackEmbeddedImage.cpp index 61bcda1a..02ada518 100644 --- a/src/libs/database/test/TrackEmbeddedImage.cpp +++ b/src/libs/database/test/TrackEmbeddedImage.cpp @@ -364,8 +364,8 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto orphans{ TrackEmbeddedImage::findOrphanIds(session, std::nullopt) }; - ASSERT_EQ(orphans.results.size(), 1); - EXPECT_EQ(orphans.results[0], image.getId()); + ASSERT_EQ(orphans.size(), 1); + EXPECT_EQ(orphans[0], image.getId()); } { @@ -376,7 +376,7 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto orphans{ TrackEmbeddedImage::findOrphanIds(session, std::nullopt) }; - ASSERT_EQ(orphans.results.size(), 0); + ASSERT_EQ(orphans.size(), 0); } } @@ -384,8 +384,8 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto orphans{ TrackEmbeddedImage::findOrphanIds(session, std::nullopt) }; - ASSERT_EQ(orphans.results.size(), 1); - EXPECT_EQ(orphans.results[0], image.getId()); + ASSERT_EQ(orphans.size(), 1); + EXPECT_EQ(orphans[0], image.getId()); } } diff --git a/src/libs/database/test/TrackList.cpp b/src/libs/database/test/TrackList.cpp index 33320ebb..b0f5db48 100644 --- a/src/libs/database/test/TrackList.cpp +++ b/src/libs/database/test/TrackList.cpp @@ -53,10 +53,10 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto tracks{ Track::findIds(session, Track::FindParameters{}.setTrackList(trackList1.getId())) }; - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); tracks = Track::findIds(session, Track::FindParameters{}.setTrackList(trackList2.getId())); - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } { @@ -69,11 +69,11 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto tracks{ Track::findIds(session, Track::FindParameters{}.setTrackList(trackList1.getId())) }; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); + ASSERT_EQ(tracks.size(), 1); + EXPECT_EQ(tracks.front(), track.getId()); tracks = Track::findIds(session, Track::FindParameters{}.setTrackList(trackList2.getId())); - EXPECT_EQ(tracks.results.size(), 0); + EXPECT_EQ(tracks.size(), 0); } } @@ -87,9 +87,9 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto trackLists{ TrackList::find(session, TrackList::FindParameters{}.setSortMethod(TrackListSortMethod::Name)) }; - ASSERT_EQ(trackLists.results.size(), 2); - EXPECT_EQ(trackLists.results[0], trackList1.getId()); - EXPECT_EQ(trackLists.results[1], trackList2.getId()); + ASSERT_EQ(trackLists.size(), 2); + EXPECT_EQ(trackLists[0], trackList1.getId()); + EXPECT_EQ(trackLists[1], trackList2.getId()); } { @@ -103,9 +103,9 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto trackLists{ TrackList::find(session, TrackList::FindParameters{}.setSortMethod(TrackListSortMethod::LastModifiedDesc)) }; - ASSERT_EQ(trackLists.results.size(), 2); - EXPECT_EQ(trackLists.results[0], trackList2.getId()); - EXPECT_EQ(trackLists.results[1], trackList1.getId()); + ASSERT_EQ(trackLists.size(), 2); + EXPECT_EQ(trackLists[0], trackList2.getId()); + EXPECT_EQ(trackLists[1], trackList1.getId()); } { @@ -119,9 +119,9 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; const auto trackLists{ TrackList::find(session, TrackList::FindParameters{}.setSortMethod(TrackListSortMethod::LastModifiedDesc)) }; - ASSERT_EQ(trackLists.results.size(), 2); - EXPECT_EQ(trackLists.results[0], trackList1.getId()); - EXPECT_EQ(trackLists.results[1], trackList2.getId()); + ASSERT_EQ(trackLists.size(), 2); + EXPECT_EQ(trackLists[0], trackList1.getId()); + EXPECT_EQ(trackLists[1], trackList2.getId()); } } @@ -245,7 +245,7 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto trackLists{ TrackList::find(session, TrackList::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster.getId() }))) }; - EXPECT_EQ(trackLists.results.size(), 0); + EXPECT_EQ(trackLists.size(), 0); } { @@ -259,8 +259,8 @@ namespace lms::db::tests auto transaction{ session.createReadTransaction() }; auto trackLists{ TrackList::find(session, TrackList::FindParameters{}.setFilters(Filters{}.setClusters(std::initializer_list{ cluster.getId() }))) }; - ASSERT_EQ(trackLists.results.size(), 1); - EXPECT_EQ(trackLists.results.front(), trackList1.getId()); + ASSERT_EQ(trackLists.size(), 1); + EXPECT_EQ(trackLists.front(), trackList1.getId()); } } @@ -278,8 +278,8 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto entries{ trackList.get()->getEntries() }; - ASSERT_EQ(entries.results.size(), 1); - EXPECT_EQ(entries.results.front()->getTrack()->getId(), track1.getId()); + ASSERT_EQ(entries.size(), 1); + EXPECT_EQ(entries.front()->getTrack()->getId(), track1.getId()); } { @@ -290,16 +290,16 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; auto entries{ trackList.get()->getEntries() }; - ASSERT_EQ(entries.results.size(), 2); - EXPECT_EQ(entries.results[0]->getTrack()->getId(), track1.getId()); - EXPECT_EQ(entries.results[1]->getTrack()->getId(), track2.getId()); + ASSERT_EQ(entries.size(), 2); + EXPECT_EQ(entries[0]->getTrack()->getId(), track1.getId()); + EXPECT_EQ(entries[1]->getTrack()->getId(), track2.getId()); } { auto transaction{ session.createReadTransaction() }; auto entries{ trackList.get()->getEntries(Range{ 1, 1 }) }; - ASSERT_EQ(entries.results.size(), 1); - EXPECT_EQ(entries.results[0]->getTrack()->getId(), track2.getId()); + ASSERT_EQ(entries.size(), 1); + EXPECT_EQ(entries[0]->getTrack()->getId(), track2.getId()); } } diff --git a/src/libs/services/artwork/impl/ArtworkService.cpp b/src/libs/services/artwork/impl/ArtworkService.cpp index 8a8e7875..5b0c6d8f 100644 --- a/src/libs/services/artwork/impl/ArtworkService.cpp +++ b/src/libs/services/artwork/impl/ArtworkService.cpp @@ -169,7 +169,7 @@ namespace lms::artwork } const auto entries{ trackList->getEntries(db::Range{ 0, 10 }) }; - for (const auto& entry : entries.results) + for (const auto& entry : entries) { const auto track{ entry->getTrack() }; if (track->getPreferredMediaArtworkId().isValid()) diff --git a/src/libs/services/feedback/impl/FeedbackService.cpp b/src/libs/services/feedback/impl/FeedbackService.cpp index 1645626f..662c2116 100644 --- a/src/libs/services/feedback/impl/FeedbackService.cpp +++ b/src/libs/services/feedback/impl/FeedbackService.cpp @@ -92,13 +92,9 @@ namespace lms::feedback FeedbackService::ArtistContainer FeedbackService::findStarredArtists(const ArtistFindParameters& params) { - auto backend{ getUserFeedbackBackend(params.user) }; - if (!backend) - return {}; - Artist::FindParameters searchParams; searchParams.setFilters(params.filters); - searchParams.setStarringUser(params.user, *backend); + searchParams.setStarringUser(params.user); searchParams.setKeywords(params.keywords); searchParams.setTrackArtistLinkType(params.trackArtistLinkType); searchParams.setSortMethod(params.sortMethod); @@ -142,12 +138,8 @@ namespace lms::feedback FeedbackService::ReleaseContainer FeedbackService::findStarredReleases(const FindParameters& params) { - auto backend{ getUserFeedbackBackend(params.user) }; - if (!backend) - return {}; - Release::FindParameters searchParams; - searchParams.setStarringUser(params.user, *backend); + searchParams.setStarringUser(params.user); searchParams.setFilters(params.filters); searchParams.setKeywords(params.keywords); searchParams.setSortMethod(ReleaseSortMethod::StarredDateDesc); @@ -191,12 +183,8 @@ namespace lms::feedback FeedbackService::TrackContainer FeedbackService::findStarredTracks(const FindParameters& params) { - auto backend{ getUserFeedbackBackend(params.user) }; - if (!backend) - return {}; - Track::FindParameters searchParams; - searchParams.setStarringUser(params.user, *backend); + searchParams.setStarringUser(params.user); searchParams.setFilters(params.filters); searchParams.setKeywords(params.keywords); searchParams.setSortMethod(TrackSortMethod::StarredDateDesc); diff --git a/src/libs/services/feedback/impl/listenbrainz/FeedbacksSynchronizer.cpp b/src/libs/services/feedback/impl/listenbrainz/FeedbacksSynchronizer.cpp index 2818ae13..b70839de 100644 --- a/src/libs/services/feedback/impl/listenbrainz/FeedbacksSynchronizer.cpp +++ b/src/libs/services/feedback/impl/listenbrainz/FeedbacksSynchronizer.cpp @@ -196,7 +196,7 @@ namespace lms::feedback::listenBrainz using namespace db; auto processPendingFeedbacks{ [this](SyncState scrobblingState, FeedbackType feedbackType) { - RangeResults pendingFeedbacks; + std::vector pendingFeedbacks; { db::Session& session{ _db.getTLSSession() }; @@ -210,9 +210,9 @@ namespace lms::feedback::listenBrainz pendingFeedbacks = StarredTrack::find(session, params); } - LOG(DEBUG, "Queing " << pendingFeedbacks.results.size() << " pending '" << (feedbackType == FeedbackType::Love ? "love" : "erase") << "' feedbacks"); + LOG(DEBUG, "Queing " << pendingFeedbacks.size() << " pending '" << (feedbackType == FeedbackType::Love ? "love" : "erase") << "' feedbacks"); - for (const StarredTrackId starredTrackId : pendingFeedbacks.results) + for (const StarredTrackId starredTrackId : pendingFeedbacks) enqueFeedback(feedbackType, starredTrackId); } }; @@ -270,14 +270,14 @@ namespace lms::feedback::listenBrainz enquePendingFeedbacks(); - db::RangeResults userIds; + std::vector userIds; { db::Session& session{ _db.getTLSSession() }; auto transaction{ session.createReadTransaction() }; userIds = db::User::find(_db.getTLSSession(), db::User::FindParameters{}.setFeedbackBackend(db::FeedbackBackend::ListenBrainz)); } - for (const db::UserId userId : userIds.results) + for (const db::UserId userId : userIds) startSync(getUserContext(userId)); if (!isSyncing()) diff --git a/src/libs/services/feedback/include/services/feedback/IFeedbackService.hpp b/src/libs/services/feedback/include/services/feedback/IFeedbackService.hpp index 519bbcad..7c9f735c 100644 --- a/src/libs/services/feedback/include/services/feedback/IFeedbackService.hpp +++ b/src/libs/services/feedback/include/services/feedback/IFeedbackService.hpp @@ -45,9 +45,9 @@ namespace lms::feedback public: virtual ~IFeedbackService() = default; - using ArtistContainer = db::RangeResults; - using ReleaseContainer = db::RangeResults; - using TrackContainer = db::RangeResults; + using ArtistContainer = std::vector; + using ReleaseContainer = std::vector; + using TrackContainer = std::vector; struct FindParameters { diff --git a/src/libs/services/recommendation/impl/audio-similarity/AudioSimilarityEngine.impl.hpp b/src/libs/services/recommendation/impl/audio-similarity/AudioSimilarityEngine.impl.hpp index 114335ef..1dc6b7d7 100644 --- a/src/libs/services/recommendation/impl/audio-similarity/AudioSimilarityEngine.impl.hpp +++ b/src/libs/services/recommendation/impl/audio-similarity/AudioSimilarityEngine.impl.hpp @@ -627,13 +627,13 @@ namespace lms::recommendation { db::Release::FindParameters params; params.setArtist(artist->getId()); - for (const db::ReleaseId releaseId : db::Release::findIds(session, params).results) + for (const db::ReleaseId releaseId : db::Release::findIds(session, params)) { if (_releaseVectors.contains(releaseId)) { db::Track::FindParameters trackParams; trackParams.setRelease(releaseId); - for (const db::TrackId trackId : db::Track::findIds(session, trackParams).results) + for (const db::TrackId trackId : db::Track::findIds(session, trackParams)) artistTrackIds.insert(trackId); } } diff --git a/src/libs/services/recommendation/impl/tags/TagsEngine.cpp b/src/libs/services/recommendation/impl/tags/TagsEngine.cpp index 6d1d87c6..3eda4ef0 100644 --- a/src/libs/services/recommendation/impl/tags/TagsEngine.cpp +++ b/src/libs/services/recommendation/impl/tags/TagsEngine.cpp @@ -169,11 +169,11 @@ namespace lms::recommendation db::Release::FindParameters params; params.setArtist(artist->getId()); - for (const db::ReleaseId releaseId : db::Release::findIds(session, params).results) + for (const db::ReleaseId releaseId : db::Release::findIds(session, params)) { db::Track::FindParameters trackParams; trackParams.setRelease(releaseId); - for (const db::TrackId trackId : db::Track::findIds(session, trackParams).results) + for (const db::TrackId trackId : db::Track::findIds(session, trackParams)) artistTrackIds.insert(trackId); } } diff --git a/src/libs/services/scanner/impl/steps/ScanStepArtistReconciliation.cpp b/src/libs/services/scanner/impl/steps/ScanStepArtistReconciliation.cpp index 83d036b6..bedce282 100644 --- a/src/libs/services/scanner/impl/steps/ScanStepArtistReconciliation.cpp +++ b/src/libs/services/scanner/impl/steps/ScanStepArtistReconciliation.cpp @@ -183,10 +183,10 @@ namespace lms::scanner auto transaction{ session.createReadTransaction() }; const auto artists{ db::Artist::findWithMBIDNameVariants(session, lastRetrievedArtist, db::Range{ .offset = 0, .size = batchSize }) }; - if (artists.results.empty()) + if (artists.empty()) break; - for (const db::Artist::pointer& artist : artists.results) + for (const db::Artist::pointer& artist : artists) { bool hasArtistInfo{}; db::ArtistInfo::find(session, artist->getId(), db::Range{ .offset = 0, .size = 1 }, [&](const db::ArtistInfo::pointer&) { @@ -218,7 +218,7 @@ namespace lms::scanner } } - if (!artists.moreResults) + if (artists.size() < batchSize) break; } diff --git a/src/libs/services/scanner/impl/steps/ScanStepCheckForDuplicatedFiles.cpp b/src/libs/services/scanner/impl/steps/ScanStepCheckForDuplicatedFiles.cpp index 8c3aafae..266f980d 100644 --- a/src/libs/services/scanner/impl/steps/ScanStepCheckForDuplicatedFiles.cpp +++ b/src/libs/services/scanner/impl/steps/ScanStepCheckForDuplicatedFiles.cpp @@ -41,8 +41,8 @@ namespace lms::scanner Session& session{ _db.getTLSSession() }; auto transaction{ session.createReadTransaction() }; - const RangeResults tracks = Track::findIdsTrackMBIDDuplicates(session); - for (const TrackId trackId : tracks.results) + const std::vector tracks = Track::findIdsTrackMBIDDuplicates(session); + for (const TrackId trackId : tracks) { if (_abortScan) break; diff --git a/src/libs/services/scanner/impl/steps/ScanStepComputeGenreStats.cpp b/src/libs/services/scanner/impl/steps/ScanStepComputeGenreStats.cpp index be1fdb18..8a1636bd 100644 --- a/src/libs/services/scanner/impl/steps/ScanStepComputeGenreStats.cpp +++ b/src/libs/services/scanner/impl/steps/ScanStepComputeGenreStats.cpp @@ -50,7 +50,7 @@ namespace lms::scanner Genre::FindParameters params; params.setRange(range); auto transaction{ dbSession.createReadTransaction() }; - return std::move(Genre::findIds(dbSession, params).results); + return Genre::findIds(dbSession, params); }() }; for (const GenreId genreId : genreIds) @@ -65,6 +65,7 @@ namespace lms::scanner trackCount = Genre::computeTrackCount(dbSession, genreId); releaseCount = Genre::computeReleaseCount(dbSession, genreId); } + { auto transaction{ dbSession.createWriteTransaction() }; auto genre{ Genre::find(dbSession, genreId) }; diff --git a/src/libs/services/scanner/impl/steps/ScanStepRemoveOrphanedDbEntries.cpp b/src/libs/services/scanner/impl/steps/ScanStepRemoveOrphanedDbEntries.cpp index 3eb63d08..3c371fe1 100644 --- a/src/libs/services/scanner/impl/steps/ScanStepRemoveOrphanedDbEntries.cpp +++ b/src/libs/services/scanner/impl/steps/ScanStepRemoveOrphanedDbEntries.cpp @@ -155,7 +155,7 @@ namespace lms::scanner db::Session& session{ _db.getTLSSession() }; - db::RangeResults entries; + std::vector entries; while (!_abortScan) { { @@ -164,16 +164,16 @@ namespace lms::scanner entries = T::findOrphanIds(session, db::Range{ 0, batchSize }); }; - if (entries.results.empty()) + if (entries.empty()) break; { auto transaction{ session.createWriteTransaction() }; - session.destroy(entries.results); + session.destroy(entries); } - context.currentStepStats.processedElems += entries.results.size(); + context.currentStepStats.processedElems += entries.size(); _progressCallback(context.currentStepStats); } } diff --git a/src/libs/services/scanner/impl/steps/ScanStepUpdateLibraryFields.cpp b/src/libs/services/scanner/impl/steps/ScanStepUpdateLibraryFields.cpp index 22500381..b787eeb4 100644 --- a/src/libs/services/scanner/impl/steps/ScanStepUpdateLibraryFields.cpp +++ b/src/libs/services/scanner/impl/steps/ScanStepUpdateLibraryFields.cpp @@ -58,7 +58,7 @@ namespace lms::scanner constexpr std::size_t batchSize = 100; - db::RangeResults entries; + std::vector entries; while (!_abortScan) { { @@ -67,7 +67,7 @@ namespace lms::scanner entries = db::Directory::findMismatchedLibrary(session, db::Range{ 0, batchSize }, mediaLibrary.rootDirectory, mediaLibrary.id); }; - if (entries.results.empty()) + if (entries.empty()) break; { @@ -77,7 +77,7 @@ namespace lms::scanner if (!library) // may be legit break; - for (const db::DirectoryId directoryId : entries.results) + for (const db::DirectoryId directoryId : entries) { if (_abortScan) break; @@ -87,7 +87,7 @@ namespace lms::scanner } } - context.currentStepStats.processedElems += entries.results.size(); + context.currentStepStats.processedElems += entries.size(); _progressCallback(context.currentStepStats); } } diff --git a/src/libs/services/scrobbling/impl/ScrobblingService.cpp b/src/libs/services/scrobbling/impl/ScrobblingService.cpp index a03c0069..21890ab5 100644 --- a/src/libs/services/scrobbling/impl/ScrobblingService.cpp +++ b/src/libs/services/scrobbling/impl/ScrobblingService.cpp @@ -156,17 +156,9 @@ namespace lms::scrobbling ScrobblingService::ArtistContainer ScrobblingService::getRecentArtists(const ArtistFindParameters& params) { ArtistContainer res; - - const auto backend{ getUserBackend(params.user) }; - if (!backend) - return res; - db::Listen::ArtistStatsFindParameters listenFindParams{ convertToListenFindParameters(params) }; - listenFindParams.setScrobblingBackend(backend); - Session& session{ _db.getTLSSession() }; auto transaction{ session.createReadTransaction() }; - res = db::Listen::getRecentArtists(session, listenFindParams); return res; } @@ -174,17 +166,9 @@ namespace lms::scrobbling ScrobblingService::ReleaseContainer ScrobblingService::getRecentReleases(const FindParameters& params) { ReleaseContainer res; - - const auto backend{ getUserBackend(params.user) }; - if (!backend) - return res; - db::Listen::StatsFindParameters listenFindParams{ convertToListenFindParameters(params) }; - listenFindParams.setScrobblingBackend(backend); - Session& session{ _db.getTLSSession() }; auto transaction{ session.createReadTransaction() }; - res = db::Listen::getRecentReleases(session, listenFindParams); return res; } @@ -192,17 +176,9 @@ namespace lms::scrobbling ScrobblingService::TrackContainer ScrobblingService::getRecentTracks(const FindParameters& params) { TrackContainer res; - - const auto backend{ getUserBackend(params.user) }; - if (!backend) - return res; - db::Listen::StatsFindParameters listenFindParams{ convertToListenFindParameters(params) }; - listenFindParams.setScrobblingBackend(backend); - Session& session{ _db.getTLSSession() }; auto transaction{ session.createReadTransaction() }; - res = db::Listen::getRecentTracks(session, listenFindParams); return res; } @@ -243,17 +219,9 @@ namespace lms::scrobbling ScrobblingService::ArtistContainer ScrobblingService::getTopArtists(const ArtistFindParameters& params) { ArtistContainer res; - - const auto backend{ getUserBackend(params.user) }; - if (!backend) - return res; - db::Listen::ArtistStatsFindParameters listenFindParams{ convertToListenFindParameters(params) }; - listenFindParams.setScrobblingBackend(backend); - Session& session{ _db.getTLSSession() }; auto transaction{ session.createReadTransaction() }; - res = db::Listen::getTopArtists(session, listenFindParams); return res; } @@ -261,17 +229,9 @@ namespace lms::scrobbling ScrobblingService::ReleaseContainer ScrobblingService::getTopReleases(const FindParameters& params) { ReleaseContainer res; - - const auto backend{ getUserBackend(params.user) }; - if (!backend) - return res; - db::Listen::StatsFindParameters listenFindParams{ convertToListenFindParameters(params) }; - listenFindParams.setScrobblingBackend(backend); - Session& session{ _db.getTLSSession() }; auto transaction{ session.createReadTransaction() }; - res = db::Listen::getTopReleases(session, listenFindParams); return res; } @@ -279,17 +239,9 @@ namespace lms::scrobbling ScrobblingService::TrackContainer ScrobblingService::getTopTracks(const FindParameters& params) { TrackContainer res; - - const auto backend{ getUserBackend(params.user) }; - if (!backend) - return res; - db::Listen::StatsFindParameters listenFindParams{ convertToListenFindParameters(params) }; - listenFindParams.setScrobblingBackend(backend); - Session& session{ _db.getTLSSession() }; auto transaction{ session.createReadTransaction() }; - res = db::Listen::getTopTracks(session, listenFindParams); return res; } diff --git a/src/libs/services/scrobbling/impl/lastfm/ScrobblingsSynchronizer.cpp b/src/libs/services/scrobbling/impl/lastfm/ScrobblingsSynchronizer.cpp index 07e7751c..50f7e4e7 100644 --- a/src/libs/services/scrobbling/impl/lastfm/ScrobblingsSynchronizer.cpp +++ b/src/libs/services/scrobbling/impl/lastfm/ScrobblingsSynchronizer.cpp @@ -226,8 +226,8 @@ namespace lms::scrobbling::lastFm .setSyncState(db::SyncState::PendingAdd) .setRange(db::Range{ 0, maxBatchSize * 10 }); - const db::RangeResults results{ db::Listen::find(session, params) }; - for (const db::ListenId listenId : results.results) + const auto results{ db::Listen::find(session, params) }; + for (const db::ListenId listenId : results) { const db::Listen::pointer dbListen{ db::Listen::find(session, listenId) }; diff --git a/src/libs/services/scrobbling/impl/listenbrainz/ListensSynchronizer.cpp b/src/libs/services/scrobbling/impl/listenbrainz/ListensSynchronizer.cpp index 9c20ddeb..cc481e45 100644 --- a/src/libs/services/scrobbling/impl/listenbrainz/ListensSynchronizer.cpp +++ b/src/libs/services/scrobbling/impl/listenbrainz/ListensSynchronizer.cpp @@ -214,12 +214,12 @@ namespace lms::scrobbling::listenBrainz const auto tracks{ Track::findIds(session, params) }; // conservative behavior: in case of multiple matches: reject - if (tracks.results.size() == 1) + if (tracks.size() == 1) { LMS_LOG_LISTENBRAINZ(DEBUG, "Matched listen '" << listen << "' using metadata"); - return tracks.results.front(); + return tracks.front(); } - else if (tracks.results.size() > 1) + else if (tracks.size() > 1) { LMS_LOG_LISTENBRAINZ(DEBUG, "Too many matches for listen '" << listen << "' using metadata"); return {}; @@ -349,10 +349,10 @@ namespace lms::scrobbling::listenBrainz .setSyncState(db::SyncState::PendingAdd) .setRange(db::Range{ 0, 100 }); // don't flood too much? - const db::RangeResults results{ db::Listen::find(session, params) }; - pendingListens.reserve(results.results.size()); + const auto results{ db::Listen::find(session, params) }; + pendingListens.reserve(results.size()); - for (db::ListenId listenId : results.results) + for (db::ListenId listenId : results) { const db::Listen::pointer listen{ db::Listen::find(session, listenId) }; @@ -421,14 +421,14 @@ namespace lms::scrobbling::listenBrainz enquePendingListens(); - db::RangeResults userIds; + std::vector userIds; { db::Session& session{ _db.getTLSSession() }; auto transaction{ session.createReadTransaction() }; userIds = db::User::find(_db.getTLSSession(), db::User::FindParameters{}.setScrobblingBackend(db::ScrobblingBackend::ListenBrainz)); } - for (const db::UserId userId : userIds.results) + for (const db::UserId userId : userIds) startSync(getUserContext(userId)); if (!isSyncing()) diff --git a/src/libs/services/scrobbling/include/services/scrobbling/IScrobblingService.hpp b/src/libs/services/scrobbling/include/services/scrobbling/IScrobblingService.hpp index f7af0d49..540173e4 100644 --- a/src/libs/services/scrobbling/include/services/scrobbling/IScrobblingService.hpp +++ b/src/libs/services/scrobbling/include/services/scrobbling/IScrobblingService.hpp @@ -66,9 +66,9 @@ namespace lms::scrobbling virtual void visitNowPlayingListens(const std::function& visitor, db::UserId userId = {}) = 0; // Stats - using ArtistContainer = db::RangeResults; - using ReleaseContainer = db::RangeResults; - using TrackContainer = db::RangeResults; + using ArtistContainer = std::vector; + using ReleaseContainer = std::vector; + using TrackContainer = std::vector; struct FindParameters { diff --git a/src/libs/subsonic/impl/endpoints/AlbumSongLists.cpp b/src/libs/subsonic/impl/endpoints/AlbumSongLists.cpp index f5e8ff0f..8ea5fac4 100644 --- a/src/libs/subsonic/impl/endpoints/AlbumSongLists.cpp +++ b/src/libs/subsonic/impl/endpoints/AlbumSongLists.cpp @@ -58,7 +58,7 @@ namespace lms::api::subsonic const Range range{ offset, size }; - RangeResults releases; + std::vector releases; scrobbling::IScrobblingService& scrobblingService{ *core::Service::get() }; feedback::IFeedbackService& feedbackService{ *core::Service::get() }; @@ -166,7 +166,7 @@ namespace lms::api::subsonic 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) + for (const ReleaseId releaseId : releases) { const Release::pointer release{ Release::find(context.getDbSession(), releaseId) }; albumListNode.addArrayChild("album", createAlbumNode(context, release, id3)); @@ -193,7 +193,7 @@ namespace lms::api::subsonic feedback::IFeedbackService::ArtistFindParameters artistFindParams; artistFindParams.setUser(context.getUser()->getId()); artistFindParams.setSortMethod(ArtistSortMethod::SortName); - for (const ArtistId artistId : feedbackService.findStarredArtists(artistFindParams).results) + for (const ArtistId artistId : feedbackService.findStarredArtists(artistFindParams)) { if (auto artist{ Artist::find(context.getDbSession(), artistId) }) starredNode.addArrayChild("artist", createArtistNode(context, artist)); @@ -204,13 +204,13 @@ namespace lms::api::subsonic findParameters.setUser(context.getUser()->getId()); findParameters.filters.setMediaLibrary(mediaLibrary); - for (const ReleaseId releaseId : feedbackService.findStarredReleases(findParameters).results) + for (const ReleaseId releaseId : feedbackService.findStarredReleases(findParameters)) { if (auto release{ Release::find(context.getDbSession(), releaseId) }) starredNode.addArrayChild("album", createAlbumNode(context, release, id3)); } - for (const TrackId trackId : feedbackService.findStarredTracks(findParameters).results) + for (const TrackId trackId : feedbackService.findStarredTracks(findParameters)) { if (auto track{ Track::find(context.getDbSession(), trackId) }) starredNode.addArrayChild("song", createSongNode(context, track, context.getUser())); diff --git a/src/libs/subsonic/impl/endpoints/Bookmarks.cpp b/src/libs/subsonic/impl/endpoints/Bookmarks.cpp index 3f9758ec..7da14301 100644 --- a/src/libs/subsonic/impl/endpoints/Bookmarks.cpp +++ b/src/libs/subsonic/impl/endpoints/Bookmarks.cpp @@ -41,7 +41,7 @@ namespace lms::api::subsonic Response response{ Response::createOkResponse(context.getServerProtocolVersion()) }; Response::Node& bookmarksNode{ response.createNode("bookmarks") }; - for (const db::TrackBookmarkId bookmarkId : bookmarkIds.results) + for (const db::TrackBookmarkId bookmarkId : bookmarkIds) { const db::TrackBookmark::pointer bookmark{ db::TrackBookmark::find(context.getDbSession(), bookmarkId) }; Response::Node bookmarkNode{ createBookmarkNode(bookmark) }; diff --git a/src/libs/subsonic/impl/endpoints/Browsing.cpp b/src/libs/subsonic/impl/endpoints/Browsing.cpp index 2ebcb9a8..0c3eb52a 100644 --- a/src/libs/subsonic/impl/endpoints/Browsing.cpp +++ b/src/libs/subsonic/impl/endpoints/Browsing.cpp @@ -69,7 +69,7 @@ namespace lms::api::subsonic } else { - res = Directory::findRootDirectories(session).results; + res = Directory::findRootDirectories(session); } return res; @@ -137,8 +137,8 @@ namespace lms::api::subsonic const auto artistTracks{ Track::findIds(context.getDbSession(), params) }; tracks.insert(std::end(tracks), - std::begin(artistTracks.results), - std::end(artistTracks.results)); + std::begin(artistTracks), + std::end(artistTracks)); } return tracks; @@ -173,8 +173,8 @@ namespace lms::api::subsonic const auto releaseTracks{ Track::findIds(context.getDbSession(), params) }; tracks.insert(std::end(tracks), - std::begin(releaseTracks.results), - std::end(releaseTracks.results)); + std::begin(releaseTracks), + std::end(releaseTracks)); } return tracks; @@ -431,7 +431,7 @@ namespace lms::api::subsonic parameters.setRange(Range{ currentArtistOffset, batchSize }); const auto artists{ Artist::find(context.getDbSession(), parameters) }; - for (const Artist::pointer& artist : artists.results) + for (const Artist::pointer& artist : artists) { std::string_view sortName{ artist->getSortName() }; @@ -439,8 +439,8 @@ namespace lms::api::subsonic artistsSortedByFirstChar[sortChar].push_back(artist->getId()); } - hasMoreArtists = artists.moreResults; - currentArtistOffset += artists.results.size(); + hasMoreArtists = (artists.size() == batchSize); + currentArtistOffset += artists.size(); } // second pass: add each artist @@ -509,7 +509,7 @@ namespace lms::api::subsonic Response::Node albumNode{ createAlbumNode(context, release, true /* id3 */) }; const auto tracks{ Track::find(context.getDbSession(), Track::FindParameters{}.setRelease(id).setSortMethod(TrackSortMethod::Release)) }; - for (const Track::pointer& track : tracks.results) + for (const Track::pointer& track : tracks) albumNode.addArrayChild("song", createSongNode(context, track, true /* id3 */)); response.addNode("album", std::move(albumNode)); @@ -660,7 +660,7 @@ namespace lms::api::subsonic params.setArtist(artists.front()->getId()); const auto trackIds{ core::Service::get()->getTopTracks(params) }; - for (const TrackId trackId : trackIds.results) + for (const TrackId trackId : trackIds) { if (Track::pointer track{ Track::find(context.getDbSession(), trackId) }) topSongs.addArrayChild("song", createSongNode(context, track, context.getUser())); diff --git a/src/libs/subsonic/impl/endpoints/MediaRetrieval.cpp b/src/libs/subsonic/impl/endpoints/MediaRetrieval.cpp index 47446d26..16458388 100644 --- a/src/libs/subsonic/impl/endpoints/MediaRetrieval.cpp +++ b/src/libs/subsonic/impl/endpoints/MediaRetrieval.cpp @@ -248,11 +248,11 @@ namespace lms::api::subsonic // Choice: we return nothing if there are too many results const auto tracks{ db::Track::findIds(context.getDbSession(), params) }; - if (tracks.results.size() == 1) + if (tracks.size() == 1) { // Choice: we return only the first lyrics if the track has many lyrics db::TrackLyrics::FindParameters lyricsParams; - lyricsParams.setTrack(tracks.results[0]); + lyricsParams.setTrack(tracks[0]); lyricsParams.setSortMethod(db::TrackLyricsSortMethod::ExternalFirst); lyricsParams.setRange(db::Range{ 0, 1 }); diff --git a/src/libs/subsonic/impl/endpoints/Playlists.cpp b/src/libs/subsonic/impl/endpoints/Playlists.cpp index 00ae150e..a9b606c3 100644 --- a/src/libs/subsonic/impl/endpoints/Playlists.cpp +++ b/src/libs/subsonic/impl/endpoints/Playlists.cpp @@ -107,7 +107,7 @@ namespace lms::api::subsonic Response::Node playlistNode{ createPlaylistNode(context, trackList) }; auto entries{ trackList->getEntries() }; - for (const TrackListEntry::pointer& entry : entries.results) + for (const TrackListEntry::pointer& entry : entries) playlistNode.addArrayChild("entry", createSongNode(context, entry->getTrack(), context.getUser())); response.addNode("playlist", std::move(playlistNode)); @@ -160,7 +160,7 @@ namespace lms::api::subsonic Response::Node playlistNode{ createPlaylistNode(context, trackList) }; auto entries{ trackList->getEntries() }; - for (const TrackListEntry::pointer& entry : entries.results) + for (const TrackListEntry::pointer& entry : entries) playlistNode.addArrayChild("entry", createSongNode(context, entry->getTrack(), context.getUser())); response.addNode("playlist", std::move(playlistNode)); diff --git a/src/libs/subsonic/impl/responses/Album.cpp b/src/libs/subsonic/impl/responses/Album.cpp index c76b8f7b..70dd7056 100644 --- a/src/libs/subsonic/impl/responses/Album.cpp +++ b/src/libs/subsonic/impl/responses/Album.cpp @@ -134,7 +134,7 @@ namespace lms::api::subsonic Genre::FindParameters genreParams; genreParams.setRelease(release->getId()); genreParams.setSortMethod(GenreSortMethod::TrackCountDesc); - const auto genres{ Genre::find(context.getDbSession(), genreParams).results }; + const auto genres{ Genre::find(context.getDbSession(), genreParams) }; if (!genres.empty()) albumNode.setAttribute("genre", genres.front()->getName()); diff --git a/src/lms/ui/PlayQueue.cpp b/src/lms/ui/PlayQueue.cpp index 9d478e89..cf353658 100644 --- a/src/lms/ui/PlayQueue.cpp +++ b/src/lms/ui/PlayQueue.cpp @@ -144,7 +144,7 @@ namespace lms::ui auto transaction{ LmsApp->getDbSession().createWriteTransaction() }; db::TrackList::pointer queue{ getQueue() }; - auto entries{ queue->getEntries().results }; + auto entries{ queue->getEntries() }; core::random::shuffleContainer(entries); queue.modify()->clear(); @@ -404,8 +404,8 @@ namespace lms::ui db::TrackList::pointer queue{ getQueue() }; auto entries{ queue->getEntries(db::Range{ _trackPos ? *_trackPos + 1 : 0, getCapacity() }) }; - tracks.reserve(entries.results.size()); - for (db::TrackListEntry::pointer& entry : entries.results) + tracks.reserve(entries.size()); + for (db::TrackListEntry::pointer& entry : entries) { tracks.push_back(entry->getTrack()->getId()); entry.remove(); @@ -466,10 +466,10 @@ namespace lms::ui const db::TrackList::pointer queue{ getQueue() }; const auto entries{ queue->getEntries(db::Range{ _entriesContainer->getCount(), _batchSize }) }; - for (const db::TrackListEntry::pointer& tracklistEntry : entries.results) + for (const db::TrackListEntry::pointer& tracklistEntry : entries) addEntry(tracklistEntry); - _entriesContainer->setHasMore(entries.moreResults); + _entriesContainer->setHasMore(entries.size() == _batchSize); } void PlayQueue::addEntry(const db::TrackListEntry::pointer& tracklistEntry) diff --git a/src/lms/ui/Utils.cpp b/src/lms/ui/Utils.cpp index 61ad0e8e..25345b59 100644 --- a/src/lms/ui/Utils.cpp +++ b/src/lms/ui/Utils.cpp @@ -235,7 +235,7 @@ namespace lms::ui::utils std::unique_ptr clusterContainer{ std::make_unique() }; // TODO: optimize this - const auto clusterTypes{ ClusterType::findIds(LmsApp->getDbSession()).results }; + const auto clusterTypes{ ClusterType::findIds(LmsApp->getDbSession()) }; const auto clusterGroups{ track->getClusterGroups(clusterTypes, 3) }; for (const auto& clusters : clusterGroups) diff --git a/src/lms/ui/admin/debug/PcmDecodingBenchmark.cpp b/src/lms/ui/admin/debug/PcmDecodingBenchmark.cpp index 329a3f33..3d8aee4a 100644 --- a/src/lms/ui/admin/debug/PcmDecodingBenchmark.cpp +++ b/src/lms/ui/admin/debug/PcmDecodingBenchmark.cpp @@ -81,7 +81,7 @@ namespace lms::ui const auto results{ db::Track::find(session, params) }; std::vector entries; - for (const db::Track::pointer& track : results.results) + for (const db::Track::pointer& track : results) { const auto trackDuration{ track->getDuration() }; if (trackDuration >= minTrackDuration && trackDuration <= maxTrackDuration) diff --git a/src/lms/ui/common/InfiniteScrollingContainer.cpp b/src/lms/ui/common/InfiniteScrollingContainer.cpp index 4a008ab0..8a955eac 100644 --- a/src/lms/ui/common/InfiniteScrollingContainer.cpp +++ b/src/lms/ui/common/InfiniteScrollingContainer.cpp @@ -21,6 +21,9 @@ #include +#include +#include + #include "LoadingIndicator.hpp" namespace lms::ui @@ -41,6 +44,7 @@ namespace lms::ui void InfiniteScrollingContainer::reset() { _elements->clear(); + hideResultHint(); setHasMore(true); } @@ -51,7 +55,8 @@ namespace lms::ui void InfiniteScrollingContainer::add(std::unique_ptr result) { - return _elements->addWidget(std::move(result)); + _gotItems = true; + _elements->addWidget(std::move(result)); } void InfiniteScrollingContainer::setHasMore() @@ -62,9 +67,20 @@ namespace lms::ui void InfiniteScrollingContainer::setHasMore(bool hasMore) { if (hasMore) + { + _gotItems = false; displayLoadingIndicator(); + } else + { hideLoadingIndicator(); + if (getCount() == 0) + displayResultHint(Wt::WString::tr("Lms.infinite-scrolling-container.no-results")); + else if (!_gotItems) + displayResultHint(Wt::WString::tr("Lms.infinite-scrolling-container.limit-reached")); + else + hideResultHint(); + } } void InfiniteScrollingContainer::remove(Wt::WWidget& widget) @@ -113,4 +129,18 @@ namespace lms::ui _loadingIndicator = nullptr; bindEmpty("loading-indicator"); } + + void InfiniteScrollingContainer::displayResultHint(const Wt::WString& msg) + { + _loadingIndicator = nullptr; + auto container{ std::make_unique() }; + container->addStyleClass("my-5 text-center text-muted"); + container->addNew(msg); + bindWidget("loading-indicator", std::move(container)); + } + + void InfiniteScrollingContainer::hideResultHint() + { + bindEmpty("loading-indicator"); + } } // namespace lms::ui diff --git a/src/lms/ui/common/InfiniteScrollingContainer.hpp b/src/lms/ui/common/InfiniteScrollingContainer.hpp index 7167e398..04ed6c95 100644 --- a/src/lms/ui/common/InfiniteScrollingContainer.hpp +++ b/src/lms/ui/common/InfiniteScrollingContainer.hpp @@ -45,7 +45,10 @@ namespace lms::ui template T* addNew(Args&&... args) { - return _elements->addNew(std::forward(args)...); + auto widget{ std::make_unique(std::forward(args)...) }; + T* ptr{ widget.get() }; + add(std::move(widget)); + return ptr; } void remove(Wt::WWidget& widget); @@ -63,8 +66,11 @@ namespace lms::ui void clear() override; void displayLoadingIndicator(); void hideLoadingIndicator(); + void displayResultHint(const Wt::WString& msg); + void hideResultHint(); Wt::WContainerWidget* _elements; Wt::WTemplate* _loadingIndicator; + bool _gotItems{}; }; } // namespace lms::ui diff --git a/src/lms/ui/explore/ArtistCollector.cpp b/src/lms/ui/explore/ArtistCollector.cpp index 03263039..2c1a8487 100644 --- a/src/lms/ui/explore/ArtistCollector.cpp +++ b/src/lms/ui/explore/ArtistCollector.cpp @@ -19,85 +19,97 @@ #include "ArtistCollector.hpp" -#include "core/Service.hpp" #include "core/Utils.hpp" #include "database/Session.hpp" #include "database/objects/Artist.hpp" +#include "database/objects/Listen.hpp" #include "database/objects/TrackList.hpp" #include "database/objects/Types.hpp" #include "database/objects/User.hpp" -#include "services/feedback/IFeedbackService.hpp" -#include "services/scrobbling/IScrobblingService.hpp" #include "LmsApplication.hpp" namespace lms::ui { - db::RangeResults ArtistCollector::get(std::optional requestedRange) + void ArtistCollector::get(db::Range requestedRange, bool& moreResults, const std::function&)>& func) { - feedback::IFeedbackService& feedbackService{ *core::Service::get() }; - scrobbling::IScrobblingService& scrobblingService{ *core::Service::get() }; - const Range range{ getActualRange(requestedRange) }; - db::RangeResults artists; + auto applyArtistType = [&](auto& params) { + std::visit(core::utils::overloads{ + [&](AllArtistsTag) {}, + [&](ReleaseArtistsTag) { params.setReleaseArtistsOnly(true); }, + [&](db::TrackArtistLinkType trackArtistLinkType) { params.setTrackArtistLinkType(trackArtistLinkType); } }, + _artistType); + }; switch (getMode()) { case Mode::Random: - artists = getRandomArtists(range); - break; + { + if (!_randomArtists) + { + db::Artist::FindParameters params; + params.setFilters(getDbFilters()); + params.setKeywords(getSearchKeywords()); + params.setSortMethod(db::ArtistSortMethod::Random); + params.setRange(db::Range{ 0, getMaxCount() }); + applyArtistType(params); + _randomArtists = db::Artist::findIds(LmsApp->getDbSession(), params); + } + const auto& all{ *_randomArtists }; + const std::size_t offset{ std::min(range.offset, all.size()) }; + const auto slice{ std::span{ all }.subspan(offset, std::min(range.size, all.size() - offset)) }; + moreResults = (offset + slice.size() < all.size()); + for (const auto id : slice) + { + if (const auto artist{ db::Artist::find(LmsApp->getDbSession(), id) }) + func(artist); + } + break; + } case Mode::Starred: { - feedback::IFeedbackService::ArtistFindParameters params; + db::Artist::FindParameters params; params.setFilters(getDbFilters()); - params.setUser(LmsApp->getUserId()); params.setKeywords(getSearchKeywords()); params.setSortMethod(db::ArtistSortMethod::StarredDateDesc); params.setRange(range); - std::visit(core::utils::overloads{ - [&](AllArtistsTag) {}, - [&](ReleaseArtistsTag) { params.setReleaseArtistsOnly(true); }, - [&](db::TrackArtistLinkType trackArtistLinkType) { params.setTrackArtistLinkType(trackArtistLinkType); } }, - _artistType); - - artists = feedbackService.findStarredArtists(params); + params.setStarringUser(LmsApp->getUserId()); + applyArtistType(params); + std::size_t count{}; + db::Artist::find(LmsApp->getDbSession(), params, [&](const auto& a) { func(a); ++count; }); + moreResults = (count == range.size); break; } case Mode::RecentlyPlayed: { - scrobbling::IScrobblingService::ArtistFindParameters params; - params.setUser(LmsApp->getUserId()); + db::Listen::ArtistStatsFindParameters params; params.setFilters(getDbFilters()); params.setKeywords(getSearchKeywords()); params.setRange(range); - std::visit(core::utils::overloads{ - [&](AllArtistsTag) {}, - [&](ReleaseArtistsTag) { params.setReleaseArtistsOnly(true); }, - [&](db::TrackArtistLinkType trackArtistLinkType) { params.setTrackArtistLinkType(trackArtistLinkType); } }, - _artistType); - - artists = scrobblingService.getRecentArtists(params); + params.setUser(LmsApp->getUserId()); + applyArtistType(params); + std::size_t count{}; + db::Listen::getRecentArtists(LmsApp->getDbSession(), params, [&](const auto& a) { func(a); ++count; }); + moreResults = (count == range.size); break; } case Mode::MostPlayed: { - scrobbling::IScrobblingService::ArtistFindParameters params; - params.setUser(LmsApp->getUserId()); + db::Listen::ArtistStatsFindParameters params; params.setFilters(getDbFilters()); params.setKeywords(getSearchKeywords()); params.setRange(range); - std::visit(core::utils::overloads{ - [&](AllArtistsTag) {}, - [&](ReleaseArtistsTag) { params.setReleaseArtistsOnly(true); }, - [&](db::TrackArtistLinkType trackArtistLinkType) { params.setTrackArtistLinkType(trackArtistLinkType); } }, - _artistType); - - artists = scrobblingService.getTopArtists(params); + params.setUser(LmsApp->getUserId()); + applyArtistType(params); + std::size_t count{}; + db::Listen::getTopArtists(LmsApp->getDbSession(), params, [&](const auto& a) { func(a); ++count; }); + moreResults = (count == range.size); break; } @@ -108,16 +120,10 @@ namespace lms::ui params.setKeywords(getSearchKeywords()); params.setSortMethod(db::ArtistSortMethod::AddedDesc); params.setRange(range); - std::visit(core::utils::overloads{ - [&](AllArtistsTag) {}, - [&](ReleaseArtistsTag) { params.setReleaseArtistsOnly(true); }, - [&](db::TrackArtistLinkType trackArtistLinkType) { params.setTrackArtistLinkType(trackArtistLinkType); } }, - _artistType); - - { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - artists = db::Artist::findIds(LmsApp->getDbSession(), params); - } + applyArtistType(params); + std::size_t count{}; + db::Artist::find(LmsApp->getDbSession(), params, [&](const auto& a) { func(a); ++count; }); + moreResults = (count == range.size); break; } @@ -128,16 +134,10 @@ namespace lms::ui params.setKeywords(getSearchKeywords()); params.setSortMethod(db::ArtistSortMethod::LastWrittenDesc); params.setRange(range); - std::visit(core::utils::overloads{ - [&](AllArtistsTag) {}, - [&](ReleaseArtistsTag) { params.setReleaseArtistsOnly(true); }, - [&](db::TrackArtistLinkType trackArtistLinkType) { params.setTrackArtistLinkType(trackArtistLinkType); } }, - _artistType); - - { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - artists = db::Artist::findIds(LmsApp->getDbSession(), params); - } + applyArtistType(params); + std::size_t count{}; + db::Artist::find(LmsApp->getDbSession(), params, [&](const auto& a) { func(a); ++count; }); + moreResults = (count == range.size); break; } @@ -148,49 +148,13 @@ namespace lms::ui params.setKeywords(getSearchKeywords()); params.setSortMethod(db::ArtistSortMethod::SortName); params.setRange(range); - std::visit(core::utils::overloads{ - [&](AllArtistsTag) {}, - [&](ReleaseArtistsTag) { params.setReleaseArtistsOnly(true); }, - [&](db::TrackArtistLinkType trackArtistLinkType) { params.setTrackArtistLinkType(trackArtistLinkType); } }, - _artistType); - - { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - artists = db::Artist::findIds(LmsApp->getDbSession(), params); - } + applyArtistType(params); + std::size_t count{}; + db::Artist::find(LmsApp->getDbSession(), params, [&](const auto& a) { func(a); ++count; }); + moreResults = (count == range.size); break; } } - - if (range.offset + range.size == getMaxCount()) - artists.moreResults = false; - - return artists; } - db::RangeResults ArtistCollector::getRandomArtists(Range range) - { - assert(getMode() == Mode::Random); - - if (!_randomArtists) - { - db::Artist::FindParameters params; - params.setFilters(getDbFilters()); - params.setKeywords(getSearchKeywords()); - params.setSortMethod(db::ArtistSortMethod::Random); - params.setRange(db::Range{ 0, getMaxCount() }); - std::visit(core::utils::overloads{ - [&](AllArtistsTag) {}, - [&](ReleaseArtistsTag) { params.setReleaseArtistsOnly(true); }, - [&](db::TrackArtistLinkType trackArtistLinkType) { params.setTrackArtistLinkType(trackArtistLinkType); } }, - _artistType); - - { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - _randomArtists = db::Artist::findIds(LmsApp->getDbSession(), params); - } - } - - return _randomArtists->getSubRange(range); - } } // namespace lms::ui diff --git a/src/lms/ui/explore/ArtistCollector.hpp b/src/lms/ui/explore/ArtistCollector.hpp index 6a61706e..9254e792 100644 --- a/src/lms/ui/explore/ArtistCollector.hpp +++ b/src/lms/ui/explore/ArtistCollector.hpp @@ -19,8 +19,12 @@ #pragma once +#include #include +#include +#include "database/Object.hpp" +#include "database/Types.hpp" #include "database/objects/ArtistId.hpp" #include "ArtistType.hpp" @@ -38,13 +42,12 @@ namespace lms::ui public: using DatabaseCollectorBase::DatabaseCollectorBase; - db::RangeResults get(std::optional range = std::nullopt); + void get(db::Range range, bool& moreResults, const std::function&)>& func); void reset() { _randomArtists.reset(); } void setArtistType(ArtistType artistType) { _artistType = artistType; } private: - db::RangeResults getRandomArtists(Range range); - std::optional> _randomArtists; + std::optional> _randomArtists; ArtistType _artistType; }; } // namespace lms::ui diff --git a/src/lms/ui/explore/ArtistView.cpp b/src/lms/ui/explore/ArtistView.cpp index 92bc2d9f..2a7a386d 100644 --- a/src/lms/ui/explore/ArtistView.cpp +++ b/src/lms/ui/explore/ArtistView.cpp @@ -175,7 +175,7 @@ namespace lms::ui }); }); - auto clusterTypes{ db::ClusterType::findIds(LmsApp->getDbSession()).results }; + auto clusterTypes{ db::ClusterType::findIds(LmsApp->getDbSession()) }; auto clusterGroups{ artist->getClusterGroups(clusterTypes, 3) }; for (const auto& clusters : clusterGroups) @@ -466,7 +466,7 @@ namespace lms::ui auto transaction{ LmsApp->getDbSession().createReadTransaction() }; const auto tracks{ db::Track::find(LmsApp->getDbSession(), params) }; - for (const db::Track::pointer& track : tracks.results) + for (const db::Track::pointer& track : tracks) { // TODO handle this with range if (_trackContainer->getCount() == _tracksMaxCount) @@ -477,7 +477,7 @@ namespace lms::ui areTracksAdded = true; } - _trackContainer->setHasMore(tracks.moreResults); + _trackContainer->setHasMore(tracks.size() == range.size); return areTracksAdded; } diff --git a/src/lms/ui/explore/ArtistsView.cpp b/src/lms/ui/explore/ArtistsView.cpp index 2c19c98e..2239fd99 100644 --- a/src/lms/ui/explore/ArtistsView.cpp +++ b/src/lms/ui/explore/ArtistsView.cpp @@ -111,19 +111,14 @@ namespace lms::ui void Artists::addSome() { - const auto artistIds{ _artistCollector.get(db::Range{ static_cast(_container->getCount()), _batchSize }) }; - + bool moreResults{}; { auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - - for (const db::ArtistId artistId : artistIds.results) - { - if (const auto artist{ db::Artist::find(LmsApp->getDbSession(), artistId) }) - _container->add(ArtistListHelpers::createEntry(artist)); - } + _artistCollector.get(db::Range{ static_cast(_container->getCount()), _batchSize }, moreResults, [&](const db::Artist::pointer& artist) { + _container->add(ArtistListHelpers::createEntry(artist)); + }); } - - _container->setHasMore(artistIds.moreResults); + _container->setHasMore(moreResults); } } // namespace lms::ui diff --git a/src/lms/ui/explore/ArtistsView.hpp b/src/lms/ui/explore/ArtistsView.hpp index fe3f3839..1e27c544 100644 --- a/src/lms/ui/explore/ArtistsView.hpp +++ b/src/lms/ui/explore/ArtistsView.hpp @@ -44,7 +44,7 @@ namespace lms::ui void addSome(); static constexpr std::size_t _batchSize{ 30 }; - static constexpr std::size_t _maxCount{ 8000 }; + static constexpr std::size_t _maxCount{ 5'000 }; Wt::WWidget* _currentLinkTypeActiveItem{}; InfiniteScrollingContainer* _container{}; diff --git a/src/lms/ui/explore/DatabaseCollectorBase.cpp b/src/lms/ui/explore/DatabaseCollectorBase.cpp index 11188c1f..6bb74737 100644 --- a/src/lms/ui/explore/DatabaseCollectorBase.cpp +++ b/src/lms/ui/explore/DatabaseCollectorBase.cpp @@ -34,24 +34,14 @@ namespace lms::ui { } - DatabaseCollectorBase::Range DatabaseCollectorBase::getActualRange(std::optional requestedRange) const + DatabaseCollectorBase::Range DatabaseCollectorBase::getActualRange(Range requestedRange) const { - db::Range res; - - if (!requestedRange) - { - res.offset = 0; - res.size = _maxCount; - } + Range res; + res.offset = requestedRange.offset; + if (requestedRange.offset < _maxCount) + res.size = std::min(_maxCount - requestedRange.offset, requestedRange.size); else - { - res.offset = requestedRange->offset; - if (requestedRange->offset < _maxCount) - res.size = std::min(_maxCount - requestedRange->offset, requestedRange->size); - else - res.size = 0; - } - + res.size = 0; return res; } diff --git a/src/lms/ui/explore/DatabaseCollectorBase.hpp b/src/lms/ui/explore/DatabaseCollectorBase.hpp index f6f1ab26..3f33efc4 100644 --- a/src/lms/ui/explore/DatabaseCollectorBase.hpp +++ b/src/lms/ui/explore/DatabaseCollectorBase.hpp @@ -19,7 +19,6 @@ #pragma once -#include #include #include #include @@ -60,7 +59,7 @@ namespace lms::ui void setSearch(std::string_view search); protected: - Range getActualRange(std::optional range) const; + Range getActualRange(Range range) const; std::size_t getMaxCount() const; const db::Filters& getDbFilters() const; const std::vector& getSearchKeywords() const { return _searchKeywords; } diff --git a/src/lms/ui/explore/PlayQueueController.cpp b/src/lms/ui/explore/PlayQueueController.cpp index 3a069b2f..5f50eca0 100644 --- a/src/lms/ui/explore/PlayQueueController.cpp +++ b/src/lms/ui/explore/PlayQueueController.cpp @@ -49,8 +49,8 @@ namespace lms::ui const auto tracks{ db::Track::findIds(session, params) }; - res.reserve(res.size() + tracks.results.size()); - res.insert(std::end(res), std::cbegin(tracks.results), std::cend(tracks.results)); + res.reserve(res.size() + tracks.size()); + res.insert(std::end(res), std::cbegin(tracks), std::cend(tracks)); if (res.size() == maxTrackCount) break; @@ -77,8 +77,8 @@ namespace lms::ui const auto tracks{ db::Track::findIds(session, params) }; - res.reserve(res.size() + tracks.results.size()); - res.insert(std::end(res), std::cbegin(tracks.results), std::cend(tracks.results)); + res.reserve(res.size() + tracks.size()); + res.insert(std::end(res), std::cbegin(tracks), std::cend(tracks)); if (res.size() == maxTrackCount) break; @@ -103,7 +103,7 @@ namespace lms::ui const auto tracks{ db::Track::findIds(session, params) }; - return tracks.results; + return tracks; } std::vector getTrackListTracks(db::Session& session, db::TrackListId trackListId, const Filters& filters, std::size_t maxTrackCount) @@ -118,7 +118,7 @@ namespace lms::ui params.setRange(db::Range{ 0, maxTrackCount }); params.setSortMethod(db::TrackSortMethod::TrackList); - return db::Track::findIds(session, params).results; + return db::Track::findIds(session, params); } } // namespace diff --git a/src/lms/ui/explore/ReleaseCollector.cpp b/src/lms/ui/explore/ReleaseCollector.cpp index c404990c..2dbf17e8 100644 --- a/src/lms/ui/explore/ReleaseCollector.cpp +++ b/src/lms/ui/explore/ReleaseCollector.cpp @@ -19,65 +19,82 @@ #include "ReleaseCollector.hpp" -#include "core/Service.hpp" #include "database/Session.hpp" +#include "database/objects/Listen.hpp" #include "database/objects/Release.hpp" #include "database/objects/User.hpp" -#include "services/feedback/IFeedbackService.hpp" -#include "services/scrobbling/IScrobblingService.hpp" #include "Filters.hpp" #include "LmsApplication.hpp" namespace lms::ui { - db::RangeResults ReleaseCollector::get(std::optional requestedRange) + void ReleaseCollector::get(db::Range requestedRange, bool& moreResults, const std::function&)>& func) { - feedback::IFeedbackService& feedbackService{ *core::Service::get() }; - scrobbling::IScrobblingService& scrobblingService{ *core::Service::get() }; - const db::Range range{ getActualRange(requestedRange) }; - db::RangeResults releases; - switch (getMode()) { case Mode::Random: - releases = getRandomReleases(range); - break; - - case Mode::Starred: { - feedback::IFeedbackService::FindParameters params; - params.setUser(LmsApp->getUserId()); - params.setFilters(getDbFilters()); - params.setKeywords(getSearchKeywords()); - params.setRange(range); - releases = feedbackService.findStarredReleases(params); + if (!_randomReleases) + { + db::Release::FindParameters params; + params.setFilters(getDbFilters()); + params.setKeywords(getSearchKeywords()); + params.setSortMethod(db::ReleaseSortMethod::Random); + params.setRange(db::Range{ 0, getMaxCount() }); + _randomReleases = db::Release::findIds(LmsApp->getDbSession(), params); + } + const auto& all{ *_randomReleases }; + const std::size_t offset{ std::min(range.offset, all.size()) }; + const auto slice{ std::span{ all }.subspan(offset, std::min(range.size, all.size() - offset)) }; + moreResults = (offset + slice.size() < all.size()); + for (const auto id : slice) + { + if (const auto release{ db::Release::find(LmsApp->getDbSession(), id) }) + func(release); + } break; } - case ReleaseCollector::Mode::RecentlyPlayed: + case Mode::Starred: { - scrobbling::IScrobblingService::FindParameters params; - params.setUser(LmsApp->getUserId()); + db::Release::FindParameters params; + params.setFilters(getDbFilters()); + params.setKeywords(getSearchKeywords()); + params.setSortMethod(db::ReleaseSortMethod::StarredDateDesc); + params.setRange(range); + params.setStarringUser(LmsApp->getUserId()); + std::size_t count{}; + db::Release::find(LmsApp->getDbSession(), params, [&](const auto& r) { func(r); ++count; }); + moreResults = (count == range.size); + break; + } + + case Mode::RecentlyPlayed: + { + db::Listen::StatsFindParameters params; params.setFilters(getDbFilters()); params.setKeywords(getSearchKeywords()); params.setRange(range); - - releases = scrobblingService.getRecentReleases(params); + params.setUser(LmsApp->getUserId()); + std::size_t count{}; + db::Listen::getRecentReleases(LmsApp->getDbSession(), params, [&](const auto& r) { func(r); ++count; }); + moreResults = (count == range.size); break; } case Mode::MostPlayed: { - scrobbling::IScrobblingService::FindParameters params; - params.setUser(LmsApp->getUserId()); + db::Listen::StatsFindParameters params; params.setFilters(getDbFilters()); params.setKeywords(getSearchKeywords()); params.setRange(range); - - releases = scrobblingService.getTopReleases(params); + params.setUser(LmsApp->getUserId()); + std::size_t count{}; + db::Listen::getTopReleases(LmsApp->getDbSession(), params, [&](const auto& r) { func(r); ++count; }); + moreResults = (count == range.size); break; } @@ -88,11 +105,9 @@ namespace lms::ui params.setKeywords(getSearchKeywords()); params.setSortMethod(db::ReleaseSortMethod::AddedDesc); params.setRange(range); - - { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - releases = db::Release::findIds(LmsApp->getDbSession(), params); - } + std::size_t count{}; + db::Release::find(LmsApp->getDbSession(), params, [&](const auto& r) { func(r); ++count; }); + moreResults = (count == range.size); break; } @@ -103,11 +118,9 @@ namespace lms::ui params.setKeywords(getSearchKeywords()); params.setSortMethod(db::ReleaseSortMethod::LastWrittenDesc); params.setRange(range); - - { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - releases = db::Release::findIds(LmsApp->getDbSession(), params); - } + std::size_t count{}; + db::Release::find(LmsApp->getDbSession(), params, [&](const auto& r) { func(r); ++count; }); + moreResults = (count == range.size); break; } @@ -118,40 +131,12 @@ namespace lms::ui params.setSortMethod(db::ReleaseSortMethod::SortName); params.setKeywords(getSearchKeywords()); params.setRange(range); - - { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - releases = db::Release::findIds(LmsApp->getDbSession(), params); - } + std::size_t count{}; + db::Release::find(LmsApp->getDbSession(), params, [&](const auto& r) { func(r); ++count; }); + moreResults = (count == range.size); break; } } - - if (range.offset + range.size == getMaxCount()) - releases.moreResults = false; - - return releases; - } - - db::RangeResults ReleaseCollector::getRandomReleases(Range range) - { - assert(getMode() == Mode::Random); - - if (!_randomReleases) - { - db::Release::FindParameters params; - params.setFilters(getDbFilters()); - params.setKeywords(getSearchKeywords()); - params.setSortMethod(db::ReleaseSortMethod::Random); - params.setRange(db::Range{ 0, getMaxCount() }); - - { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - _randomReleases = db::Release::findIds(LmsApp->getDbSession(), params); - } - } - - return _randomReleases->getSubRange(range); } } // namespace lms::ui diff --git a/src/lms/ui/explore/ReleaseCollector.hpp b/src/lms/ui/explore/ReleaseCollector.hpp index cd434b54..b1eeffe8 100644 --- a/src/lms/ui/explore/ReleaseCollector.hpp +++ b/src/lms/ui/explore/ReleaseCollector.hpp @@ -19,10 +19,13 @@ #pragma once +#include #include +#include #include "DatabaseCollectorBase.hpp" +#include "database/Object.hpp" #include "database/Types.hpp" #include "database/objects/ReleaseId.hpp" @@ -38,11 +41,10 @@ namespace lms::ui public: using DatabaseCollectorBase::DatabaseCollectorBase; - db::RangeResults get(std::optional range = std::nullopt); + void get(db::Range range, bool& moreResults, const std::function&)>& func); void reset() { _randomReleases.reset(); } private: - db::RangeResults getRandomReleases(Range range); - std::optional> _randomReleases; + std::optional> _randomReleases; }; } // namespace lms::ui diff --git a/src/lms/ui/explore/ReleaseView.cpp b/src/lms/ui/explore/ReleaseView.cpp index 170ef5a5..74806986 100644 --- a/src/lms/ui/explore/ReleaseView.cpp +++ b/src/lms/ui/explore/ReleaseView.cpp @@ -313,7 +313,7 @@ namespace lms::ui }); }); - const auto clusterTypeIds{ db::ClusterType::findIds(session).results }; + const auto clusterTypeIds{ db::ClusterType::findIds(session) }; const auto clusterGroups{ release->getClusterGroups(clusterTypeIds, maxTagCloudItemCount) }; for (const auto& clusters : clusterGroups) @@ -607,13 +607,13 @@ namespace lms::ui params.setSortMethod(db::ReleaseSortMethod::DateAsc); const auto releaseIds{ db::Release::findIds(LmsApp->getDbSession(), params) }; - if (releaseIds.results.size() <= 1) + if (releaseIds.size() <= 1) return; setCondition("if-has-other-versions", true); auto* container{ bindNew("other-versions") }; - for (const db::ReleaseId id : releaseIds.results) + for (const db::ReleaseId id : releaseIds) { if (id == _releaseId) continue; diff --git a/src/lms/ui/explore/ReleasesView.cpp b/src/lms/ui/explore/ReleasesView.cpp index 99d3cf53..f148c271 100644 --- a/src/lms/ui/explore/ReleasesView.cpp +++ b/src/lms/ui/explore/ReleasesView.cpp @@ -114,25 +114,27 @@ namespace lms::ui void Releases::addSome() { - const auto releaseIds{ _releaseCollector.get(db::Range{ static_cast(_container->getCount()), _batchSize }) }; - + bool moreResults{}; { auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - - for (const db::ReleaseId releaseId : releaseIds.results) - { - if (const db::Release::pointer release{ db::Release::find(LmsApp->getDbSession(), releaseId) }) - _container->add(releaseListHelpers::createEntry(release, { releaseListHelpers::DisplayOptions::ShowArtist })); - } + _releaseCollector.get(db::Range{ static_cast(_container->getCount()), _batchSize }, moreResults, [&](const db::Release::pointer& release) { + _container->add(releaseListHelpers::createEntry(release, { releaseListHelpers::DisplayOptions::ShowArtist })); + }); } - - _container->setHasMore(releaseIds.moreResults); + _container->setHasMore(moreResults); } std::vector Releases::getAllReleases() { - db::RangeResults releaseIds{ _releaseCollector.get() }; - return std::move(releaseIds.results); + std::vector ids; + bool moreResults{}; + { + auto transaction{ LmsApp->getDbSession().createReadTransaction() }; + _releaseCollector.get(db::Range{ 0, _maxCount }, moreResults, [&](const db::Release::pointer& release) { + ids.push_back(release->getId()); + }); + } + return ids; } } // namespace lms::ui diff --git a/src/lms/ui/explore/ReleasesView.hpp b/src/lms/ui/explore/ReleasesView.hpp index f321b2bb..7c3ce598 100644 --- a/src/lms/ui/explore/ReleasesView.hpp +++ b/src/lms/ui/explore/ReleasesView.hpp @@ -41,9 +41,8 @@ namespace lms::ui void addSome(); std::vector getAllReleases(); - static constexpr std::size_t _maxItemsPerLine{ 6 }; - static constexpr std::size_t _batchSize{ _maxItemsPerLine }; - static constexpr std::size_t _maxCount{ _maxItemsPerLine * 500 }; + static constexpr std::size_t _batchSize{ 30 }; + static constexpr std::size_t _maxCount{ 5'000 }; PlayQueueController& _playQueueController; InfiniteScrollingContainer* _container{}; diff --git a/src/lms/ui/explore/TrackCollector.cpp b/src/lms/ui/explore/TrackCollector.cpp index 83f3978d..3bb22131 100644 --- a/src/lms/ui/explore/TrackCollector.cpp +++ b/src/lms/ui/explore/TrackCollector.cpp @@ -19,66 +19,80 @@ #include "TrackCollector.hpp" -#include "core/Service.hpp" -#include "database/Session.hpp" +#include "database/objects/Listen.hpp" #include "database/objects/Track.hpp" #include "database/objects/TrackList.hpp" -#include "database/objects/User.hpp" -#include "services/feedback/IFeedbackService.hpp" -#include "services/scrobbling/IScrobblingService.hpp" -#include "Filters.hpp" #include "LmsApplication.hpp" namespace lms::ui { - db::RangeResults TrackCollector::get(std::optional requestedRange) + void TrackCollector::get(db::Range requestedRange, bool& moreResults, const std::function&)>& func) { - feedback::IFeedbackService& feedbackService{ *core::Service::get() }; - scrobbling::IScrobblingService& scrobblingService{ *core::Service::get() }; - const db::Range range{ getActualRange(requestedRange) }; - db::RangeResults tracks; - switch (getMode()) { case Mode::Random: - tracks = getRandomTracks(range); - break; - - case Mode::Starred: { - feedback::IFeedbackService::FindParameters params; - params.setFilters(getDbFilters()); - params.setKeywords(getSearchKeywords()); - params.setRange(range); - params.setUser(LmsApp->getUserId()); - tracks = feedbackService.findStarredTracks(params); + if (!_randomTracks) + { + db::Track::FindParameters params; + params.setFilters(getDbFilters()); + params.setKeywords(getSearchKeywords()); + params.setSortMethod(db::TrackSortMethod::Random); + params.setRange(db::Range{ 0, getMaxCount() }); + _randomTracks = db::Track::findIds(LmsApp->getDbSession(), params); + } + const auto& all{ *_randomTracks }; + const std::size_t offset{ std::min(range.offset, all.size()) }; + const auto slice{ std::span{ all }.subspan(offset, std::min(range.size, all.size() - offset)) }; + moreResults = (offset + slice.size() < all.size()); + for (const auto id : slice) + { + if (const auto track{ db::Track::find(LmsApp->getDbSession(), id) }) + func(track); + } break; } - case TrackCollector::Mode::RecentlyPlayed: + case Mode::Starred: { - scrobbling::IScrobblingService::FindParameters params; - params.setUser(LmsApp->getUserId()); + db::Track::FindParameters params; + params.setFilters(getDbFilters()); + params.setKeywords(getSearchKeywords()); + params.setSortMethod(db::TrackSortMethod::StarredDateDesc); + params.setRange(range); + params.setStarringUser(LmsApp->getUserId()); + std::size_t count{}; + db::Track::find(LmsApp->getDbSession(), params, [&](const auto& t) { func(t); ++count; }); + moreResults = (count == range.size); + break; + } + + case Mode::RecentlyPlayed: + { + db::Listen::StatsFindParameters params; params.setFilters(getDbFilters()); params.setKeywords(getSearchKeywords()); params.setRange(range); - - tracks = scrobblingService.getRecentTracks(params); + params.setUser(LmsApp->getUserId()); + std::size_t count{}; + db::Listen::getRecentTracks(LmsApp->getDbSession(), params, [&](const auto& t) { func(t); ++count; }); + moreResults = (count == range.size); break; } case Mode::MostPlayed: { - scrobbling::IScrobblingService::FindParameters params; - params.setUser(LmsApp->getUserId()); + db::Listen::StatsFindParameters params; params.setFilters(getDbFilters()); params.setKeywords(getSearchKeywords()); params.setRange(range); - - tracks = scrobblingService.getTopTracks(params); + params.setUser(LmsApp->getUserId()); + std::size_t count{}; + db::Listen::getTopTracks(LmsApp->getDbSession(), params, [&](const auto& t) { func(t); ++count; }); + moreResults = (count == range.size); break; } @@ -89,11 +103,9 @@ namespace lms::ui params.setKeywords(getSearchKeywords()); params.setSortMethod(db::TrackSortMethod::AddedDesc); params.setRange(range); - - { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - tracks = db::Track::findIds(LmsApp->getDbSession(), params); - } + std::size_t count{}; + db::Track::find(LmsApp->getDbSession(), params, [&](const auto& t) { func(t); ++count; }); + moreResults = (count == range.size); break; } @@ -104,11 +116,9 @@ namespace lms::ui params.setKeywords(getSearchKeywords()); params.setSortMethod(db::TrackSortMethod::LastWrittenDesc); params.setRange(range); - - { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - tracks = db::Track::findIds(LmsApp->getDbSession(), params); - } + std::size_t count{}; + db::Track::find(LmsApp->getDbSession(), params, [&](const auto& t) { func(t); ++count; }); + moreResults = (count == range.size); break; } @@ -118,40 +128,12 @@ namespace lms::ui params.setFilters(getDbFilters()); params.setKeywords(getSearchKeywords()); params.setRange(range); - - { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - tracks = db::Track::findIds(LmsApp->getDbSession(), params); - } + std::size_t count{}; + db::Track::find(LmsApp->getDbSession(), params, [&](const auto& t) { func(t); ++count; }); + moreResults = (count == range.size); break; } } - - if (range.offset + range.size == getMaxCount()) - tracks.moreResults = false; - - return tracks; - } - - db::RangeResults TrackCollector::getRandomTracks(Range range) - { - assert(getMode() == Mode::Random); - - if (!_randomTracks) - { - db::Track::FindParameters params; - params.setFilters(getDbFilters()); - params.setKeywords(getSearchKeywords()); - params.setSortMethod(db::TrackSortMethod::Random); - params.setRange(db::Range{ 0, getMaxCount() }); - - { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - _randomTracks = db::Track::findIds(LmsApp->getDbSession(), params); - } - } - - return _randomTracks->getSubRange(range); } } // namespace lms::ui diff --git a/src/lms/ui/explore/TrackCollector.hpp b/src/lms/ui/explore/TrackCollector.hpp index b27ea867..2d9bedd6 100644 --- a/src/lms/ui/explore/TrackCollector.hpp +++ b/src/lms/ui/explore/TrackCollector.hpp @@ -19,8 +19,12 @@ #pragma once +#include #include +#include +#include "database/Object.hpp" +#include "database/Types.hpp" #include "database/objects/TrackId.hpp" #include "DatabaseCollectorBase.hpp" @@ -37,11 +41,10 @@ namespace lms::ui public: using DatabaseCollectorBase::DatabaseCollectorBase; - db::RangeResults get(std::optional range = std::nullopt); + void get(db::Range range, bool& moreResults, const std::function&)>& func); void reset() { _randomTracks.reset(); } private: - db::RangeResults getRandomTracks(Range range); - std::optional> _randomTracks; + std::optional> _randomTracks; }; } // namespace lms::ui diff --git a/src/lms/ui/explore/TrackListView.cpp b/src/lms/ui/explore/TrackListView.cpp index 6dc4717e..8b45b2ac 100644 --- a/src/lms/ui/explore/TrackListView.cpp +++ b/src/lms/ui/explore/TrackListView.cpp @@ -101,7 +101,7 @@ namespace lms::ui Wt::WContainerWidget* clusterContainers{ bindNew("clusters") }; { - const auto clusterTypeIds{ db::ClusterType::findIds(LmsApp->getDbSession()).results }; + const auto clusterTypeIds{ db::ClusterType::findIds(LmsApp->getDbSession()) }; const auto clusterGroups{ trackList->getClusterGroups(clusterTypeIds, 3) }; for (const auto& clusters : clusterGroups) @@ -194,11 +194,12 @@ namespace lms::ui params.setSortMethod(db::TrackSortMethod::TrackList); params.setRange(db::Range{ static_cast(_container->getCount()), _batchSize }); - bool moreResults{}; - db::Track::find(LmsApp->getDbSession(), params, moreResults, [this](const db::Track::pointer& track) { + std::size_t count{}; + db::Track::find(LmsApp->getDbSession(), params, [&](const db::Track::pointer& track) { _container->add(TrackListHelpers::createEntry(track, _playQueueController, _filters)); + ++count; }); - _container->setHasMore(moreResults); + _container->setHasMore(count == _batchSize); } } // namespace lms::ui diff --git a/src/lms/ui/explore/TrackListsView.cpp b/src/lms/ui/explore/TrackListsView.cpp index 7b2faca9..660282a3 100644 --- a/src/lms/ui/explore/TrackListsView.cpp +++ b/src/lms/ui/explore/TrackListsView.cpp @@ -145,13 +145,13 @@ namespace lms::ui } const auto trackListIds{ db::TrackList::find(session, params) }; - for (const db::TrackListId trackListId : trackListIds.results) + for (const db::TrackListId trackListId : trackListIds) { if (const db::TrackList::pointer trackList{ db::TrackList::find(LmsApp->getDbSession(), trackListId) }) addTracklist(trackList); } - _container->setHasMore(trackListIds.moreResults); + _container->setHasMore(trackListIds.size() == _batchSize); } void TrackLists::addTracklist(const db::ObjectPtr& trackList) diff --git a/src/lms/ui/explore/TracksView.cpp b/src/lms/ui/explore/TracksView.cpp index 9a59f84b..060fea65 100644 --- a/src/lms/ui/explore/TracksView.cpp +++ b/src/lms/ui/explore/TracksView.cpp @@ -115,22 +115,26 @@ namespace lms::ui void Tracks::addSome() { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - - const auto trackIds{ _trackCollector.get(db::Range{ static_cast(_container->getCount()), _batchSize }) }; - - for (const db::TrackId trackId : trackIds.results) + bool moreResults{}; { - if (const db::Track::pointer track{ db::Track::find(LmsApp->getDbSession(), trackId) }) + auto transaction{ LmsApp->getDbSession().createReadTransaction() }; + _trackCollector.get(db::Range{ static_cast(_container->getCount()), _batchSize }, moreResults, [&](const db::Track::pointer& track) { _container->add(TrackListHelpers::createEntry(track, _playQueueController, _filters)); + }); } - - _container->setHasMore(trackIds.moreResults); + _container->setHasMore(moreResults); } std::vector Tracks::getAllTracks() { - db::RangeResults trackIds{ _trackCollector.get() }; - return std::move(trackIds.results); + std::vector ids; + bool moreResults{}; + { + auto transaction{ LmsApp->getDbSession().createReadTransaction() }; + _trackCollector.get(db::Range{ 0, _maxCount }, moreResults, [&](const db::Track::pointer& track) { + ids.push_back(track->getId()); + }); + } + return ids; } } // namespace lms::ui diff --git a/src/lms/ui/explore/TracksView.hpp b/src/lms/ui/explore/TracksView.hpp index 2d7db3e9..1edeeb20 100644 --- a/src/lms/ui/explore/TracksView.hpp +++ b/src/lms/ui/explore/TracksView.hpp @@ -42,8 +42,8 @@ namespace lms::ui std::vector getAllTracks(); static constexpr TrackCollector::Mode _defaultMode{ TrackCollector::Mode::Random }; - static constexpr std::size_t _batchSize{ 6 }; - static constexpr std::size_t _maxCount{ 8000 }; + static constexpr std::size_t _batchSize{ 10 }; + static constexpr std::size_t _maxCount{ 5'000 }; Filters& _filters; PlayQueueController& _playQueueController; diff --git a/src/lms/ui/resource/DownloadResource.cpp b/src/lms/ui/resource/DownloadResource.cpp index 6ac94f9c..849e6a7c 100644 --- a/src/lms/ui/resource/DownloadResource.cpp +++ b/src/lms/ui/resource/DownloadResource.cpp @@ -182,7 +182,7 @@ namespace lms::ui auto transaction{ LmsApp->getDbSession().createReadTransaction() }; const auto trackResults{ db::Track::find(LmsApp->getDbSession(), db::Track::FindParameters{}.setArtist(_artistId).setSortMethod(db::TrackSortMethod::DateDescAndRelease)) }; - return detail::createZipper(trackResults.results); + return detail::createZipper(trackResults); } DownloadReleaseResource::DownloadReleaseResource(db::ReleaseId releaseId) @@ -200,7 +200,7 @@ namespace lms::ui auto transaction{ LmsApp->getDbSession().createReadTransaction() }; auto tracks{ db::Track::find(LmsApp->getDbSession(), db::Track::FindParameters{}.setRelease(_releaseId).setSortMethod(db::TrackSortMethod::Release)) }; - return detail::createZipper(tracks.results); + return detail::createZipper(tracks); } DownloadTrackResource::DownloadTrackResource(db::TrackId trackId) @@ -244,7 +244,7 @@ namespace lms::ui db::Track::FindParameters params; params.setTrackList(_trackListId); const auto tracks{ db::Track::find(LmsApp->getDbSession(), params) }; - return detail::createZipper(tracks.results); + return detail::createZipper(tracks); } } // namespace lms::ui diff --git a/src/tools/recommendation/LmsRecommendation.cpp b/src/tools/recommendation/LmsRecommendation.cpp index 825d8d34..0761e08f 100644 --- a/src/tools/recommendation/LmsRecommendation.cpp +++ b/src/tools/recommendation/LmsRecommendation.cpp @@ -60,7 +60,7 @@ namespace lms params.setKeywords(core::stringUtils::splitString(name, ' ')); auto transaction{ session.createReadTransaction() }; - trackIds = db::Track::findIds(session, params).results; + trackIds = db::Track::findIds(session, params); } std::cout << "*** Tracks (" << trackIds.size() << ") ***" << std::endl; @@ -106,7 +106,7 @@ namespace lms params.setKeywords(core::stringUtils::splitString(name, ' ')); auto transaction{ session.createReadTransaction() }; - releaseIds = db::Release::findIds(session, params).results; + releaseIds = db::Release::findIds(session, params); } std::cout << "*** Releases ***" << std::endl; @@ -148,7 +148,7 @@ namespace lms params.setKeywords(core::stringUtils::splitString(name, ' ')); auto transaction{ session.createReadTransaction() }; - artistIds = db::Artist::findIds(session, params).results; + artistIds = db::Artist::findIds(session, params); } std::cout << "*** Artists ***" << std::endl; @@ -246,7 +246,7 @@ namespace lms std::vector releaseIds; { auto transaction{ session.createReadTransaction() }; - releaseIds = db::Release::findIds(session, db::Release::FindParameters{}).results; + releaseIds = db::Release::findIds(session, db::Release::FindParameters{}); } if (releaseIds.empty()) @@ -307,7 +307,7 @@ namespace lms std::vector artistIds; { auto transaction{ session.createReadTransaction() }; - artistIds = db::Artist::findIds(session, db::Artist::FindParameters{}).results; + artistIds = db::Artist::findIds(session, db::Artist::FindParameters{}); } if (artistIds.empty()) @@ -372,7 +372,7 @@ namespace lms params.setKeywords(core::stringUtils::splitString(fromName, ' ')); auto transaction{ session.createReadTransaction() }; - fromTrackIds = db::Track::findIds(session, params).results; + fromTrackIds = db::Track::findIds(session, params); } // Find 'to' tracks @@ -388,7 +388,7 @@ namespace lms params.setKeywords(core::stringUtils::splitString(toName, ' ')); auto transaction{ session.createReadTransaction() }; - toTrackIds = db::Track::findIds(session, params).results; + toTrackIds = db::Track::findIds(session, params); } if (fromTrackIds.empty() || toTrackIds.empty()) From 1c52972c12c2602183be682727a5b0ae79a4d2a8 Mon Sep 17 00:00:00 2001 From: emeric Date: Sat, 11 Jul 2026 21:50:45 +0200 Subject: [PATCH 03/22] Added support for work/movements, fixes #834 --- approot/release.xml | 49 +- src/libs/audio/impl/ffmpeg/TagReader.cpp | 6 +- src/libs/audio/impl/taglib/TagReader.cpp | 6 +- src/libs/core/impl/String.cpp | 38 ++ src/libs/core/include/core/String.hpp | 3 + src/libs/core/test/String.cpp | 30 ++ src/libs/database/CMakeLists.txt | 2 + src/libs/database/impl/Migration.cpp | 37 +- src/libs/database/impl/Session.cpp | 8 + src/libs/database/impl/objects/Cluster.cpp | 2 + src/libs/database/impl/objects/Genre.cpp | 2 + src/libs/database/impl/objects/Grouping.cpp | 2 + src/libs/database/impl/objects/Language.cpp | 2 + src/libs/database/impl/objects/Medium.cpp | 2 + src/libs/database/impl/objects/Mood.cpp | 2 + src/libs/database/impl/objects/Movement.cpp | 64 +++ src/libs/database/impl/objects/PlayQueue.cpp | 2 + src/libs/database/impl/objects/Release.cpp | 2 + src/libs/database/impl/objects/Track.cpp | 36 ++ .../impl/objects/TrackEmbeddedImage.cpp | 2 + src/libs/database/impl/objects/TrackList.cpp | 2 + src/libs/database/impl/objects/Work.cpp | 112 ++++ .../include/database/objects/Movement.hpp | 69 +++ .../include/database/objects/MovementId.hpp | 24 + .../include/database/objects/Track.hpp | 19 +- .../include/database/objects/Work.hpp | 82 +++ .../include/database/objects/WorkId.hpp | 24 + src/libs/database/test/CMakeLists.txt | 2 + src/libs/database/test/Movement.cpp | 172 ++++++ src/libs/database/test/Work.cpp | 213 ++++++++ .../audiofile/AudioFileScanOperation.cpp | 26 + .../audiofile/TrackMetadataParser.cpp | 34 ++ .../steps/ScanStepRemoveOrphanedDbEntries.cpp | 8 + .../steps/ScanStepRemoveOrphanedDbEntries.hpp | 1 + .../scanner/impl/types/TrackMetadata.hpp | 17 + .../services/scanner/test/TestTagReader.hpp | 5 + .../scanner/test/TrackMetadataParser.cpp | 72 +++ .../impl/listenbrainz/ListensSynchronizer.cpp | 2 +- src/libs/subsonic/impl/responses/Song.cpp | 24 + src/lms/ui/MediaPlayer.cpp | 5 +- src/lms/ui/PlayQueue.cpp | 22 +- src/lms/ui/PlayQueue.hpp | 13 +- src/lms/ui/Utils.cpp | 23 + src/lms/ui/Utils.hpp | 3 + src/lms/ui/explore/ArtistView.cpp | 12 +- src/lms/ui/explore/PlayQueueController.cpp | 56 +- src/lms/ui/explore/PlayQueueController.hpp | 14 +- src/lms/ui/explore/ReleaseView.cpp | 501 ++++++++++++------ src/lms/ui/explore/ReleaseView.hpp | 53 +- src/lms/ui/explore/TrackListHelpers.cpp | 19 +- 50 files changed, 1630 insertions(+), 296 deletions(-) create mode 100644 src/libs/database/impl/objects/Movement.cpp create mode 100644 src/libs/database/impl/objects/Work.cpp create mode 100644 src/libs/database/include/database/objects/Movement.hpp create mode 100644 src/libs/database/include/database/objects/MovementId.hpp create mode 100644 src/libs/database/include/database/objects/Work.hpp create mode 100644 src/libs/database/include/database/objects/WorkId.hpp create mode 100644 src/libs/database/test/Movement.cpp create mode 100644 src/libs/database/test/Work.cpp diff --git a/approot/release.xml b/approot/release.xml index a542b941..fdcf8568 100644 --- a/approot/release.xml +++ b/approot/release.xml @@ -55,36 +55,43 @@ ${artist class="text-decoration-none link-success"} - -

- ${} -
${artwork class="Lms-cursor-pointer"}
- ${
} -
${disc-title}
-
- ${play-btn class="d-none d-sm-block btn btn-sm btn-outline-secondary border-0"} - + + ${} +
${artwork class="Lms-cursor-pointer"}
+ ${
} +
${title}
+
+ ${play-btn class="d-none d-sm-block btn btn-sm btn-outline-secondary border-0"} + -

+ +
+ + +

${header class="d-flex align-items-center"}

+ ${tracks class="d-grid gap-1"} +
+ + +
${header class="d-flex align-items-center"}
${tracks class="d-grid gap-1 Lms-row-container"}
- + ${tracks class="d-grid gap-1 Lms-row-container"} - +
- ${}${track-number}${} + ${}${position}${}
diff --git a/src/libs/audio/impl/ffmpeg/TagReader.cpp b/src/libs/audio/impl/ffmpeg/TagReader.cpp index dcf648aa..97095f7e 100644 --- a/src/libs/audio/impl/ffmpeg/TagReader.cpp +++ b/src/libs/audio/impl/ffmpeg/TagReader.cpp @@ -83,9 +83,9 @@ namespace lms::audio::ffmpeg { TagType::Mixers, { "MIXERS" } }, { TagType::MixersSortOrder, { "MIXERSSORT" } }, { TagType::Mood, { "MOOD" } }, - { TagType::Movement, { "MOVEMENT", "MOVEMENTNAME" } }, - { TagType::MovementCount, { "MOVEMENTCOUNT" } }, - { TagType::MovementNumber, { "MOVEMENTNUMBER" } }, + { TagType::Movement, { "MOVEMENTNAME" } }, + { TagType::MovementCount, { "MOVEMENTCOUNT", "MOVEMENTTOTAL" } }, + { TagType::MovementNumber, { "MOVEMENTNUMBER", "MOVEMENT" } }, { TagType::MusicBrainzArtistID, { "MUSICBRAINZ_ARTISTID", "MUSICBRAINZ ARTIST ID", "MUSICBRAINZ/ARTIST ID" } }, { TagType::MusicBrainzArrangerID, { "MUSICBRAINZ_ARRANGERID", "MUSICBRAINZ ARRANGER ID", "MUSICBRAINZ/ARRANGER ID" } }, { TagType::MusicBrainzComposerID, { "MUSICBRAINZ_COMPOSERID", "MUSICBRAINZ COMPOSER ID", "MUSICBRAINZ/COMPOSER ID" } }, diff --git a/src/libs/audio/impl/taglib/TagReader.cpp b/src/libs/audio/impl/taglib/TagReader.cpp index a905f7b5..cd3f594b 100644 --- a/src/libs/audio/impl/taglib/TagReader.cpp +++ b/src/libs/audio/impl/taglib/TagReader.cpp @@ -113,9 +113,9 @@ namespace lms::audio::taglib { TagType::Mixers, { "MIXERS" } }, { TagType::MixersSortOrder, { "MIXERSSORT" } }, { TagType::Mood, { "MOOD" } }, - { TagType::Movement, { "MOVEMENT", "MOVEMENTNAME" } }, - { TagType::MovementCount, { "MOVEMENTCOUNT" } }, - { TagType::MovementNumber, { "MOVEMENTNUMBER" } }, + { TagType::Movement, { "MOVEMENTNAME" } }, + { TagType::MovementCount, { "MOVEMENTCOUNT", "MOVEMENTTOTAL" } }, + { TagType::MovementNumber, { "MOVEMENTNUMBER", "MOVEMENT" } }, { TagType::MusicBrainzArtistID, { "MUSICBRAINZ_ARTISTID", "MUSICBRAINZ ARTIST ID", "MUSICBRAINZ/ARTIST ID" } }, { TagType::MusicBrainzArrangerID, { "MUSICBRAINZ_ARRANGERID", "MUSICBRAINZ ARRANGER ID", "MUSICBRAINZ/ARRANGER ID" } }, { TagType::MusicBrainzComposerID, { "MUSICBRAINZ_COMPOSERID", "MUSICBRAINZ COMPOSER ID", "MUSICBRAINZ/COMPOSER ID" } }, diff --git a/src/libs/core/impl/String.cpp b/src/libs/core/impl/String.cpp index 8fec0efb..04edadb5 100644 --- a/src/libs/core/impl/String.cpp +++ b/src/libs/core/impl/String.cpp @@ -418,6 +418,44 @@ namespace lms::core::stringUtils } } + std::string toRomanNumeral(std::size_t n) + { + if (n == 0 || n > 3999) + return {}; + + static constexpr struct + { + std::size_t val; + const char* sym; + } table[]{ + { 1000, "m" }, + { 900, "cm" }, + { 500, "d" }, + { 400, "cd" }, + { 100, "c" }, + { 90, "xc" }, + { 50, "l" }, + { 40, "xl" }, + { 10, "x" }, + { 9, "ix" }, + { 5, "v" }, + { 4, "iv" }, + { 1, "i" } + }; + + std::string res; + for (const auto& [val, sym] : table) + { + while (n >= val) + { + res += sym; + n -= val; + } + } + + return res; + } + std::string replaceInString(std::string_view str, std::string_view from, std::string_view to) { std::string res{ str }; diff --git a/src/libs/core/include/core/String.hpp b/src/libs/core/include/core/String.hpp index 2dd2652c..8ac81d8a 100644 --- a/src/libs/core/include/core/String.hpp +++ b/src/libs/core/include/core/String.hpp @@ -65,6 +65,9 @@ namespace lms::core::stringUtils void capitalize(std::string& str); + // returns empty string if invalid input + [[nodiscard]] std::string toRomanNumeral(std::size_t n); + template [[nodiscard]] std::optional readAs(std::string_view str) { diff --git a/src/libs/core/test/String.cpp b/src/libs/core/test/String.cpp index 29b1d259..bbc7ee58 100644 --- a/src/libs/core/test/String.cpp +++ b/src/libs/core/test/String.cpp @@ -17,6 +17,8 @@ * along with LMS. If not, see . */ +#include + #include #include @@ -412,4 +414,32 @@ namespace lms::core::stringUtils::tests EXPECT_EQ(stringFromHex("3132333435"), "12345"); EXPECT_EQ(stringFromHex("54657374"), "Test"); } + + TEST(StringUtils, toRomanNumeral) + { + EXPECT_EQ(toRomanNumeral(1), "i"); + EXPECT_EQ(toRomanNumeral(2), "ii"); + EXPECT_EQ(toRomanNumeral(3), "iii"); + EXPECT_EQ(toRomanNumeral(4), "iv"); + EXPECT_EQ(toRomanNumeral(5), "v"); + EXPECT_EQ(toRomanNumeral(6), "vi"); + EXPECT_EQ(toRomanNumeral(7), "vii"); + EXPECT_EQ(toRomanNumeral(8), "viii"); + EXPECT_EQ(toRomanNumeral(9), "ix"); + EXPECT_EQ(toRomanNumeral(10), "x"); + EXPECT_EQ(toRomanNumeral(11), "xi"); + EXPECT_EQ(toRomanNumeral(14), "xiv"); + EXPECT_EQ(toRomanNumeral(16), "xvi"); + EXPECT_EQ(toRomanNumeral(40), "xl"); + EXPECT_EQ(toRomanNumeral(50), "l"); + EXPECT_EQ(toRomanNumeral(90), "xc"); + EXPECT_EQ(toRomanNumeral(99), "xcix"); + EXPECT_EQ(toRomanNumeral(444), "cdxliv"); + EXPECT_EQ(toRomanNumeral(1994), "mcmxciv"); + EXPECT_EQ(toRomanNumeral(3999), "mmmcmxcix"); + EXPECT_EQ(toRomanNumeral(0), ""); + EXPECT_EQ(toRomanNumeral(4000), ""); + EXPECT_EQ(toRomanNumeral(static_cast(-1)), ""); // underflows to SIZE_MAX + EXPECT_EQ(toRomanNumeral(std::numeric_limits::max()), ""); + } } // namespace lms::core::stringUtils::tests \ No newline at end of file diff --git a/src/libs/database/CMakeLists.txt b/src/libs/database/CMakeLists.txt index bc164a03..ca023ffb 100644 --- a/src/libs/database/CMakeLists.txt +++ b/src/libs/database/CMakeLists.txt @@ -27,8 +27,10 @@ add_library(lmsdatabase STATIC impl/objects/StarredArtist.cpp impl/objects/StarredRelease.cpp impl/objects/StarredTrack.cpp + impl/objects/Movement.cpp impl/objects/Track.cpp impl/objects/TrackArtistLink.cpp + impl/objects/Work.cpp impl/objects/TrackBookmark.cpp impl/objects/TrackEmbeddedImage.cpp impl/objects/TrackEmbeddedImageLink.cpp diff --git a/src/libs/database/impl/Migration.cpp b/src/libs/database/impl/Migration.cpp index dc65b75d..2611dac0 100644 --- a/src/libs/database/impl/Migration.cpp +++ b/src/libs/database/impl/Migration.cpp @@ -36,7 +36,7 @@ namespace lms::db { namespace { - static constexpr Version LMS_DATABASE_VERSION{ 108 }; + static constexpr Version LMS_DATABASE_VERSION{ 109 }; } VersionInfo::VersionInfo() @@ -1922,6 +1922,40 @@ WHERE ct.name = 'GROUPING')"); utils::executeCommand(*session.getDboSession(), R"(DELETE FROM cluster_type WHERE name IN ('GENRE', 'MOOD', 'LANGUAGE', 'GROUPING'))"); } + void migrateFromV108(Session& session) + { + utils::executeCommand(*session.getDboSession(), R"( +CREATE TABLE IF NOT EXISTS "work" ( + "id" integer primary key autoincrement, + "version" integer not null, + "name" text not null, + "mbid" blob +))"); + utils::executeCommand(*session.getDboSession(), R"( +CREATE TABLE IF NOT EXISTS "track_work" ( + "work_id" bigint, + "track_id" bigint, + primary key ("work_id", "track_id"), + constraint "fk_track_work_key1" foreign key ("work_id") references "work" ("id") on delete cascade deferrable initially deferred, + constraint "fk_track_work_key2" foreign key ("track_id") references "track" ("id") on delete cascade deferrable initially deferred +))"); + utils::executeCommand(*session.getDboSession(), R"(CREATE INDEX "track_work_work" on "track_work" ("work_id"))"); + utils::executeCommand(*session.getDboSession(), R"(CREATE INDEX "track_work_track" on "track_work" ("track_id"))"); + utils::executeCommand(*session.getDboSession(), R"( +CREATE TABLE IF NOT EXISTS "track_movement" ( + "id" integer primary key autoincrement, + "version" integer not null, + "name" text not null, + "number" integer, + "count" integer, + "track_id" bigint, + constraint "fk_track_movement_track" foreign key ("track_id") references "track" ("id") on delete cascade deferrable initially deferred +))"); + + // Just increment the scan version of the settings to make the next scan rescan all audio files + utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET audio_scan_version = audio_scan_version + 1"); + } + bool doDbMigration(Session& session) { constexpr std::string_view outdatedMsg{ "Outdated database, please rebuild it (delete the .db file and restart)" }; @@ -2006,6 +2040,7 @@ WHERE ct.name = 'GROUPING')"); { 105, migrateFromV105 }, { 106, migrateFromV106 }, { 107, migrateFromV107 }, + { 108, migrateFromV108 }, }; LMS_SCOPED_TRACE_OVERVIEW("Database", "Migration"); diff --git a/src/libs/database/impl/Session.cpp b/src/libs/database/impl/Session.cpp index 01c49b2b..a5d7530c 100644 --- a/src/libs/database/impl/Session.cpp +++ b/src/libs/database/impl/Session.cpp @@ -38,6 +38,7 @@ #include "database/objects/MediaLibrary.hpp" #include "database/objects/Medium.hpp" #include "database/objects/Mood.hpp" +#include "database/objects/Movement.hpp" #include "database/objects/PlayListFile.hpp" #include "database/objects/PlayQueue.hpp" #include "database/objects/Podcast.hpp" @@ -61,6 +62,7 @@ #include "database/objects/TrackMusicNNEmbeddings.hpp" #include "database/objects/UIState.hpp" #include "database/objects/User.hpp" +#include "database/objects/Work.hpp" #include "Db.hpp" #include "Migration.hpp" @@ -111,6 +113,7 @@ namespace lms::db _session.mapClass("starred_release"); _session.mapClass("starred_track"); _session.mapClass("track"); + _session.mapClass("track_movement"); _session.mapClass("track_bookmark"); _session.mapClass("track_artist_link"); _session.mapClass("track_embedded_image"); @@ -120,6 +123,7 @@ namespace lms::db _session.mapClass("tracklist_entry"); _session.mapClass("track_lyrics"); _session.mapClass("ui_state"); + _session.mapClass("work"); _session.mapClass("user"); _session.mapClass("version_info"); } @@ -322,6 +326,10 @@ namespace lms::db "CREATE INDEX IF NOT EXISTS track_lyrics_directory_idx ON track_lyrics(directory_id)", "CREATE INDEX IF NOT EXISTS track_lyrics_track_idx ON track_lyrics(track_id)", + "CREATE INDEX IF NOT EXISTS track_movement_track_idx ON track_movement(track_id)", + + "CREATE INDEX IF NOT EXISTS work_mbid_idx ON work(mbid)", + "CREATE INDEX IF NOT EXISTS track_bookmark_user_idx ON track_bookmark(user_id)", "CREATE INDEX IF NOT EXISTS track_bookmark_user_track_idx ON track_bookmark(user_id,track_id)", diff --git a/src/libs/database/impl/objects/Cluster.cpp b/src/libs/database/impl/objects/Cluster.cpp index 2d57d9a4..996c8bf8 100644 --- a/src/libs/database/impl/objects/Cluster.cpp +++ b/src/libs/database/impl/objects/Cluster.cpp @@ -31,12 +31,14 @@ #include "database/objects/MediaLibrary.hpp" #include "database/objects/Medium.hpp" #include "database/objects/Mood.hpp" +#include "database/objects/Movement.hpp" #include "database/objects/Release.hpp" #include "database/objects/Track.hpp" #include "database/objects/TrackArtistLink.hpp" #include "database/objects/TrackEmbeddedImage.hpp" #include "database/objects/TrackEmbeddedImageLink.hpp" #include "database/objects/TrackLyrics.hpp" +#include "database/objects/Work.hpp" #include "Utils.hpp" #include "traits/IdTypeTraits.hpp" diff --git a/src/libs/database/impl/objects/Genre.cpp b/src/libs/database/impl/objects/Genre.cpp index 8f546257..aa74a78c 100644 --- a/src/libs/database/impl/objects/Genre.cpp +++ b/src/libs/database/impl/objects/Genre.cpp @@ -33,12 +33,14 @@ #include "database/objects/MediaLibrary.hpp" #include "database/objects/Medium.hpp" #include "database/objects/Mood.hpp" +#include "database/objects/Movement.hpp" #include "database/objects/Release.hpp" #include "database/objects/Track.hpp" #include "database/objects/TrackArtistLink.hpp" #include "database/objects/TrackEmbeddedImage.hpp" #include "database/objects/TrackEmbeddedImageLink.hpp" #include "database/objects/TrackLyrics.hpp" +#include "database/objects/Work.hpp" #include "Utils.hpp" #include "traits/IdTypeTraits.hpp" diff --git a/src/libs/database/impl/objects/Grouping.cpp b/src/libs/database/impl/objects/Grouping.cpp index 80590c5f..22612765 100644 --- a/src/libs/database/impl/objects/Grouping.cpp +++ b/src/libs/database/impl/objects/Grouping.cpp @@ -33,12 +33,14 @@ #include "database/objects/MediaLibrary.hpp" #include "database/objects/Medium.hpp" #include "database/objects/Mood.hpp" +#include "database/objects/Movement.hpp" #include "database/objects/Release.hpp" #include "database/objects/Track.hpp" #include "database/objects/TrackArtistLink.hpp" #include "database/objects/TrackEmbeddedImage.hpp" #include "database/objects/TrackEmbeddedImageLink.hpp" #include "database/objects/TrackLyrics.hpp" +#include "database/objects/Work.hpp" #include "Utils.hpp" #include "traits/IdTypeTraits.hpp" diff --git a/src/libs/database/impl/objects/Language.cpp b/src/libs/database/impl/objects/Language.cpp index 00230538..6a5c4ad9 100644 --- a/src/libs/database/impl/objects/Language.cpp +++ b/src/libs/database/impl/objects/Language.cpp @@ -33,12 +33,14 @@ #include "database/objects/MediaLibrary.hpp" #include "database/objects/Medium.hpp" #include "database/objects/Mood.hpp" +#include "database/objects/Movement.hpp" #include "database/objects/Release.hpp" #include "database/objects/Track.hpp" #include "database/objects/TrackArtistLink.hpp" #include "database/objects/TrackEmbeddedImage.hpp" #include "database/objects/TrackEmbeddedImageLink.hpp" #include "database/objects/TrackLyrics.hpp" +#include "database/objects/Work.hpp" #include "Utils.hpp" #include "traits/IdTypeTraits.hpp" diff --git a/src/libs/database/impl/objects/Medium.cpp b/src/libs/database/impl/objects/Medium.cpp index 4c2cd5ac..d50970e7 100644 --- a/src/libs/database/impl/objects/Medium.cpp +++ b/src/libs/database/impl/objects/Medium.cpp @@ -31,12 +31,14 @@ #include "database/objects/Language.hpp" #include "database/objects/MediaLibrary.hpp" #include "database/objects/Mood.hpp" +#include "database/objects/Movement.hpp" #include "database/objects/Release.hpp" #include "database/objects/Track.hpp" #include "database/objects/TrackArtistLink.hpp" #include "database/objects/TrackEmbeddedImage.hpp" #include "database/objects/TrackEmbeddedImageLink.hpp" #include "database/objects/TrackLyrics.hpp" +#include "database/objects/Work.hpp" #include "Utils.hpp" #include "traits/IdTypeTraits.hpp" diff --git a/src/libs/database/impl/objects/Mood.cpp b/src/libs/database/impl/objects/Mood.cpp index c2e5d478..cfd9bd37 100644 --- a/src/libs/database/impl/objects/Mood.cpp +++ b/src/libs/database/impl/objects/Mood.cpp @@ -33,12 +33,14 @@ #include "database/objects/Language.hpp" #include "database/objects/MediaLibrary.hpp" #include "database/objects/Medium.hpp" +#include "database/objects/Movement.hpp" #include "database/objects/Release.hpp" #include "database/objects/Track.hpp" #include "database/objects/TrackArtistLink.hpp" #include "database/objects/TrackEmbeddedImage.hpp" #include "database/objects/TrackEmbeddedImageLink.hpp" #include "database/objects/TrackLyrics.hpp" +#include "database/objects/Work.hpp" #include "Utils.hpp" #include "traits/IdTypeTraits.hpp" diff --git a/src/libs/database/impl/objects/Movement.cpp b/src/libs/database/impl/objects/Movement.cpp new file mode 100644 index 00000000..ab96550e --- /dev/null +++ b/src/libs/database/impl/objects/Movement.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2025 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#include "database/objects/Movement.hpp" + +#include + +#include "core/ILogger.hpp" + +#include "database/Session.hpp" +#include "database/objects/Artist.hpp" +#include "database/objects/Artwork.hpp" +#include "database/objects/Cluster.hpp" +#include "database/objects/Directory.hpp" +#include "database/objects/Genre.hpp" +#include "database/objects/Grouping.hpp" +#include "database/objects/Language.hpp" +#include "database/objects/MediaLibrary.hpp" +#include "database/objects/Medium.hpp" +#include "database/objects/Mood.hpp" +#include "database/objects/Release.hpp" +#include "database/objects/Track.hpp" +#include "database/objects/TrackArtistLink.hpp" +#include "database/objects/TrackEmbeddedImage.hpp" +#include "database/objects/TrackEmbeddedImageLink.hpp" +#include "database/objects/TrackLyrics.hpp" + +#include "traits/IdTypeTraits.hpp" + +DBO_INSTANTIATE_TEMPLATES(lms::db::Movement) + +namespace lms::db +{ + Movement::Movement(std::string_view name, std::optional number, std::optional count, const ObjectPtr& track) + : _name{ name.substr(0, maxNameLength) } + , _number{ number } + , _count{ count } + , _track{ getDboPtr(track) } + { + LMS_LOG_IF(DB, WARNING, name.size() > maxNameLength, "Movement name too long, truncated to '" << _name << "'"); + } + + Movement::pointer Movement::create(Session& session, std::string_view name, std::optional number, std::optional count, const ObjectPtr& track) + { + return session.getDboSession()->add(std::unique_ptr{ new Movement{ name, number, count, track } }); + } + +} // namespace lms::db diff --git a/src/libs/database/impl/objects/PlayQueue.cpp b/src/libs/database/impl/objects/PlayQueue.cpp index ffa824ab..25145a85 100644 --- a/src/libs/database/impl/objects/PlayQueue.cpp +++ b/src/libs/database/impl/objects/PlayQueue.cpp @@ -33,6 +33,7 @@ #include "database/objects/MediaLibrary.hpp" #include "database/objects/Medium.hpp" #include "database/objects/Mood.hpp" +#include "database/objects/Movement.hpp" #include "database/objects/Release.hpp" #include "database/objects/Track.hpp" #include "database/objects/TrackArtistLink.hpp" @@ -40,6 +41,7 @@ #include "database/objects/TrackEmbeddedImageLink.hpp" #include "database/objects/TrackLyrics.hpp" #include "database/objects/User.hpp" +#include "database/objects/Work.hpp" #include "Utils.hpp" #include "traits/IdTypeTraits.hpp" diff --git a/src/libs/database/impl/objects/Release.cpp b/src/libs/database/impl/objects/Release.cpp index 62202405..9b7be1b9 100644 --- a/src/libs/database/impl/objects/Release.cpp +++ b/src/libs/database/impl/objects/Release.cpp @@ -35,6 +35,7 @@ #include "database/objects/MediaLibrary.hpp" #include "database/objects/Medium.hpp" #include "database/objects/Mood.hpp" +#include "database/objects/Movement.hpp" #include "database/objects/ReleaseArtistLink.hpp" #include "database/objects/Track.hpp" #include "database/objects/TrackArtistLink.hpp" @@ -42,6 +43,7 @@ #include "database/objects/TrackEmbeddedImageLink.hpp" #include "database/objects/TrackLyrics.hpp" #include "database/objects/User.hpp" +#include "database/objects/Work.hpp" #include "SqlQuery.hpp" #include "Utils.hpp" diff --git a/src/libs/database/impl/objects/Track.cpp b/src/libs/database/impl/objects/Track.cpp index 1b01fd72..a3d23394 100644 --- a/src/libs/database/impl/objects/Track.cpp +++ b/src/libs/database/impl/objects/Track.cpp @@ -36,12 +36,14 @@ #include "database/objects/MediaLibrary.hpp" #include "database/objects/Medium.hpp" #include "database/objects/Mood.hpp" +#include "database/objects/Movement.hpp" #include "database/objects/Release.hpp" #include "database/objects/TrackArtistLink.hpp" #include "database/objects/TrackEmbeddedImage.hpp" #include "database/objects/TrackEmbeddedImageLink.hpp" #include "database/objects/TrackLyrics.hpp" #include "database/objects/User.hpp" +#include "database/objects/Work.hpp" #include "SqlQuery.hpp" #include "Utils.hpp" @@ -673,6 +675,40 @@ namespace lms::db _moods.insert(getDboPtr(mood)); } + void Track::setWorks(std::span> works) + { + _works.clear(); + for (const ObjectPtr& work : works) + _works.insert(getDboPtr(work)); + } + + std::vector Track::getWorks() const + { + // deterministic order, callers rely on the first entry + return utils::fetchQueryResults(_works.find().orderBy("id")); + } + + bool Track::hasWork() const + { + return !_works.empty(); + } + + void Track::clearMovements() + { + _movements.clear(); + } + + std::vector Track::getMovements() const + { + // deterministic order, callers rely on the first entry + return utils::fetchQueryResults(_movements.find().orderBy("id")); + } + + bool Track::hasMovement() const + { + return !_movements.empty(); + } + void Track::clearLyrics() { _trackLyrics.clear(); diff --git a/src/libs/database/impl/objects/TrackEmbeddedImage.cpp b/src/libs/database/impl/objects/TrackEmbeddedImage.cpp index c800afdc..cb971bd6 100644 --- a/src/libs/database/impl/objects/TrackEmbeddedImage.cpp +++ b/src/libs/database/impl/objects/TrackEmbeddedImage.cpp @@ -27,7 +27,9 @@ #include "database/objects/Grouping.hpp" #include "database/objects/Language.hpp" #include "database/objects/Mood.hpp" +#include "database/objects/Movement.hpp" #include "database/objects/Track.hpp" +#include "database/objects/Work.hpp" #include "database/objects/TrackEmbeddedImageLink.hpp" diff --git a/src/libs/database/impl/objects/TrackList.cpp b/src/libs/database/impl/objects/TrackList.cpp index 486aa5b9..018fd1e2 100644 --- a/src/libs/database/impl/objects/TrackList.cpp +++ b/src/libs/database/impl/objects/TrackList.cpp @@ -29,9 +29,11 @@ #include "database/objects/Grouping.hpp" #include "database/objects/Language.hpp" #include "database/objects/Mood.hpp" +#include "database/objects/Movement.hpp" #include "database/objects/PlayListFile.hpp" #include "database/objects/Track.hpp" #include "database/objects/User.hpp" +#include "database/objects/Work.hpp" #include "SqlQuery.hpp" #include "Utils.hpp" diff --git a/src/libs/database/impl/objects/Work.cpp b/src/libs/database/impl/objects/Work.cpp new file mode 100644 index 00000000..e032c890 --- /dev/null +++ b/src/libs/database/impl/objects/Work.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2025 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#include "database/objects/Work.hpp" + +#include + +#include "core/ILogger.hpp" + +#include "database/Session.hpp" +#include "database/objects/Artist.hpp" +#include "database/objects/Artwork.hpp" +#include "database/objects/Cluster.hpp" +#include "database/objects/Directory.hpp" +#include "database/objects/Genre.hpp" +#include "database/objects/Grouping.hpp" +#include "database/objects/Language.hpp" +#include "database/objects/MediaLibrary.hpp" +#include "database/objects/Medium.hpp" +#include "database/objects/Mood.hpp" +#include "database/objects/Movement.hpp" +#include "database/objects/Release.hpp" +#include "database/objects/Track.hpp" +#include "database/objects/TrackArtistLink.hpp" +#include "database/objects/TrackEmbeddedImage.hpp" +#include "database/objects/TrackEmbeddedImageLink.hpp" +#include "database/objects/TrackLyrics.hpp" + +#include "Utils.hpp" +#include "traits/IdTypeTraits.hpp" +#include "traits/UUIDTraits.hpp" + +DBO_INSTANTIATE_TEMPLATES(lms::db::Work) + +namespace lms::db +{ + Work::Work(std::string_view name, const std::optional& mbid) + : _mbid{ mbid } + { + setName(name); + } + + void Work::setName(std::string_view name) + { + _name = name.substr(0, maxNameLength); + LMS_LOG_IF(DB, WARNING, name.size() > maxNameLength, "Work name too long, truncated to '" << _name << "'"); + } + + Work::pointer Work::create(Session& session, std::string_view name, const std::optional& mbid) + { + return session.getDboSession()->add(std::unique_ptr{ new Work{ name, mbid } }); + } + + Work::pointer Work::find(Session& session, WorkId id) + { + session.checkReadTransaction(); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("id = ?").bind(id)); + } + + Work::pointer Work::find(Session& session, const core::UUID& mbid) + { + session.checkReadTransaction(); + + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("mbid = ?").bind(mbid)); + } + + Work::pointer Work::find(Session& session, ReleaseId releaseId, std::string_view name) + { + session.checkReadTransaction(); + + if (name.size() > maxNameLength) + name = name.substr(0, maxNameLength); + + auto query{ + session.getDboSession()->query>("SELECT w FROM work w") + // clang-format off + .join("track_work t_w ON t_w.work_id = w.id") + .join("track t ON t.id = t_w.track_id") + .where("t.release_id = ?").bind(releaseId) + .where("w.name = ?").bind(std::string{ name }) + .where("w.mbid IS NULL") + .groupBy("w.id") + // clang-format on + }; + + return utils::fetchQuerySingleResult(query); + } + + std::vector Work::findOrphanIds(Session& session, std::optional range) + { + session.checkReadTransaction(); + auto query{ session.getDboSession()->query("SELECT w.id FROM work w WHERE NOT EXISTS (SELECT 1 FROM track_work t_w WHERE t_w.work_id = w.id)") }; + return utils::execRangeQuery(query, range); + } + +} // namespace lms::db diff --git a/src/libs/database/include/database/objects/Movement.hpp b/src/libs/database/include/database/objects/Movement.hpp new file mode 100644 index 00000000..fb33a9ba --- /dev/null +++ b/src/libs/database/include/database/objects/Movement.hpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2025 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#pragma once + +#include +#include +#include + +#include + +#include "database/Object.hpp" +#include "database/objects/MovementId.hpp" +#include "database/objects/TrackId.hpp" + +namespace lms::db +{ + class Session; + class Track; + + class Movement final : public Object + { + public: + static constexpr std::size_t maxNameLength{ 512 }; + + Movement() = default; + + static pointer create(Session& session, std::string_view name, std::optional number, std::optional count, const ObjectPtr& track); + + std::string_view getName() const { return _name; } + std::optional getNumber() const { return _number; } + std::optional getCount() const { return _count; } + + template + void persist(Action& a) + { + Wt::Dbo::field(a, _name, "name"); + Wt::Dbo::field(a, _number, "number"); + Wt::Dbo::field(a, _count, "count"); + Wt::Dbo::belongsTo(a, _track, "track", Wt::Dbo::OnDeleteCascade); + } + + private: + friend class Session; + Movement(std::string_view name, std::optional number, std::optional count, const ObjectPtr& track); + + std::string _name; + std::optional _number; + std::optional _count; + Wt::Dbo::ptr _track; + }; + +} // namespace lms::db diff --git a/src/libs/database/include/database/objects/MovementId.hpp b/src/libs/database/include/database/objects/MovementId.hpp new file mode 100644 index 00000000..264f3789 --- /dev/null +++ b/src/libs/database/include/database/objects/MovementId.hpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2025 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#pragma once + +#include "database/IdType.hpp" + +LMS_DECLARE_IDTYPE(MovementId) diff --git a/src/libs/database/include/database/objects/Track.hpp b/src/libs/database/include/database/objects/Track.hpp index 5c84a60c..ca743af6 100644 --- a/src/libs/database/include/database/objects/Track.hpp +++ b/src/libs/database/include/database/objects/Track.hpp @@ -51,12 +51,14 @@ #include "database/objects/MediaLibraryId.hpp" #include "database/objects/MediumId.hpp" #include "database/objects/MoodId.hpp" +#include "database/objects/MovementId.hpp" #include "database/objects/ReleaseId.hpp" #include "database/objects/TrackEmbeddedImageId.hpp" #include "database/objects/TrackId.hpp" #include "database/objects/TrackListId.hpp" #include "database/objects/Types.hpp" #include "database/objects/UserId.hpp" +#include "database/objects/WorkId.hpp" #include "database/objects/detail/Types.hpp" namespace lms::db @@ -69,16 +71,18 @@ namespace lms::db class Genre; class Grouping; class Language; + class Medium; + class Movement; class Mood; class TrackEmbeddedImageLink; class MediaLibrary; - class Medium; class Release; class Session; class TrackArtistLink; class TrackLyrics; class TrackStats; class User; + class Work; class Track final : public Object { @@ -279,6 +283,8 @@ namespace lms::db void setGroupings(std::span> groupings); void setLanguages(std::span> languages); void setMoods(std::span> moods); + void setWorks(std::span> works); + void clearMovements(); void clearLyrics(); void clearEmbeddedLyrics(); void addLyrics(const ObjectPtr& lyrics); @@ -310,7 +316,7 @@ namespace lms::db // Metadata std::optional getTrackNumber() const { return _trackNumber; } - std::string getName() const { return _name; } + std::string_view getName() const { return _name; } const core::PartialDateTime& getDate() const { return _date; } std::optional getYear() const; const core::PartialDateTime& getOriginalDate() const { return _originalDate; } @@ -347,6 +353,10 @@ namespace lms::db std::vector getLanguageIds() const; std::vector> getMoods() const; std::vector getMoodIds() const; + std::vector> getWorks() const; + bool hasWork() const; + std::vector> getMovements() const; + bool hasMovement() const; ObjectPtr getMediaLibrary() const; ObjectPtr getDirectory() const; ObjectPtr getPreferredArtwork() const; @@ -393,12 +403,14 @@ namespace lms::db Wt::Dbo::belongsTo(a, _directory, "directory", Wt::Dbo::OnDeleteCascade); Wt::Dbo::belongsTo(a, _preferredArtwork, "preferred_artwork", Wt::Dbo::OnDeleteSetNull); Wt::Dbo::belongsTo(a, _preferredMediaArtwork, "preferred_media_artwork", Wt::Dbo::OnDeleteSetNull); + Wt::Dbo::hasMany(a, _movements, Wt::Dbo::ManyToOne, "track"); Wt::Dbo::hasMany(a, _trackArtistLinks, Wt::Dbo::ManyToOne, "track"); Wt::Dbo::hasMany(a, _clusters, Wt::Dbo::ManyToMany, "track_cluster", "", Wt::Dbo::OnDeleteCascade); Wt::Dbo::hasMany(a, _genres, Wt::Dbo::ManyToMany, "track_genre", "", Wt::Dbo::OnDeleteCascade); Wt::Dbo::hasMany(a, _groupings, Wt::Dbo::ManyToMany, "track_grouping", "", Wt::Dbo::OnDeleteCascade); Wt::Dbo::hasMany(a, _languages, Wt::Dbo::ManyToMany, "track_language", "", Wt::Dbo::OnDeleteCascade); Wt::Dbo::hasMany(a, _moods, Wt::Dbo::ManyToMany, "track_mood", "", Wt::Dbo::OnDeleteCascade); + Wt::Dbo::hasMany(a, _works, Wt::Dbo::ManyToMany, "track_work", "", Wt::Dbo::OnDeleteCascade); Wt::Dbo::hasMany(a, _trackLyrics, Wt::Dbo::ManyToOne, "track"); Wt::Dbo::hasMany(a, _embeddedImageLinks, Wt::Dbo::ManyToOne, "track"); } @@ -441,7 +453,6 @@ namespace lms::db std::string _artistDisplayName; std::string _comment; Advisory _advisory{ Advisory::UnSet }; - Wt::Dbo::ptr _medium; Wt::Dbo::ptr _release; Wt::Dbo::ptr _mediaLibrary; @@ -454,6 +465,8 @@ namespace lms::db Wt::Dbo::collection> _groupings; Wt::Dbo::collection> _languages; Wt::Dbo::collection> _moods; + Wt::Dbo::collection> _works; + Wt::Dbo::collection> _movements; Wt::Dbo::collection> _trackLyrics; Wt::Dbo::collection> _embeddedImageLinks; }; diff --git a/src/libs/database/include/database/objects/Work.hpp b/src/libs/database/include/database/objects/Work.hpp new file mode 100644 index 00000000..cc7a3d00 --- /dev/null +++ b/src/libs/database/include/database/objects/Work.hpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2025 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#pragma once + +#include +#include +#include +#include + +#include +#include + +#include "core/UUID.hpp" + +#include "database/Object.hpp" +#include "database/Types.hpp" +#include "database/objects/ReleaseId.hpp" +#include "database/objects/TrackId.hpp" +#include "database/objects/WorkId.hpp" + +namespace lms::db +{ + class Session; + class Track; + + class Work final : public Object + { + public: + static constexpr std::size_t maxNameLength{ 512 }; + + Work() = default; + + static pointer find(Session& session, WorkId id); + // Global lookup: MusicBrainz Work Id is a strong, unambiguous identity shared across the whole library + static pointer find(Session& session, const core::UUID& mbid); + // Name-only lookup, scoped to works already linked to a track of the given release: work titles are + // often generic (e.g. "Symphony No. 5") and collide across unrelated works, so without an mbid we only + // ever match within the same release instead of matching globally by name + static pointer find(Session& session, ReleaseId releaseId, std::string_view name); + static std::vector findOrphanIds(Session& session, std::optional range = std::nullopt); + + void setName(std::string_view name); + + std::string_view getName() const { return _name; } + std::optional getMBID() const { return _mbid; } + + template + void persist(Action& a) + { + Wt::Dbo::field(a, _name, "name"); + Wt::Dbo::field(a, _mbid, "mbid"); + Wt::Dbo::hasMany(a, _tracks, Wt::Dbo::ManyToMany, "track_work", "", Wt::Dbo::OnDeleteCascade); + } + + private: + friend class Session; + Work(std::string_view name, const std::optional& mbid); + static pointer create(Session& session, std::string_view name, const std::optional& mbid); + + std::string _name; + std::optional _mbid; + Wt::Dbo::collection> _tracks; + }; + +} // namespace lms::db diff --git a/src/libs/database/include/database/objects/WorkId.hpp b/src/libs/database/include/database/objects/WorkId.hpp new file mode 100644 index 00000000..35e1ca3d --- /dev/null +++ b/src/libs/database/include/database/objects/WorkId.hpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2025 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#pragma once + +#include "database/IdType.hpp" + +LMS_DECLARE_IDTYPE(WorkId) diff --git a/src/libs/database/test/CMakeLists.txt b/src/libs/database/test/CMakeLists.txt index 90a204f1..0858c8b6 100644 --- a/src/libs/database/test/CMakeLists.txt +++ b/src/libs/database/test/CMakeLists.txt @@ -16,6 +16,7 @@ add_executable(test-database Medium.cpp Migration.cpp Mood.cpp + Movement.cpp PlayListFile.cpp Podcast.cpp RatedArtist.cpp @@ -29,6 +30,7 @@ add_executable(test-database StarredTrack.cpp Track.cpp TrackArtistLink.cpp + Work.cpp TrackBookmark.cpp TrackEmbeddedImage.cpp TrackList.cpp diff --git a/src/libs/database/test/Movement.cpp b/src/libs/database/test/Movement.cpp new file mode 100644 index 00000000..84ec1269 --- /dev/null +++ b/src/libs/database/test/Movement.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2025 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#include "Common.hpp" + +#include "database/objects/Movement.hpp" +#include "database/objects/Track.hpp" + +namespace lms::db::tests +{ + TEST_F(DatabaseFixture, Movement_create) + { + ScopedTrack track{ session }; + + { + auto transaction{ session.createWriteTransaction() }; + Movement::create(session, "Allegro con brio", std::size_t{ 1 }, std::size_t{ 4 }, track.get()); + } + + { + auto transaction{ session.createReadTransaction() }; + const auto movements{ track->getMovements() }; + ASSERT_EQ(movements.size(), 1); + ASSERT_FALSE(movements[0]->getName().empty()); + EXPECT_EQ(movements[0]->getName(), "Allegro con brio"); + ASSERT_TRUE(movements[0]->getNumber()); + EXPECT_EQ(*movements[0]->getNumber(), std::size_t{ 1 }); + ASSERT_TRUE(movements[0]->getCount()); + EXPECT_EQ(*movements[0]->getCount(), std::size_t{ 4 }); + } + } + + TEST_F(DatabaseFixture, Movement_createWithNullFields) + { + ScopedTrack track{ session }; + + { + auto transaction{ session.createWriteTransaction() }; + Movement::create(session, "", std::nullopt, std::nullopt, track.get()); + } + + { + auto transaction{ session.createReadTransaction() }; + const auto movements{ track->getMovements() }; + ASSERT_EQ(movements.size(), 1); + EXPECT_TRUE(movements[0]->getName().empty()); + EXPECT_FALSE(movements[0]->getNumber()); + EXPECT_FALSE(movements[0]->getCount()); + } + } + + TEST_F(DatabaseFixture, Movement_multipleMovementsOnTrack) + { + ScopedTrack track{ session }; + + { + auto transaction{ session.createWriteTransaction() }; + Movement::create(session, "Allegro con brio", std::size_t{ 1 }, std::size_t{ 4 }, track.get()); + Movement::create(session, "Andante con moto", std::size_t{ 2 }, std::size_t{ 4 }, track.get()); + Movement::create(session, "Scherzo. Allegro", std::size_t{ 3 }, std::size_t{ 4 }, track.get()); + } + + { + auto transaction{ session.createReadTransaction() }; + const auto movements{ track->getMovements() }; + EXPECT_EQ(movements.size(), 3); + } + } + + TEST_F(DatabaseFixture, Movement_cascadeDeleteWithTrack) + { + ScopedTrack track{ session }; + + { + auto transaction{ session.createWriteTransaction() }; + Movement::create(session, "Allegro", std::size_t{ 1 }, std::nullopt, track.get()); + } + + { + auto transaction{ session.createReadTransaction() }; + EXPECT_EQ(track->getMovements().size(), 1); + } + + // track goes out of scope here — movements are cascade deleted + } + + TEST_F(DatabaseFixture, Movement_clearMovements) + { + ScopedTrack track{ session }; + + { + auto transaction{ session.createWriteTransaction() }; + Movement::create(session, "Allegro", std::size_t{ 1 }, std::size_t{ 2 }, track.get()); + Movement::create(session, "Andante", std::size_t{ 2 }, std::size_t{ 2 }, track.get()); + } + + { + auto transaction{ session.createReadTransaction() }; + EXPECT_EQ(track->getMovements().size(), 2); + } + + { + auto transaction{ session.createWriteTransaction() }; + track.get().modify()->clearMovements(); + } + + { + auto transaction{ session.createReadTransaction() }; + EXPECT_EQ(track->getMovements().size(), 0); + } + } + + TEST_F(DatabaseFixture, Movement_replacingMovements) + { + ScopedTrack track{ session }; + + { + auto transaction{ session.createWriteTransaction() }; + Movement::create(session, "OldMovement", std::size_t{ 1 }, std::nullopt, track.get()); + } + + { + auto transaction{ session.createWriteTransaction() }; + track.get().modify()->clearMovements(); + Movement::create(session, "NewMovement", std::size_t{ 1 }, std::nullopt, track.get()); + } + + { + auto transaction{ session.createReadTransaction() }; + const auto movements{ track->getMovements() }; + ASSERT_EQ(movements.size(), 1); + ASSERT_FALSE(movements[0]->getName().empty()); + EXPECT_EQ(movements[0]->getName(), "NewMovement"); + } + } + + TEST_F(DatabaseFixture, Movement_getNumberReturnsCorrectSizeT) + { + ScopedTrack track{ session }; + + { + auto transaction{ session.createWriteTransaction() }; + Movement::create(session, "", std::size_t{ 42 }, std::size_t{ 100 }, track.get()); + } + + { + auto transaction{ session.createReadTransaction() }; + const auto movements{ track->getMovements() }; + ASSERT_EQ(movements.size(), 1); + ASSERT_TRUE(movements[0]->getNumber()); + EXPECT_EQ(*movements[0]->getNumber(), std::size_t{ 42 }); + ASSERT_TRUE(movements[0]->getCount()); + EXPECT_EQ(*movements[0]->getCount(), std::size_t{ 100 }); + } + } +} // namespace lms::db::tests diff --git a/src/libs/database/test/Work.cpp b/src/libs/database/test/Work.cpp new file mode 100644 index 00000000..846a949a --- /dev/null +++ b/src/libs/database/test/Work.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2025 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#include "Common.hpp" + +#include "database/objects/Work.hpp" + +namespace lms::db::tests +{ + using ScopedWork = ScopedEntity; + + TEST_F(DatabaseFixture, Work_create) + { + ScopedWork work{ session, "Symphony No. 5", std::optional{} }; + + { + auto transaction{ session.createReadTransaction() }; + + const Work::pointer found{ Work::find(session, work.getId()) }; + ASSERT_TRUE(found); + EXPECT_EQ(found->getName(), "Symphony No. 5"); + EXPECT_FALSE(found->getMBID()); + } + } + + TEST_F(DatabaseFixture, Work_createWithMBID) + { + const auto mbid{ core::UUID::fromString("8f3471b3-7e93-4de1-a9c7-3b843c21b84e") }; + ASSERT_TRUE(mbid); + + ScopedWork work{ session, "Symphony No. 9", mbid }; + + { + auto transaction{ session.createReadTransaction() }; + + const Work::pointer found{ Work::find(session, work.getId()) }; + ASSERT_TRUE(found); + EXPECT_EQ(found->getName(), "Symphony No. 9"); + ASSERT_TRUE(found->getMBID()); + EXPECT_EQ(found->getMBID(), mbid); + } + } + + TEST_F(DatabaseFixture, Work_findByMBID) + { + const auto mbid{ core::UUID::fromString("8f3471b3-7e93-4de1-a9c7-3b843c21b84e") }; + ASSERT_TRUE(mbid); + + ScopedWork workWithMbid{ session, "Piano Sonata", mbid }; + + { + auto transaction{ session.createReadTransaction() }; + + const Work::pointer byMbid{ Work::find(session, *mbid) }; + ASSERT_TRUE(byMbid); + EXPECT_EQ(byMbid->getId(), workWithMbid.getId()); + } + } + + TEST_F(DatabaseFixture, Work_findByNameScopedToRelease) + { + // Work titles are often generic (e.g. "Piano Sonata"): two unrelated releases can each have + // their own work with the exact same name, and lookup must not merge them + ScopedRelease release1{ session, "Release1" }; + ScopedRelease release2{ session, "Release2" }; + ScopedTrack track1{ session }; + ScopedTrack track2{ session }; + ScopedWork work1{ session, "Piano Sonata", std::optional{} }; + ScopedWork work2{ session, "Piano Sonata", std::optional{} }; + + { + auto transaction{ session.createWriteTransaction() }; + track1.get().modify()->setRelease(release1.get()); + track1.get().modify()->setWorks(std::array{ work1.get() }); + track2.get().modify()->setRelease(release2.get()); + track2.get().modify()->setWorks(std::array{ work2.get() }); + } + + { + auto transaction{ session.createReadTransaction() }; + + // Same name, but each release resolves to its own work + const Work::pointer foundInRelease1{ Work::find(session, release1.getId(), "Piano Sonata") }; + ASSERT_TRUE(foundInRelease1); + EXPECT_EQ(foundInRelease1->getId(), work1.getId()); + + const Work::pointer foundInRelease2{ Work::find(session, release2.getId(), "Piano Sonata") }; + ASSERT_TRUE(foundInRelease2); + EXPECT_EQ(foundInRelease2->getId(), work2.getId()); + + // Unknown name in a known release returns null + EXPECT_FALSE(Work::find(session, release1.getId(), "Unknown Work")); + } + } + + TEST_F(DatabaseFixture, Work_orphan) + { + ScopedWork work{ session, "Unlinked Work", std::optional{} }; + + { + auto transaction{ session.createReadTransaction() }; + const auto orphans{ Work::findOrphanIds(session) }; + ASSERT_EQ(orphans.size(), 1); + EXPECT_EQ(orphans.front(), work.getId()); + } + } + + TEST_F(DatabaseFixture, Work_singleTrack) + { + ScopedTrack track{ session }; + ScopedWork work1{ session, "Requiem", std::optional{} }; + ScopedWork work2{ session, "Missa Solemnis", std::optional{} }; + + { + auto transaction{ session.createReadTransaction() }; + EXPECT_EQ(Work::findOrphanIds(session).size(), 2); + EXPECT_EQ(track->getWorks().size(), 0); + } + + { + auto transaction{ session.createWriteTransaction() }; + track.get().modify()->setWorks(std::array{ work1.get() }); + } + + { + auto transaction{ session.createReadTransaction() }; + + const auto orphans{ Work::findOrphanIds(session) }; + ASSERT_EQ(orphans.size(), 1); + EXPECT_EQ(orphans.front(), work2.getId()); + + const auto trackWorks{ track->getWorks() }; + ASSERT_EQ(trackWorks.size(), 1); + EXPECT_EQ(trackWorks.front()->getId(), work1.getId()); + } + } + + TEST_F(DatabaseFixture, Work_multipleWorksOnTrack) + { + ScopedTrack track{ session }; + ScopedWork work1{ session, "Symphony No. 5", std::optional{} }; + ScopedWork work2{ session, "Symphony No. 6", std::optional{} }; + + { + auto transaction{ session.createWriteTransaction() }; + track.get().modify()->setWorks(std::array{ work1.get(), work2.get() }); + } + + { + auto transaction{ session.createReadTransaction() }; + EXPECT_EQ(Work::findOrphanIds(session).size(), 0); + + const auto trackWorks{ track->getWorks() }; + EXPECT_EQ(trackWorks.size(), 2); + } + } + + TEST_F(DatabaseFixture, Work_multipleTracksOnWork) + { + ScopedTrack track1{ session }; + ScopedTrack track2{ session }; + ScopedTrack track3{ session }; + ScopedWork work{ session, "The Four Seasons", std::optional{} }; + + { + auto transaction{ session.createWriteTransaction() }; + track1.get().modify()->setWorks(std::array{ work.get() }); + track2.get().modify()->setWorks(std::array{ work.get() }); + track3.get().modify()->setWorks(std::array{ work.get() }); + } + + { + auto transaction{ session.createReadTransaction() }; + EXPECT_EQ(Work::findOrphanIds(session).size(), 0); + + EXPECT_EQ(track1->getWorks().size(), 1); + EXPECT_EQ(track2->getWorks().size(), 1); + EXPECT_EQ(track3->getWorks().size(), 1); + } + } + + TEST_F(DatabaseFixture, Work_nameTruncation) + { + const std::string longName(Work::maxNameLength + 100, 'x'); + const std::string expectedName(Work::maxNameLength, 'x'); + + { + auto transaction{ session.createWriteTransaction() }; + Work::pointer work{ session.create(longName, std::optional{}) }; + ASSERT_TRUE(work); + EXPECT_EQ(work->getName().size(), Work::maxNameLength); + EXPECT_EQ(work->getName(), expectedName); + work.remove(); + } + } + +} // namespace lms::db::tests diff --git a/src/libs/services/scanner/impl/scanners/audiofile/AudioFileScanOperation.cpp b/src/libs/services/scanner/impl/scanners/audiofile/AudioFileScanOperation.cpp index 9f7b5918..7e68b47a 100644 --- a/src/libs/services/scanner/impl/scanners/audiofile/AudioFileScanOperation.cpp +++ b/src/libs/services/scanner/impl/scanners/audiofile/AudioFileScanOperation.cpp @@ -41,6 +41,7 @@ #include "database/objects/MediaLibrary.hpp" #include "database/objects/Medium.hpp" #include "database/objects/Mood.hpp" +#include "database/objects/Movement.hpp" #include "database/objects/Release.hpp" #include "database/objects/ReleaseArtistLink.hpp" #include "database/objects/Track.hpp" @@ -49,6 +50,7 @@ #include "database/objects/TrackEmbeddedImageLink.hpp" #include "database/objects/TrackLyrics.hpp" #include "database/objects/TrackMusicNNEmbeddings.hpp" +#include "database/objects/Work.hpp" #include "image/Exception.hpp" #include "image/Image.hpp" @@ -368,6 +370,24 @@ namespace lms::scanner return moods; } + std::vector getOrCreateWorks(db::Session& session, db::ReleaseId releaseId, std::span works) + { + std::vector dbWorks; + dbWorks.reserve(works.size()); + for (const Work& work : works) + { + // Work titles are often generic and collide across unrelated works, so + // without an mbid we only ever match a work already used on the same release, not globally by name + db::Work::pointer dbWork{ work.mbid ? db::Work::find(session, *work.mbid) : (releaseId.isValid() ? db::Work::find(session, releaseId, work.name) : db::Work::pointer{}) }; + if (!dbWork) + dbWork = session.create(work.name, work.mbid); + else if (dbWork->getName() != work.name) + dbWork.modify()->setName(work.name); + dbWorks.push_back(dbWork); + } + return dbWorks; + } + std::vector getOrCreateClusters(db::Session& session, const Track& track) { std::vector clusters; @@ -836,6 +856,12 @@ namespace lms::scanner track.modify()->setGroupings(getOrCreateGroupings(dbSession, _file->track.groupings)); track.modify()->setLanguages(getOrCreateLanguages(dbSession, _file->track.languages)); track.modify()->setMoods(getOrCreateMoods(dbSession, _file->track.moods)); + track.modify()->setWorks(getOrCreateWorks(dbSession, track->getReleaseId(), _file->track.works)); + + track.modify()->clearMovements(); + for (const auto& movement : _file->track.movements) + db::Movement::create(dbSession, movement.name, movement.number, movement.count, track); + track.modify()->setName(title); track.modify()->setTrackNumber(_file->track.position); track.modify()->setDate(_file->track.date); diff --git a/src/libs/services/scanner/impl/scanners/audiofile/TrackMetadataParser.cpp b/src/libs/services/scanner/impl/scanners/audiofile/TrackMetadataParser.cpp index 230d2e30..c248a6f5 100644 --- a/src/libs/services/scanner/impl/scanners/audiofile/TrackMetadataParser.cpp +++ b/src/libs/services/scanner/impl/scanners/audiofile/TrackMetadataParser.cpp @@ -184,6 +184,38 @@ namespace lms::scanner return res; } + std::vector getWorks(const audio::ITagReader& tagReader) + { + const std::vector titles{ getTagValuesAs(tagReader, audio::TagType::WorkTitle, {}) }; + const std::vector mbids{ getTagValuesAs(tagReader, audio::TagType::MusicBrainzWorkID, {}) }; + + const bool mbidsMatch{ mbids.size() == titles.size() }; + + std::vector works; + works.reserve(titles.size()); + for (std::size_t i{}; i < titles.size(); ++i) + works.push_back({ mbidsMatch ? std::optional{ mbids[i] } : std::nullopt, titles[i] }); + + return works; + } + + std::vector getMovements(const audio::ITagReader& tagReader) + { + const std::vector names{ getTagValuesAs(tagReader, audio::TagType::Movement, {}) }; + const std::vector numbers{ getTagValuesAs(tagReader, audio::TagType::MovementNumber, {}) }; + const std::vector counts{ getTagValuesAs(tagReader, audio::TagType::MovementCount, {}) }; + + const bool numbersMatch{ numbers.size() == names.size() }; + const bool countsMatch{ counts.size() == names.size() }; + + std::vector movements; + movements.reserve(names.size()); + for (std::size_t i{}; i < names.size(); ++i) + movements.push_back({ names[i], numbersMatch ? std::optional{ numbers[i] } : std::nullopt, countsMatch ? std::optional{ counts[i] } : std::nullopt }); + + return movements; + } + std::vector getArtists(const audio::ITagReader& tagReader, std::initializer_list artistTagNames, std::initializer_list artistSortTagNames, @@ -328,6 +360,8 @@ namespace lms::scanner track.title = getTagValueAs(tagReader, TagType::TrackTitle).value_or(""); track.mbid = getTagValueAs(tagReader, TagType::MusicBrainzTrackID); track.recordingMBID = getTagValueAs(tagReader, TagType::MusicBrainzRecordingID); + track.works = getWorks(tagReader); + track.movements = getMovements(tagReader); track.acoustID = getTagValueAs(tagReader, TagType::AcoustID); track.position = getTagValueAs(tagReader, TagType::TrackNumber); // May parse 'Number/Total', that's fine if (const auto dateStr{ getTagValueAs(tagReader, TagType::Date) }) diff --git a/src/libs/services/scanner/impl/steps/ScanStepRemoveOrphanedDbEntries.cpp b/src/libs/services/scanner/impl/steps/ScanStepRemoveOrphanedDbEntries.cpp index 3c371fe1..df484b4c 100644 --- a/src/libs/services/scanner/impl/steps/ScanStepRemoveOrphanedDbEntries.cpp +++ b/src/libs/services/scanner/impl/steps/ScanStepRemoveOrphanedDbEntries.cpp @@ -33,6 +33,7 @@ #include "database/objects/Release.hpp" #include "database/objects/Track.hpp" #include "database/objects/TrackEmbeddedImage.hpp" +#include "database/objects/Work.hpp" #include "ScanContext.hpp" @@ -52,6 +53,7 @@ namespace lms::scanner removeOrphanedGroupings(context); removeOrphanedLanguages(context); removeOrphanedMoods(context); + removeOrphanedWorks(context); removeOrphanedArtists(context); removeOrphanedReleases(context); removeOrphanedMediums(context); // after release so that most entries are removed using the medium foreign key @@ -98,6 +100,12 @@ namespace lms::scanner removeOrphanedEntries(context); } + void ScanStepRemoveOrphanedDbEntries::removeOrphanedWorks(ScanContext& context) + { + LMS_LOG(DBUPDATER, DEBUG, "Checking orphaned works..."); + removeOrphanedEntries(context); + } + void ScanStepRemoveOrphanedDbEntries::removeOrphanedArtists(ScanContext& context) { LMS_LOG(DBUPDATER, DEBUG, "Checking orphaned artists..."); diff --git a/src/libs/services/scanner/impl/steps/ScanStepRemoveOrphanedDbEntries.hpp b/src/libs/services/scanner/impl/steps/ScanStepRemoveOrphanedDbEntries.hpp index 3173414e..27f59955 100644 --- a/src/libs/services/scanner/impl/steps/ScanStepRemoveOrphanedDbEntries.hpp +++ b/src/libs/services/scanner/impl/steps/ScanStepRemoveOrphanedDbEntries.hpp @@ -40,6 +40,7 @@ namespace lms::scanner void removeOrphanedGroupings(ScanContext& context); void removeOrphanedLanguages(ScanContext& context); void removeOrphanedMoods(ScanContext& context); + void removeOrphanedWorks(ScanContext& context); void removeOrphanedArtists(ScanContext& context); void removeOrphanedMediums(ScanContext& context); void removeOrphanedReleases(ScanContext& context); diff --git a/src/libs/services/scanner/impl/types/TrackMetadata.hpp b/src/libs/services/scanner/impl/types/TrackMetadata.hpp index 319c5fd8..ee247f68 100644 --- a/src/libs/services/scanner/impl/types/TrackMetadata.hpp +++ b/src/libs/services/scanner/impl/types/TrackMetadata.hpp @@ -54,6 +54,14 @@ namespace lms::scanner using PerformerContainer = std::map>; + struct Work + { + std::optional mbid; + std::string name; + + auto operator<=>(const Work&) const = default; + }; + struct Release { std::optional mbid; @@ -100,8 +108,17 @@ namespace lms::scanner Clean, }; + struct MovementData + { + std::string name; + std::optional number; + std::optional count; + }; + std::optional mbid; std::optional recordingMBID; + std::vector works; + std::vector movements; std::string title; std::optional medium; std::optional position; // in medium diff --git a/src/libs/services/scanner/test/TestTagReader.hpp b/src/libs/services/scanner/test/TestTagReader.hpp index 3ba949a0..d5ed5e1b 100644 --- a/src/libs/services/scanner/test/TestTagReader.hpp +++ b/src/libs/services/scanner/test/TestTagReader.hpp @@ -137,6 +137,11 @@ namespace lms::scanner::tests { TagType::MusicBrainzReleaseID, { "3fa39992-b786-4585-a70e-85d5cc15ef69" } }, { TagType::MusicBrainzReleaseGroupID, { "5b1a5a44-8420-4426-9b86-d25dc8d04838" } }, { TagType::MusicBrainzRecordingID, { "bd3fc666-89de-4ac8-93f6-2dbf028ad8d5" } }, + { TagType::MusicBrainzWorkID, { "11112222-3333-4444-5555-666677778888", "aaaabbbb-cccc-dddd-eeee-ffff00001111" } }, + { TagType::WorkTitle, { "MyWork1", "MyWork2" } }, + { TagType::Movement, { "Allegro con brio", "Andante" } }, + { TagType::MovementNumber, { "1", "2" } }, + { TagType::MovementCount, { "4", "4" } }, { TagType::Producer, { "MyProducer1", "MyProducer2" } }, { TagType::Remixer, { "MyRemixer1", "MyRemixer2" } }, { TagType::RecordLabel, { "Label1", "Label2" } }, diff --git a/src/libs/services/scanner/test/TrackMetadataParser.cpp b/src/libs/services/scanner/test/TrackMetadataParser.cpp index 6f94bf4b..7ea182a0 100644 --- a/src/libs/services/scanner/test/TrackMetadataParser.cpp +++ b/src/libs/services/scanner/test/TrackMetadataParser.cpp @@ -114,6 +114,24 @@ namespace lms::scanner::tests EXPECT_EQ(track.producerArtists[1].name, "MyProducer2"); ASSERT_TRUE(track.recordingMBID.has_value()); EXPECT_EQ(track.recordingMBID.value(), core::UUID::fromString("bd3fc666-89de-4ac8-93f6-2dbf028ad8d5")); + ASSERT_EQ(track.works.size(), 2); + EXPECT_EQ(track.works[0].name, "MyWork1"); + EXPECT_EQ(track.works[1].name, "MyWork2"); + ASSERT_TRUE(track.works[0].mbid.has_value()); + EXPECT_EQ(track.works[0].mbid.value(), core::UUID::fromString("11112222-3333-4444-5555-666677778888")); + ASSERT_TRUE(track.works[1].mbid.has_value()); + EXPECT_EQ(track.works[1].mbid.value(), core::UUID::fromString("aaaabbbb-cccc-dddd-eeee-ffff00001111")); + ASSERT_EQ(track.movements.size(), 2); + EXPECT_EQ(track.movements[0].name, "Allegro con brio"); + ASSERT_TRUE(track.movements[0].number.has_value()); + EXPECT_EQ(track.movements[0].number.value(), 1); + ASSERT_TRUE(track.movements[0].count.has_value()); + EXPECT_EQ(track.movements[0].count.value(), 4); + EXPECT_EQ(track.movements[1].name, "Andante"); + ASSERT_TRUE(track.movements[1].number.has_value()); + EXPECT_EQ(track.movements[1].number.value(), 2); + ASSERT_TRUE(track.movements[1].count.has_value()); + EXPECT_EQ(track.movements[1].count.value(), 4); ASSERT_TRUE(track.replayGain.has_value()); EXPECT_FLOAT_EQ(track.replayGain.value(), -0.33); ASSERT_EQ(track.remixerArtists.size(), 2); @@ -720,6 +738,60 @@ namespace lms::scanner::tests EXPECT_EQ(track.artistDisplayName, "Artist1, Artist2"); // reconstruct the artist display name } + TEST(TrackMetadataParser, works_allMbidsPresent) + { + const TestTagReader testTags{ + { + { audio::TagType::WorkTitle, { "MyWork1", "MyWork2" } }, + { audio::TagType::MusicBrainzWorkID, { "11112222-3333-4444-5555-666677778888", "aaaabbbb-cccc-dddd-eeee-ffff00001111" } }, + } + }; + + const Track track{ TrackMetadataParser{}.parseTrackMetaData(testTags) }; + + ASSERT_EQ(track.works.size(), 2); + EXPECT_EQ(track.works[0].name, "MyWork1"); + EXPECT_EQ(track.works[0].mbid, core::UUID::fromString("11112222-3333-4444-5555-666677778888")); + EXPECT_EQ(track.works[1].name, "MyWork2"); + EXPECT_EQ(track.works[1].mbid, core::UUID::fromString("aaaabbbb-cccc-dddd-eeee-ffff00001111")); + } + + TEST(TrackMetadataParser, works_noMbids) + { + const TestTagReader testTags{ + { + { audio::TagType::WorkTitle, { "MyWork1", "MyWork2" } }, + } + }; + + const Track track{ TrackMetadataParser{}.parseTrackMetaData(testTags) }; + + ASSERT_EQ(track.works.size(), 2); + EXPECT_EQ(track.works[0].name, "MyWork1"); + EXPECT_EQ(track.works[0].mbid, std::nullopt); + EXPECT_EQ(track.works[1].name, "MyWork2"); + EXPECT_EQ(track.works[1].mbid, std::nullopt); + } + + TEST(TrackMetadataParser, works_mismatchedMbidCount) + { + // mbid count does not match work title count => mbids are all discarded (all or nothing) + const TestTagReader testTags{ + { + { audio::TagType::WorkTitle, { "MyWork1", "MyWork2" } }, + { audio::TagType::MusicBrainzWorkID, { "11112222-3333-4444-5555-666677778888" } }, + } + }; + + const Track track{ TrackMetadataParser{}.parseTrackMetaData(testTags) }; + + ASSERT_EQ(track.works.size(), 2); + EXPECT_EQ(track.works[0].name, "MyWork1"); + EXPECT_EQ(track.works[0].mbid, std::nullopt); + EXPECT_EQ(track.works[1].name, "MyWork2"); + EXPECT_EQ(track.works[1].mbid, std::nullopt); + } + TEST(TrackMetadataParser, heterogeneousArtistMbids) { { diff --git a/src/libs/services/scrobbling/impl/listenbrainz/ListensSynchronizer.cpp b/src/libs/services/scrobbling/impl/listenbrainz/ListensSynchronizer.cpp index cc481e45..0f36d7e2 100644 --- a/src/libs/services/scrobbling/impl/listenbrainz/ListensSynchronizer.cpp +++ b/src/libs/services/scrobbling/impl/listenbrainz/ListensSynchronizer.cpp @@ -118,7 +118,7 @@ namespace lms::scrobbling::listenBrainz Wt::Json::Object trackMetadata; trackMetadata["additional_info"] = std::move(additionalInfo); trackMetadata["artist_name"] = Wt::Json::Value{ std::string{ track->getArtistDisplayName() } }; - trackMetadata["track_name"] = Wt::Json::Value{ track->getName() }; + trackMetadata["track_name"] = Wt::Json::Value{ std::string{ track->getName() } }; if (track->getRelease()) trackMetadata["release_name"] = Wt::Json::Value{ std::string{ track->getRelease()->getName() } }; diff --git a/src/libs/subsonic/impl/responses/Song.cpp b/src/libs/subsonic/impl/responses/Song.cpp index 5289a7fc..b0192118 100644 --- a/src/libs/subsonic/impl/responses/Song.cpp +++ b/src/libs/subsonic/impl/responses/Song.cpp @@ -36,11 +36,13 @@ #include "database/objects/MediaLibrary.hpp" #include "database/objects/Medium.hpp" #include "database/objects/Mood.hpp" +#include "database/objects/Movement.hpp" #include "database/objects/Release.hpp" #include "database/objects/ReleaseArtistLink.hpp" #include "database/objects/Track.hpp" #include "database/objects/TrackArtistLink.hpp" #include "database/objects/User.hpp" +#include "database/objects/Work.hpp" #include "services/feedback/IFeedbackService.hpp" #include "services/scrobbling/IScrobblingService.hpp" @@ -250,6 +252,28 @@ namespace lms::api::subsonic trackResponse.addChild("replayGain", createReplayGainNode(track, medium)); + trackResponse.createEmptyArrayChild("works"); + for (const auto& work : track->getWorks()) + { + Response::Node workNode; + workNode.setAttribute("name", work->getName()); + if (const auto mbid{ work->getMBID() }) + workNode.setAttribute("musicBrainzId", mbid->toString()); + trackResponse.addArrayChild("works", std::move(workNode)); + } + + trackResponse.createEmptyArrayChild("movements"); + for (const auto& movement : track->getMovements()) + { + Response::Node movementNode; + movementNode.setAttribute("name", movement->getName()); + if (const auto n{ movement->getNumber() }) + movementNode.setAttribute("number", *n); + if (const auto c{ movement->getCount() }) + movementNode.setAttribute("count", *c); + trackResponse.addArrayChild("movements", std::move(movementNode)); + } + return trackResponse; } } // namespace lms::api::subsonic \ No newline at end of file diff --git a/src/lms/ui/MediaPlayer.cpp b/src/lms/ui/MediaPlayer.cpp index 1cbd635c..5e33226e 100644 --- a/src/lms/ui/MediaPlayer.cpp +++ b/src/lms/ui/MediaPlayer.cpp @@ -244,6 +244,7 @@ namespace lms::ui const std::string nativeResource{ _audioFileResource->getUrl(trackId) }; const auto artistDisplayInfo{ utils::computeArtistDisplayInfo(track, db::TrackArtistLinkType::Artist) }; + const std::string displayTitle{ utils::computeTrackDisplayTitle(track) }; oss << "var params = {" @@ -252,7 +253,7 @@ namespace lms::ui << " transcodingResource: \"" << transcodingResource << "\"," << " duration: " << std::chrono::duration_cast>(track->getDuration()).count() << "," << " replayGain: " << replayGain << "," - << " title: \"" << core::stringUtils::jsEscape(track->getName()) << "\"," + << " title: \"" << core::stringUtils::jsEscape(displayTitle) << "\"," << " artist: \"" << (!artistDisplayInfo.displayName.empty() ? core::stringUtils::jsEscape(track->getArtistDisplayName()) : "") << "\"," << " release: \"" << (release ? core::stringUtils::jsEscape(release->getName()) : "") << "\","; @@ -282,7 +283,7 @@ namespace lms::ui oss << jsRef() + ".mediaplayer.loadTrack(params, " << (play ? "true" : "false") << ")"; // true to autoplay _title->setTextFormat(Wt::TextFormat::Plain); - _title->setText(Wt::WString::fromUTF8(track->getName())); + _title->setText(Wt::WString::fromUTF8(displayTitle)); _artists->clear(); _artists->addWidget(utils::createArtistsAnchors(artistDisplayInfo)); diff --git a/src/lms/ui/PlayQueue.cpp b/src/lms/ui/PlayQueue.cpp index cf353658..73cf2057 100644 --- a/src/lms/ui/PlayQueue.cpp +++ b/src/lms/ui/PlayQueue.cpp @@ -368,7 +368,7 @@ namespace lms::ui entry->toggleStyleClass("Lms-entry-playing", selected); } - void PlayQueue::enqueueTracks(const std::vector& trackIds) + void PlayQueue::enqueueTracks(std::span trackIds) { { auto transaction{ LmsApp->getDbSession().createWriteTransaction() }; @@ -425,35 +425,35 @@ namespace lms::ui return tracks; } - void PlayQueue::play(const std::vector& trackIds) + void PlayQueue::play(std::span trackIds) { playAtIndex(trackIds, 0); } - void PlayQueue::playNext(const std::vector& trackIds) + void PlayQueue::playNext(std::span trackIds) { std::vector nextTracks{ getAndClearNextTracks() }; nextTracks.insert(std::cbegin(nextTracks), std::cbegin(trackIds), std::cend(trackIds)); playOrAddLast(nextTracks); } - void PlayQueue::playShuffled(const std::vector& trackIds) + void PlayQueue::playShuffled(std::span trackIds) { clearTracks(); - std::vector shuffledTrackIds{ trackIds }; + std::vector shuffledTrackIds{ std::cbegin(trackIds), std::cend(trackIds) }; core::random::shuffleContainer(shuffledTrackIds); enqueueTracks(shuffledTrackIds); loadTrack(0, true); } - void PlayQueue::playOrAddLast(const std::vector& trackIds) + void PlayQueue::playOrAddLast(std::span trackIds) { enqueueTracks(trackIds); if (!_isTrackSelected) loadTrack(0, true); } - void PlayQueue::playAtIndex(const std::vector& trackIds, std::size_t index) + void PlayQueue::playAtIndex(std::span trackIds, std::size_t index) { clearTracks(); enqueueTracks(trackIds); @@ -478,10 +478,12 @@ namespace lms::ui const auto track{ tracklistEntry->getTrack() }; const db::TrackId trackId{ track->getId() }; + const std::string displayTitle{ utils::computeTrackDisplayTitle(track) }; + Template* entry{ _entriesContainer->addNew