From 7386c89ae7b558fbcfa3df0873c85cce99a6c839 Mon Sep 17 00:00:00 2001 From: emeric Date: Mon, 18 Oct 2021 21:16:10 +0200 Subject: [PATCH] Migrated recommendation stuff --- .../services/auth/impl/AuthTokenService.cpp | 2 +- .../services/auth/impl/AuthTokenService.hpp | 2 +- src/libs/services/auth/impl/EnvService.cpp | 4 +- .../auth/impl/PasswordServiceBase.cpp | 2 +- .../auth/impl/PasswordServiceBase.hpp | 2 +- .../http-headers/HttpHeadersEnvService.hpp | 2 +- .../impl/internal/InternalPasswordService.cpp | 4 +- .../auth/impl/pam/PAMPasswordService.cpp | 2 +- .../{ => services}/auth/IAuthTokenService.hpp | 0 .../{ => services}/auth/IEnvService.hpp | 0 .../{ => services}/auth/IPasswordService.hpp | 4 +- .../include/{ => services}/auth/Types.hpp | 0 .../services/recommendation/CMakeLists.txt | 2 +- .../impl/FeaturesEngineCreator.hpp | 2 +- .../recommendation => impl}/IEngine.hpp | 15 +----- .../{Engine.cpp => RecommendationService.cpp} | 36 ++++++------- .../{Engine.hpp => RecommendationService.hpp} | 18 +++---- .../impl/clusters/ClustersEngine.cpp | 8 +-- .../impl/clusters/ClustersEngine.hpp | 3 +- .../impl/features/FeaturesEngine.cpp | 12 ++--- .../impl/features/FeaturesEngine.hpp | 3 +- .../recommendation/IRecommendationService.hpp | 51 +++++++++++++++++++ .../include/services/recommendation/Types.hpp | 22 ++++++++ src/libs/services/scanner/impl/Scanner.cpp | 26 +++++----- src/libs/services/scanner/impl/Scanner.hpp | 8 +-- .../scanner/include/scanner/IScanner.hpp | 4 +- src/libs/subsonic/impl/SubsonicResource.cpp | 10 ++-- src/lms/main.cpp | 12 ++--- src/lms/ui/Auth.cpp | 4 +- src/lms/ui/LmsApplication.cpp | 4 +- src/lms/ui/PlayQueue.cpp | 4 +- src/lms/ui/SettingsView.cpp | 2 +- src/lms/ui/admin/InitWizardView.cpp | 2 +- src/lms/ui/admin/UserView.cpp | 2 +- src/lms/ui/admin/UsersView.cpp | 2 +- src/lms/ui/common/PasswordValidator.cpp | 2 +- src/lms/ui/common/PasswordValidator.hpp | 2 +- src/lms/ui/explore/ArtistView.cpp | 4 +- src/lms/ui/explore/ReleaseView.cpp | 4 +- .../recommendation/LmsRecommendation.cpp | 32 ++++++------ 40 files changed, 189 insertions(+), 131 deletions(-) rename src/libs/services/auth/include/{ => services}/auth/IAuthTokenService.hpp (100%) rename src/libs/services/auth/include/{ => services}/auth/IEnvService.hpp (100%) rename src/libs/services/auth/include/{ => services}/auth/IPasswordService.hpp (98%) rename src/libs/services/auth/include/{ => services}/auth/Types.hpp (100%) rename src/libs/services/recommendation/{include/recommendation => impl}/IEngine.hpp (77%) rename src/libs/services/recommendation/impl/{Engine.cpp => RecommendationService.cpp} (83%) rename src/libs/services/recommendation/impl/{Engine.hpp => RecommendationService.hpp} (82%) create mode 100644 src/libs/services/recommendation/include/services/recommendation/IRecommendationService.hpp create mode 100644 src/libs/services/recommendation/include/services/recommendation/Types.hpp diff --git a/src/libs/services/auth/impl/AuthTokenService.cpp b/src/libs/services/auth/impl/AuthTokenService.cpp index f6f305b6..f4104ca0 100644 --- a/src/libs/services/auth/impl/AuthTokenService.cpp +++ b/src/libs/services/auth/impl/AuthTokenService.cpp @@ -23,7 +23,7 @@ #include #include -#include "auth/Types.hpp" +#include "services/auth/Types.hpp" #include "database/Session.hpp" #include "database/User.hpp" #include "utils/Exception.hpp" diff --git a/src/libs/services/auth/impl/AuthTokenService.hpp b/src/libs/services/auth/impl/AuthTokenService.hpp index 8825a3d3..e95a8a79 100644 --- a/src/libs/services/auth/impl/AuthTokenService.hpp +++ b/src/libs/services/auth/impl/AuthTokenService.hpp @@ -21,7 +21,7 @@ #include -#include "auth/IAuthTokenService.hpp" +#include "services/auth/IAuthTokenService.hpp" #include "AuthServiceBase.hpp" #include "LoginThrottler.hpp" diff --git a/src/libs/services/auth/impl/EnvService.cpp b/src/libs/services/auth/impl/EnvService.cpp index 12de9858..26f972a6 100644 --- a/src/libs/services/auth/impl/EnvService.cpp +++ b/src/libs/services/auth/impl/EnvService.cpp @@ -17,9 +17,9 @@ * along with LMS. If not, see . */ -#include "auth/IEnvService.hpp" +#include "services/auth/IEnvService.hpp" -#include "auth/Types.hpp" +#include "services/auth/Types.hpp" #include "http-headers/HttpHeadersEnvService.hpp" namespace Auth diff --git a/src/libs/services/auth/impl/PasswordServiceBase.cpp b/src/libs/services/auth/impl/PasswordServiceBase.cpp index 3b230503..bd1901ee 100644 --- a/src/libs/services/auth/impl/PasswordServiceBase.cpp +++ b/src/libs/services/auth/impl/PasswordServiceBase.cpp @@ -27,7 +27,7 @@ #include "pam/PAMPasswordService.hpp" #endif // LMS_SUPPORT_PAM -#include "auth/Types.hpp" +#include "services/auth/Types.hpp" #include "database/Session.hpp" #include "database/User.hpp" #include "utils/Exception.hpp" diff --git a/src/libs/services/auth/impl/PasswordServiceBase.hpp b/src/libs/services/auth/impl/PasswordServiceBase.hpp index f575e4e1..9f9575ec 100644 --- a/src/libs/services/auth/impl/PasswordServiceBase.hpp +++ b/src/libs/services/auth/impl/PasswordServiceBase.hpp @@ -21,7 +21,7 @@ #include -#include "auth/IPasswordService.hpp" +#include "services/auth/IPasswordService.hpp" #include "AuthServiceBase.hpp" #include "LoginThrottler.hpp" diff --git a/src/libs/services/auth/impl/http-headers/HttpHeadersEnvService.hpp b/src/libs/services/auth/impl/http-headers/HttpHeadersEnvService.hpp index 5c44b9fb..02e4f94c 100644 --- a/src/libs/services/auth/impl/http-headers/HttpHeadersEnvService.hpp +++ b/src/libs/services/auth/impl/http-headers/HttpHeadersEnvService.hpp @@ -19,7 +19,7 @@ #pragma once -#include "auth/IEnvService.hpp" +#include "services/auth/IEnvService.hpp" #include "AuthServiceBase.hpp" namespace Auth diff --git a/src/libs/services/auth/impl/internal/InternalPasswordService.cpp b/src/libs/services/auth/impl/internal/InternalPasswordService.cpp index 96a6c34a..fe162150 100644 --- a/src/libs/services/auth/impl/internal/InternalPasswordService.cpp +++ b/src/libs/services/auth/impl/internal/InternalPasswordService.cpp @@ -20,8 +20,8 @@ #include "InternalPasswordService.hpp" #include -#include "auth/IAuthTokenService.hpp" -#include "auth/Types.hpp" +#include "services/auth/IAuthTokenService.hpp" +#include "services/auth/Types.hpp" #include "database/Session.hpp" #include "database/User.hpp" #include "utils/Exception.hpp" diff --git a/src/libs/services/auth/impl/pam/PAMPasswordService.cpp b/src/libs/services/auth/impl/pam/PAMPasswordService.cpp index c5682f42..e24de954 100644 --- a/src/libs/services/auth/impl/pam/PAMPasswordService.cpp +++ b/src/libs/services/auth/impl/pam/PAMPasswordService.cpp @@ -26,7 +26,7 @@ #include #include -#include "auth/Types.hpp" +#include "services/auth/Types.hpp" #include "database/Session.hpp" #include "utils/Logger.hpp" diff --git a/src/libs/services/auth/include/auth/IAuthTokenService.hpp b/src/libs/services/auth/include/services/auth/IAuthTokenService.hpp similarity index 100% rename from src/libs/services/auth/include/auth/IAuthTokenService.hpp rename to src/libs/services/auth/include/services/auth/IAuthTokenService.hpp diff --git a/src/libs/services/auth/include/auth/IEnvService.hpp b/src/libs/services/auth/include/services/auth/IEnvService.hpp similarity index 100% rename from src/libs/services/auth/include/auth/IEnvService.hpp rename to src/libs/services/auth/include/services/auth/IEnvService.hpp diff --git a/src/libs/services/auth/include/auth/IPasswordService.hpp b/src/libs/services/auth/include/services/auth/IPasswordService.hpp similarity index 98% rename from src/libs/services/auth/include/auth/IPasswordService.hpp rename to src/libs/services/auth/include/services/auth/IPasswordService.hpp index f197ae16..6a9cb2bd 100644 --- a/src/libs/services/auth/include/auth/IPasswordService.hpp +++ b/src/libs/services/auth/include/services/auth/IPasswordService.hpp @@ -21,11 +21,11 @@ #include +#include #include #include -#include -#include "auth/Types.hpp" +#include "services/auth/Types.hpp" #include "database/Types.hpp" namespace Database diff --git a/src/libs/services/auth/include/auth/Types.hpp b/src/libs/services/auth/include/services/auth/Types.hpp similarity index 100% rename from src/libs/services/auth/include/auth/Types.hpp rename to src/libs/services/auth/include/services/auth/Types.hpp diff --git a/src/libs/services/recommendation/CMakeLists.txt b/src/libs/services/recommendation/CMakeLists.txt index 4682173d..a001854e 100644 --- a/src/libs/services/recommendation/CMakeLists.txt +++ b/src/libs/services/recommendation/CMakeLists.txt @@ -4,7 +4,7 @@ add_library(lmsrecommendation SHARED impl/features/FeaturesEngineCache.cpp impl/features/FeaturesEngine.cpp impl/features/FeaturesDefs.cpp - impl/Engine.cpp + impl/RecommendationService.cpp ) target_include_directories(lmsrecommendation INTERFACE diff --git a/src/libs/services/recommendation/impl/FeaturesEngineCreator.hpp b/src/libs/services/recommendation/impl/FeaturesEngineCreator.hpp index 1378970f..5cbbde7c 100644 --- a/src/libs/services/recommendation/impl/FeaturesEngineCreator.hpp +++ b/src/libs/services/recommendation/impl/FeaturesEngineCreator.hpp @@ -20,7 +20,7 @@ #pragma once #include -#include "recommendation/IEngine.hpp" +#include "IEngine.hpp" namespace Database { diff --git a/src/libs/services/recommendation/include/recommendation/IEngine.hpp b/src/libs/services/recommendation/impl/IEngine.hpp similarity index 77% rename from src/libs/services/recommendation/include/recommendation/IEngine.hpp rename to src/libs/services/recommendation/impl/IEngine.hpp index 26f180bc..8c16b407 100644 --- a/src/libs/services/recommendation/include/recommendation/IEngine.hpp +++ b/src/libs/services/recommendation/impl/IEngine.hpp @@ -24,6 +24,7 @@ #include #include "database/Types.hpp" #include "utils/EnumSet.hpp" +#include "services/recommendation/Types.hpp" namespace Database { @@ -37,23 +38,9 @@ namespace Recommendation public: virtual ~IEngine() = default; - struct Progress - { - std::size_t totalElems {}; - std::size_t processedElems {}; - }; - using ProgressCallback = std::function; virtual void load(bool forceReload, const ProgressCallback& progressCallback = {}) = 0; - virtual void cancelLoad() = 0; // wait for cancel done virtual void requestCancelLoad() = 0; - template - using ResultContainer = std::vector; - - using ArtistContainer = ResultContainer; - using ReleaseContainer = ResultContainer; - using TrackContainer = ResultContainer; - virtual TrackContainer getSimilarTracksFromTrackList(Database::TrackListId tracklistId, std::size_t maxCount) const = 0; virtual TrackContainer getSimilarTracks(const std::vector& tracksId, std::size_t maxCount) const = 0; virtual ReleaseContainer getSimilarReleases(Database::ReleaseId releaseId, std::size_t maxCount) const = 0; diff --git a/src/libs/services/recommendation/impl/Engine.cpp b/src/libs/services/recommendation/impl/RecommendationService.cpp similarity index 83% rename from src/libs/services/recommendation/impl/Engine.cpp rename to src/libs/services/recommendation/impl/RecommendationService.cpp index b6808ceb..b2b6f235 100644 --- a/src/libs/services/recommendation/impl/Engine.cpp +++ b/src/libs/services/recommendation/impl/RecommendationService.cpp @@ -17,7 +17,7 @@ * along with LMS. If not, see . */ -#include "Engine.hpp" +#include "RecommendationService.hpp" #include #include @@ -47,19 +47,19 @@ namespace Recommendation throw LmsException {"Internal error"}; } - std::unique_ptr - createEngine(Database::Db& db) + std::unique_ptr + createRecommendationService(Database::Db& db) { - return std::make_unique(db); + return std::make_unique(db); } - Engine::Engine(Database::Db& db) + RecommendationService::RecommendationService(Database::Db& db) : _db {db} { } - Engine::TrackContainer - Engine::getSimilarTracksFromTrackList(Database::TrackListId trackListId, std::size_t maxCount) const + TrackContainer + RecommendationService::getSimilarTracksFromTrackList(Database::TrackListId trackListId, std::size_t maxCount) const { TrackContainer res; @@ -78,8 +78,8 @@ namespace Recommendation return res; } - Engine::TrackContainer - Engine::getSimilarTracks(const std::vector& trackIds, std::size_t maxCount) const + TrackContainer + RecommendationService::getSimilarTracks(const std::vector& trackIds, std::size_t maxCount) const { TrackContainer res; @@ -102,8 +102,8 @@ namespace Recommendation return res; } - Engine::ReleaseContainer - Engine::getSimilarReleases(Database::ReleaseId releaseId, std::size_t maxCount) const + ReleaseContainer + RecommendationService::getSimilarReleases(Database::ReleaseId releaseId, std::size_t maxCount) const { ReleaseContainer res; @@ -128,8 +128,8 @@ namespace Recommendation return res; } - Engine::ArtistContainer - Engine::getSimilarArtists(Database::ArtistId artistId, EnumSet linkTypes, std::size_t maxCount) const + ArtistContainer + RecommendationService::getSimilarArtists(Database::ArtistId artistId, EnumSet linkTypes, std::size_t maxCount) const { ArtistContainer res; @@ -162,7 +162,7 @@ namespace Recommendation } void - Engine::load(bool forceReload, const ProgressCallback& progressCallback) + RecommendationService::load(bool forceReload, const ProgressCallback& progressCallback) { using namespace Database; @@ -208,18 +208,18 @@ namespace Recommendation } void - Engine::loadPendingEngine(EngineType engineType, std::unique_ptr engine, bool forceReload, const ProgressCallback& progressCallback) + RecommendationService::loadPendingEngine(EngineType engineType, std::unique_ptr engine, bool forceReload, const ProgressCallback& progressCallback) { if (!_loadCancelled) { LMS_LOG(RECOMMENDATION, INFO) << "Initializing engine '" << engineTypeToString(engineType) << "'..."; - auto progress {[&](const IEngine::Progress& progress) + auto progress {[&](const Progress& progress) { progressCallback(progress); }}; - engine->load(forceReload, progressCallback ? progress : IEngine::ProgressCallback {}); + engine->load(forceReload, progressCallback ? progress : ProgressCallback {}); { std::scoped_lock lock {_controlMutex}; @@ -236,7 +236,7 @@ namespace Recommendation } void - Engine::cancelLoad() + RecommendationService::cancelLoad() { LMS_LOG(RECOMMENDATION, DEBUG) << "Cancelling loading..."; diff --git a/src/libs/services/recommendation/impl/Engine.hpp b/src/libs/services/recommendation/impl/RecommendationService.hpp similarity index 82% rename from src/libs/services/recommendation/impl/Engine.hpp rename to src/libs/services/recommendation/impl/RecommendationService.hpp index ac253b5c..22e07217 100644 --- a/src/libs/services/recommendation/impl/Engine.hpp +++ b/src/libs/services/recommendation/impl/RecommendationService.hpp @@ -25,7 +25,8 @@ #include #include -#include "recommendation/IEngine.hpp" +#include "services/recommendation/IRecommendationService.hpp" +#include "IEngine.hpp" namespace Database { @@ -40,21 +41,20 @@ namespace Recommendation Features, }; - class Engine : public IEngine + class RecommendationService : public IRecommendationService { public: - Engine(Database::Db& db); - ~Engine() = default; + RecommendationService(Database::Db& db); + ~RecommendationService() = default; - Engine(const Engine&) = delete; - Engine(Engine&&) = delete; - Engine& operator=(const Engine&) = delete; - Engine& operator=(Engine&&) = delete; + RecommendationService(const RecommendationService&) = delete; + RecommendationService(RecommendationService&&) = delete; + RecommendationService& operator=(const RecommendationService&) = delete; + RecommendationService& operator=(RecommendationService&&) = delete; private: void load(bool forceReload, const ProgressCallback& progressCallback) override; void cancelLoad() override; - void requestCancelLoad() override {}; TrackContainer getSimilarTracksFromTrackList(Database::TrackListId tracklistId, std::size_t maxCount) const override; TrackContainer getSimilarTracks(const std::vector& tracksId, std::size_t maxCount) const override; diff --git a/src/libs/services/recommendation/impl/clusters/ClustersEngine.cpp b/src/libs/services/recommendation/impl/clusters/ClustersEngine.cpp index b0703a0f..f873443a 100644 --- a/src/libs/services/recommendation/impl/clusters/ClustersEngine.cpp +++ b/src/libs/services/recommendation/impl/clusters/ClustersEngine.cpp @@ -34,7 +34,7 @@ std::unique_ptr createClustersEngine(Database::Db& db) return std::make_unique(db); } -IEngine::TrackContainer +TrackContainer ClusterEngine::getSimilarTracks(const std::vector& trackIds, std::size_t maxCount) const { Database::Session& dbSession {_db.getTLSSession()}; @@ -52,7 +52,7 @@ ClusterEngine::getSimilarTracks(const std::vector& trackIds, return res; } -IEngine::ResultContainer +TrackContainer ClusterEngine::getSimilarTracksFromTrackList(Database::TrackListId tracklistId, std::size_t maxCount) const { Database::Session& dbSession {_db.getTLSSession()}; @@ -74,7 +74,7 @@ ClusterEngine::getSimilarTracksFromTrackList(Database::TrackListId tracklistId, return res; } -IEngine::ResultContainer +ReleaseContainer ClusterEngine::getSimilarReleases(Database::ReleaseId releaseId, std::size_t maxCount) const { Database::Session& dbSession {_db.getTLSSession()}; @@ -95,7 +95,7 @@ ClusterEngine::getSimilarReleases(Database::ReleaseId releaseId, std::size_t max return res; } -IEngine::ResultContainer +ArtistContainer ClusterEngine::getSimilarArtists(Database::ArtistId artistId, EnumSet artistLinkTypes, std::size_t maxCount) const { Database::Session& dbSession {_db.getTLSSession()}; diff --git a/src/libs/services/recommendation/impl/clusters/ClustersEngine.hpp b/src/libs/services/recommendation/impl/clusters/ClustersEngine.hpp index 47654aac..faff863c 100644 --- a/src/libs/services/recommendation/impl/clusters/ClustersEngine.hpp +++ b/src/libs/services/recommendation/impl/clusters/ClustersEngine.hpp @@ -19,7 +19,7 @@ #pragma once -#include "recommendation/IEngine.hpp" +#include "IEngine.hpp" namespace Recommendation { @@ -37,7 +37,6 @@ namespace Recommendation private: void load(bool, const ProgressCallback&) override {} void requestCancelLoad() override {} - void cancelLoad() {} TrackContainer getSimilarTracksFromTrackList(Database::TrackListId tracklistId, std::size_t maxCount) const override; TrackContainer getSimilarTracks(const std::vector& tracksId, std::size_t maxCount) const override; diff --git a/src/libs/services/recommendation/impl/features/FeaturesEngine.cpp b/src/libs/services/recommendation/impl/features/FeaturesEngine.cpp index 7b1f39b6..7610ee75 100644 --- a/src/libs/services/recommendation/impl/features/FeaturesEngine.cpp +++ b/src/libs/services/recommendation/impl/features/FeaturesEngine.cpp @@ -248,7 +248,7 @@ FeaturesEngine::loadFromCache(FeaturesEngineCache cache) load(std::move(cache._network), cache._trackPositions); } -IEngine::TrackContainer +TrackContainer FeaturesEngine::getSimilarTracksFromTrackList(Database::TrackListId trackListId, std::size_t maxCount) const { const TrackContainer trackIds {[&] @@ -269,7 +269,7 @@ FeaturesEngine::getSimilarTracksFromTrackList(Database::TrackListId trackListId, return getSimilarTracks(trackIds, maxCount); } -IEngine::TrackContainer +TrackContainer FeaturesEngine::getSimilarTracks(const std::vector& tracksIds, std::size_t maxCount) const { auto similarTrackIds {getSimilarObjects(tracksIds, _trackMatrix, _trackPositions, maxCount)}; @@ -290,7 +290,7 @@ FeaturesEngine::getSimilarTracks(const std::vector& tracksIds return similarTrackIds; } -IEngine::ReleaseContainer +ReleaseContainer FeaturesEngine::getSimilarReleases(Database::ReleaseId releaseId, std::size_t maxCount) const { auto similarReleaseIds {getSimilarObjects({releaseId}, _releaseMatrix, _releasePositions, maxCount)}; @@ -312,12 +312,12 @@ FeaturesEngine::getSimilarReleases(Database::ReleaseId releaseId, std::size_t ma return similarReleaseIds; } -std::vector +ArtistContainer FeaturesEngine::getSimilarArtists(Database::ArtistId artistId, EnumSet linkTypes, std::size_t maxCount) const { auto getSimilarArtistIdsForLinkType {[&] (Database::TrackArtistLinkType linkType) { - std::vector similarArtistIds; + ArtistContainer similarArtistIds; const auto itArtists {_artistMatrix.find(linkType)}; if (itArtists == std::cend(_artistMatrix)) @@ -336,7 +336,7 @@ FeaturesEngine::getSimilarArtists(Database::ArtistId artistId, EnumSet res(std::cbegin(similarArtistIds), std::cend(similarArtistIds)); + ArtistContainer res(std::cbegin(similarArtistIds), std::cend(similarArtistIds)); Database::Session& session {_db.getTLSSession()}; { diff --git a/src/libs/services/recommendation/impl/features/FeaturesEngine.hpp b/src/libs/services/recommendation/impl/features/FeaturesEngine.hpp index d6c1e81b..e29feb93 100644 --- a/src/libs/services/recommendation/impl/features/FeaturesEngine.hpp +++ b/src/libs/services/recommendation/impl/features/FeaturesEngine.hpp @@ -26,10 +26,10 @@ #include #include -#include "recommendation/IEngine.hpp" #include "som/DataNormalizer.hpp" #include "som/Network.hpp" #include "utils/Utils.hpp" +#include "IEngine.hpp" #include "FeaturesEngineCache.hpp" #include "FeaturesDefs.hpp" @@ -62,7 +62,6 @@ class FeaturesEngine : public IEngine private: void load(bool forceReload, const ProgressCallback& progressCallback) override; void requestCancelLoad() override; - void cancelLoad() override {} TrackContainer getSimilarTracksFromTrackList(Database::TrackListId tracklistId, std::size_t maxCount) const override; TrackContainer getSimilarTracks(const std::vector& tracksId, std::size_t maxCount) const override; diff --git a/src/libs/services/recommendation/include/services/recommendation/IRecommendationService.hpp b/src/libs/services/recommendation/include/services/recommendation/IRecommendationService.hpp new file mode 100644 index 00000000..900c95a4 --- /dev/null +++ b/src/libs/services/recommendation/include/services/recommendation/IRecommendationService.hpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 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 "utils/EnumSet.hpp" +#include "services/recommendation/Types.hpp" + +namespace Database +{ + class Db; +} + +namespace Recommendation +{ + class IRecommendationService + { + public: + virtual ~IRecommendationService() = default; + + virtual void load(bool forceReload, const ProgressCallback& progressCallback = {}) = 0; + virtual void cancelLoad() = 0; // wait for cancel done + + virtual TrackContainer getSimilarTracksFromTrackList(Database::TrackListId tracklistId, std::size_t maxCount) const = 0; + virtual TrackContainer getSimilarTracks(const std::vector& tracksId, std::size_t maxCount) const = 0; + virtual ReleaseContainer getSimilarReleases(Database::ReleaseId releaseId, std::size_t maxCount) const = 0; + virtual ArtistContainer getSimilarArtists(Database::ArtistId artistId, EnumSet linkTypes, std::size_t maxCount) const = 0; + }; + + std::unique_ptr createRecommendationService(Database::Db& db); + +} // ns Recommendation + diff --git a/src/libs/services/recommendation/include/services/recommendation/Types.hpp b/src/libs/services/recommendation/include/services/recommendation/Types.hpp new file mode 100644 index 00000000..08fa2f90 --- /dev/null +++ b/src/libs/services/recommendation/include/services/recommendation/Types.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include "database/Types.hpp" + +namespace Recommendation +{ + struct Progress + { + std::size_t totalElems {}; + std::size_t processedElems {}; + }; + using ProgressCallback = std::function; + + template + using ResultContainer = std::vector; + + using ArtistContainer = ResultContainer; + using ReleaseContainer = ResultContainer; + using TrackContainer = ResultContainer; + +} // namespace Recommendation diff --git a/src/libs/services/scanner/impl/Scanner.cpp b/src/libs/services/scanner/impl/Scanner.cpp index 125324dc..09efc62d 100644 --- a/src/libs/services/scanner/impl/Scanner.cpp +++ b/src/libs/services/scanner/impl/Scanner.cpp @@ -32,7 +32,7 @@ #include "database/TrackArtistLink.hpp" #include "database/TrackFeatures.hpp" #include "metadata/TagLibParser.hpp" -#include "recommendation/IEngine.hpp" +#include "services/recommendation/IRecommendationService.hpp" #include "utils/Exception.hpp" #include "utils/Logger.hpp" #include "utils/Path.hpp" @@ -249,13 +249,13 @@ getOrCreateClusters(Session& session, const MetaData::Clusters& clustersNames) namespace Scanner { std::unique_ptr -createScanner(Database::Db& db, Recommendation::IEngine& recommendationEngine) +createScanner(Database::Db& db, Recommendation::IRecommendationService& recommendationService) { - return std::make_unique(db, recommendationEngine); + return std::make_unique(db, recommendationService); } -Scanner::Scanner(Database::Db& db, Recommendation::IEngine& recommendationEngine) -: _recommendationEngine {recommendationEngine} +Scanner::Scanner(Database::Db& db, Recommendation::IRecommendationService& recommendationService) +: _recommendationService {recommendationService} , _dbSession {db} { // For now, always use TagLib @@ -284,8 +284,8 @@ Scanner::start() if (_abortScan) return; - _recommendationEngine.load(false, - [](const Recommendation::IEngine::Progress& progress) + _recommendationService.load(false, + [](const Recommendation::Progress& progress) { LMS_LOG(DBUPDATER, DEBUG) << "Reloading recommendation : " << progress.processedElems << "/" << progress.totalElems; }); @@ -302,7 +302,7 @@ Scanner::stop() _abortScan = true; _scheduleTimer.cancel(); - _recommendationEngine.cancelLoad(); + _recommendationService.cancelLoad(); _ioService.stop(); } @@ -316,7 +316,7 @@ Scanner::abortScan() _abortScan = true; _scheduleTimer.cancel(); - _recommendationEngine.cancelLoad(); + _recommendationService.cancelLoad(); _ioService.stop(); LMS_LOG(DBUPDATER, DEBUG) << "Scan abort done!"; @@ -571,7 +571,7 @@ Scanner::fetchTrackFeatures(Database::TrackId trackId, const UUID& recordingMBID void Scanner::fetchTrackFeatures(ScanStats& stats) { - if (_recommendationEngineType != ScanSettings::RecommendationEngineType::Features) + if (_recommendationServiceType != ScanSettings::RecommendationEngineType::Features) return; ScanStepStats stepStats{stats.startTime, ScanProgressStep::FetchingTrackFeatures}; @@ -638,7 +638,7 @@ Scanner::refreshScanSettings() [](const std::filesystem::path& extension) { return std::filesystem::path{ StringUtils::stringToLower(extension.string()) }; }); } _mediaDirectory = scanSettings->getMediaDirectory(); - _recommendationEngineType = scanSettings->getRecommendationEngineType(); + _recommendationServiceType = scanSettings->getRecommendationEngineType(); const auto clusterTypes = scanSettings->getClusterTypes(); std::set clusterTypeNames; @@ -1037,7 +1037,7 @@ Scanner::reloadSimilarityEngine(ScanStats& stats) { ScanStepStats stepStats {stats.startTime, ScanProgressStep::ReloadingSimilarityEngine}; - auto progressCallback {[&](const Recommendation::IEngine::Progress& progress) + auto progressCallback {[&](const Recommendation::Progress& progress) { stepStats.totalElems = progress.totalElems; stepStats.processedElems = progress.processedElems; @@ -1045,7 +1045,7 @@ Scanner::reloadSimilarityEngine(ScanStats& stats) }}; notifyInProgress(stepStats); - _recommendationEngine.load(stats.nbChanges() > 0, progressCallback); + _recommendationService.load(stats.nbChanges() > 0, progressCallback); notifyInProgress(stepStats); } diff --git a/src/libs/services/scanner/impl/Scanner.hpp b/src/libs/services/scanner/impl/Scanner.hpp index 76aeb819..6999ef9a 100644 --- a/src/libs/services/scanner/impl/Scanner.hpp +++ b/src/libs/services/scanner/impl/Scanner.hpp @@ -41,7 +41,7 @@ class UUID; namespace Recommendation { - class IEngine; + class IRecommendationService; } namespace Scanner { @@ -49,7 +49,7 @@ namespace Scanner { class Scanner : public IScanner { public: - Scanner(Database::Db& db, Recommendation::IEngine& recommendationEngine); + Scanner(Database::Db& db, Recommendation::IRecommendationService& recommendationService); ~Scanner(); Scanner(const Scanner&) = delete; @@ -92,7 +92,7 @@ class Scanner : public IScanner void notifyInProgress(const ScanStepStats& stats); void reloadSimilarityEngine(ScanStats& stats); - Recommendation::IEngine& _recommendationEngine; + Recommendation::IRecommendationService& _recommendationService; std::mutex _controlMutex; std::atomic _abortScan {}; @@ -115,7 +115,7 @@ class Scanner : public IScanner Database::ScanSettings::UpdatePeriod _updatePeriod {Database::ScanSettings::UpdatePeriod::Never}; std::unordered_set _fileExtensions; std::filesystem::path _mediaDirectory; - Database::ScanSettings::RecommendationEngineType _recommendationEngineType; + Database::ScanSettings::RecommendationEngineType _recommendationServiceType; }; } // Scanner diff --git a/src/libs/services/scanner/include/scanner/IScanner.hpp b/src/libs/services/scanner/include/scanner/IScanner.hpp index 018cca98..602a4626 100644 --- a/src/libs/services/scanner/include/scanner/IScanner.hpp +++ b/src/libs/services/scanner/include/scanner/IScanner.hpp @@ -31,7 +31,7 @@ namespace Database namespace Recommendation { - class IEngine; + class IRecommendationService; } namespace Scanner @@ -66,7 +66,7 @@ namespace Scanner virtual Events& getEvents() = 0; }; - std::unique_ptr createScanner(Database::Db& db, Recommendation::IEngine& recommendationEngine); + std::unique_ptr createScanner(Database::Db& db, Recommendation::IRecommendationService& recommendationEngine); } // Scanner diff --git a/src/libs/subsonic/impl/SubsonicResource.cpp b/src/libs/subsonic/impl/SubsonicResource.cpp index 43bbdcca..6cbac9a5 100644 --- a/src/libs/subsonic/impl/SubsonicResource.cpp +++ b/src/libs/subsonic/impl/SubsonicResource.cpp @@ -26,8 +26,8 @@ #include -#include "auth/IPasswordService.hpp" -#include "auth/IEnvService.hpp" +#include "services/auth/IPasswordService.hpp" +#include "services/auth/IEnvService.hpp" #include "database/Artist.hpp" #include "database/Cluster.hpp" #include "database/Db.hpp" @@ -37,7 +37,7 @@ #include "database/TrackBookmark.hpp" #include "database/TrackList.hpp" #include "database/User.hpp" -#include "recommendation/IEngine.hpp" +#include "services/recommendation/IRecommendationService.hpp" #include "services/scrobbling/IScrobblingService.hpp" #include "services/cover/ICoverService.hpp" #include "utils/IConfig.hpp" @@ -905,7 +905,7 @@ handleGetArtistInfoRequestCommon(RequestContext& context, bool id3) artistInfoNode.createChild("musicBrainzId").setValue(artistMBID->getAsString()); } - auto similarArtistsId {Service::get()->getSimilarArtists(id, {TrackArtistLinkType::Artist, TrackArtistLinkType::ReleaseArtist}, count)}; + auto similarArtistsId {Service::get()->getSimilarArtists(id, {TrackArtistLinkType::Artist, TrackArtistLinkType::ReleaseArtist}, count)}; { auto transaction {context.dbSession.createSharedTransaction()}; @@ -1141,7 +1141,7 @@ handleGetSimilarSongsRequestCommon(RequestContext& context, bool id3) // Optional params std::size_t count {getParameterAs(context.parameters, "count").value_or(50)}; - const auto similarArtistIds {Service::get()->getSimilarArtists(artistId, {TrackArtistLinkType::Artist, TrackArtistLinkType::ReleaseArtist}, 5)}; + const auto similarArtistIds {Service::get()->getSimilarArtists(artistId, {TrackArtistLinkType::Artist, TrackArtistLinkType::ReleaseArtist}, 5)}; auto transaction {context.dbSession.createSharedTransaction()}; diff --git a/src/lms/main.cpp b/src/lms/main.cpp index 467446dc..3d452a67 100644 --- a/src/lms/main.cpp +++ b/src/lms/main.cpp @@ -25,15 +25,15 @@ #include #include -#include "auth/IAuthTokenService.hpp" -#include "auth/IPasswordService.hpp" -#include "auth/IEnvService.hpp" +#include "services/auth/IAuthTokenService.hpp" +#include "services/auth/IPasswordService.hpp" +#include "services/auth/IEnvService.hpp" #include "services/cover/ICoverService.hpp" #include "database/Db.hpp" #include "database/Session.hpp" #include "scanner/IScanner.hpp" -#include "recommendation/IEngine.hpp" #include "subsonic/SubsonicResource.hpp" +#include "services/recommendation/IRecommendationService.hpp" #include "services/scrobbling/IScrobblingService.hpp" #include "ui/LmsApplication.hpp" #include "ui/LmsApplicationManager.hpp" @@ -258,8 +258,8 @@ int main(int argc, char* argv[]) Service httpClient {Http::createClient(ioContext)}; Service coverService {Cover::createCoverService(database, argv[0], server.appRoot() + "/images/unknown-cover.jpg")}; - Service recommendationEngineService {Recommendation::createEngine(database)}; - Service scannerService {Scanner::createScanner(database, *recommendationEngineService)}; + Service recommendationService {Recommendation::createRecommendationService(database)}; + Service scannerService {Scanner::createScanner(database, *recommendationService)}; scannerService->getEvents().scanComplete.connect([&] { diff --git a/src/lms/ui/Auth.cpp b/src/lms/ui/Auth.cpp index 29414b43..b7585247 100644 --- a/src/lms/ui/Auth.cpp +++ b/src/lms/ui/Auth.cpp @@ -28,8 +28,8 @@ #include #include -#include "auth/IAuthTokenService.hpp" -#include "auth/IPasswordService.hpp" +#include "services/auth/IAuthTokenService.hpp" +#include "services/auth/IPasswordService.hpp" #include "database/Session.hpp" #include "database/User.hpp" #include "utils/Logger.hpp" diff --git a/src/lms/ui/LmsApplication.cpp b/src/lms/ui/LmsApplication.cpp index 0c9123f7..b20489d8 100644 --- a/src/lms/ui/LmsApplication.cpp +++ b/src/lms/ui/LmsApplication.cpp @@ -28,8 +28,8 @@ #include #include -#include "auth/IEnvService.hpp" -#include "auth/IPasswordService.hpp" +#include "services/auth/IEnvService.hpp" +#include "services/auth/IPasswordService.hpp" #include "services/cover/ICoverService.hpp" #include "database/Artist.hpp" #include "database/Cluster.hpp" diff --git a/src/lms/ui/PlayQueue.cpp b/src/lms/ui/PlayQueue.cpp index 554b34d2..550016ee 100644 --- a/src/lms/ui/PlayQueue.cpp +++ b/src/lms/ui/PlayQueue.cpp @@ -28,7 +28,7 @@ #include "database/Track.hpp" #include "database/TrackList.hpp" #include "database/User.hpp" -#include "recommendation/IEngine.hpp" +#include "services/recommendation/IRecommendationService.hpp" #include "utils/Logger.hpp" #include "utils/Random.hpp" #include "utils/Service.hpp" @@ -520,7 +520,7 @@ PlayQueue::addEntry(const Database::TrackListEntry::pointer& tracklistEntry) void PlayQueue::enqueueRadioTracks() { - const auto similarTrackIds {Service::get()->getSimilarTracksFromTrackList(_tracklistId, 3)}; + const auto similarTrackIds {Service::get()->getSimilarTracksFromTrackList(_tracklistId, 3)}; std::vector trackToAddIds(std::cbegin(similarTrackIds), std::cend(similarTrackIds)); Random::shuffleContainer(trackToAddIds); diff --git a/src/lms/ui/SettingsView.cpp b/src/lms/ui/SettingsView.cpp index 66105842..c01c7d8e 100644 --- a/src/lms/ui/SettingsView.cpp +++ b/src/lms/ui/SettingsView.cpp @@ -34,7 +34,7 @@ #include "common/UUIDValidator.hpp" #include "common/ValueStringModel.hpp" -#include "auth/IPasswordService.hpp" +#include "services/auth/IPasswordService.hpp" #include "database/Session.hpp" #include "utils/IConfig.hpp" #include "utils/Logger.hpp" diff --git a/src/lms/ui/admin/InitWizardView.cpp b/src/lms/ui/admin/InitWizardView.cpp index b37645b3..ce7ca58d 100644 --- a/src/lms/ui/admin/InitWizardView.cpp +++ b/src/lms/ui/admin/InitWizardView.cpp @@ -24,7 +24,7 @@ #include #include -#include "auth/IPasswordService.hpp" +#include "services/auth/IPasswordService.hpp" #include "database/Session.hpp" #include "database/User.hpp" #include "utils/Exception.hpp" diff --git a/src/lms/ui/admin/UserView.cpp b/src/lms/ui/admin/UserView.cpp index 16374d80..e974c967 100644 --- a/src/lms/ui/admin/UserView.cpp +++ b/src/lms/ui/admin/UserView.cpp @@ -27,7 +27,7 @@ #include -#include "auth/IPasswordService.hpp" +#include "services/auth/IPasswordService.hpp" #include "database/User.hpp" #include "database/Session.hpp" #include "utils/IConfig.hpp" diff --git a/src/lms/ui/admin/UsersView.cpp b/src/lms/ui/admin/UsersView.cpp index 50bc58e7..98160461 100644 --- a/src/lms/ui/admin/UsersView.cpp +++ b/src/lms/ui/admin/UsersView.cpp @@ -23,7 +23,7 @@ #include #include -#include "auth/IPasswordService.hpp" +#include "services/auth/IPasswordService.hpp" #include "database/User.hpp" #include "database/Session.hpp" #include "utils/Logger.hpp" diff --git a/src/lms/ui/common/PasswordValidator.cpp b/src/lms/ui/common/PasswordValidator.cpp index 2df00c3f..2979739e 100644 --- a/src/lms/ui/common/PasswordValidator.cpp +++ b/src/lms/ui/common/PasswordValidator.cpp @@ -21,7 +21,7 @@ #include -#include "auth/IPasswordService.hpp" +#include "services/auth/IPasswordService.hpp" #include "utils/Service.hpp" #include "LmsApplication.hpp" diff --git a/src/lms/ui/common/PasswordValidator.hpp b/src/lms/ui/common/PasswordValidator.hpp index d504dbc1..40a22679 100644 --- a/src/lms/ui/common/PasswordValidator.hpp +++ b/src/lms/ui/common/PasswordValidator.hpp @@ -23,7 +23,7 @@ #include #include "database/Types.hpp" -#include "auth/Types.hpp" +#include "services/auth/Types.hpp" namespace UserInterface { diff --git a/src/lms/ui/explore/ArtistView.cpp b/src/lms/ui/explore/ArtistView.cpp index eb6f1d41..f44d7ee2 100644 --- a/src/lms/ui/explore/ArtistView.cpp +++ b/src/lms/ui/explore/ArtistView.cpp @@ -32,7 +32,7 @@ #include "database/Session.hpp" #include "database/Track.hpp" #include "database/User.hpp" -#include "recommendation/IEngine.hpp" +#include "services/recommendation/IRecommendationService.hpp" #include "utils/Logger.hpp" #include "utils/String.hpp" @@ -102,7 +102,7 @@ Artist::refreshView() if (!artistId) throw ArtistNotFoundException {}; - const auto similarArtistIds {Service::get()->getSimilarArtists(*artistId, {TrackArtistLinkType::Artist, TrackArtistLinkType::ReleaseArtist}, 5)}; + const auto similarArtistIds {Service::get()->getSimilarArtists(*artistId, {TrackArtistLinkType::Artist, TrackArtistLinkType::ReleaseArtist}, 5)}; auto transaction {LmsApp->getDbSession().createSharedTransaction()}; diff --git a/src/lms/ui/explore/ReleaseView.cpp b/src/lms/ui/explore/ReleaseView.cpp index 15334246..facbea1e 100644 --- a/src/lms/ui/explore/ReleaseView.cpp +++ b/src/lms/ui/explore/ReleaseView.cpp @@ -30,7 +30,7 @@ #include "database/ScanSettings.hpp" #include "database/Session.hpp" #include "database/Track.hpp" -#include "recommendation/IEngine.hpp" +#include "services/recommendation/IRecommendationService.hpp" #include "utils/Logger.hpp" #include "utils/String.hpp" @@ -101,7 +101,7 @@ Release::refreshView() if (!releaseId) throw ReleaseNotFoundException {}; - auto similarReleasesIds {Service::get()->getSimilarReleases(*releaseId, 6)}; + auto similarReleasesIds {Service::get()->getSimilarReleases(*releaseId, 6)}; auto transaction {LmsApp->getDbSession().createSharedTransaction()}; diff --git a/src/tools/recommendation/LmsRecommendation.cpp b/src/tools/recommendation/LmsRecommendation.cpp index c88dcc36..54118ffc 100644 --- a/src/tools/recommendation/LmsRecommendation.cpp +++ b/src/tools/recommendation/LmsRecommendation.cpp @@ -30,14 +30,14 @@ #include "database/Release.hpp" #include "database/Session.hpp" #include "database/Track.hpp" +#include "services/recommendation/IRecommendationService.hpp" #include "utils/IConfig.hpp" #include "utils/Service.hpp" #include "utils/StreamLogger.hpp" -#include "recommendation/IEngine.hpp" static void -dumpTracksRecommendation(Database::Session session, Recommendation::IEngine& engine, unsigned maxSimilarityCount) +dumpTracksRecommendation(Database::Session session, Recommendation::IRecommendationService& recommendationService, unsigned maxSimilarityCount) { const std::vector trackIds {[&]() { @@ -66,14 +66,14 @@ dumpTracksRecommendation(Database::Session session, Recommendation::IEngine& eng }; std::cout << "Processing track '" << trackToString(trackId) << std::endl; - for (Database::TrackId similarTrackId : engine.getSimilarTracks({trackId}, maxSimilarityCount)) + for (Database::TrackId similarTrackId : recommendationService.getSimilarTracks({trackId}, maxSimilarityCount)) std::cout << "\t- Similar track '" << trackToString(similarTrackId) << std::endl; } } static void -dumpReleasesRecommendation(Database::Session session, Recommendation::IEngine& engine, unsigned maxSimilarityCount) +dumpReleasesRecommendation(Database::Session session, Recommendation::IRecommendationService& recommendationService, unsigned maxSimilarityCount) { const std::vector releaseIds = std::invoke([&]() { @@ -93,14 +93,14 @@ dumpReleasesRecommendation(Database::Session session, Recommendation::IEngine& e }; std::cout << "Processing release '" << releaseToString(releaseId) << "'" << std::endl; - for (Database::ReleaseId similarReleaseId : engine.getSimilarReleases(releaseId, maxSimilarityCount)) + for (Database::ReleaseId similarReleaseId : recommendationService.getSimilarReleases(releaseId, maxSimilarityCount)) std::cout << "\t- Similar release '" << releaseToString(similarReleaseId) << "'" << std::endl; } } static void -dumpArtistsRecommendation(Database::Session session, Recommendation::IEngine& engine, unsigned maxSimilarityCount) +dumpArtistsRecommendation(Database::Session session, Recommendation::IRecommendationService& recommendationService, unsigned maxSimilarityCount) { const std::vector artistIds = std::invoke([&]() { @@ -120,7 +120,7 @@ dumpArtistsRecommendation(Database::Session session, Recommendation::IEngine& en }; std::cout << "Processing artist '" << artistToString(artistId) << "'" << std::endl; - for (Database::ArtistId similarArtistId : engine.getSimilarArtists(artistId, {Database::TrackArtistLinkType::Artist, Database::TrackArtistLinkType::ReleaseArtist}, maxSimilarityCount)) + for (Database::ArtistId similarArtistId : recommendationService.getSimilarArtists(artistId, {Database::TrackArtistLinkType::Artist, Database::TrackArtistLinkType::ReleaseArtist}, maxSimilarityCount)) { std::cout << "\t- Similar artist '" << artistToString(similarArtistId) << "'" << std::endl; } @@ -161,25 +161,25 @@ int main(int argc, char *argv[]) Database::Db db {config->getPath("working-dir") / "lms.db"}; Database::Session session {db}; - std::cout << "Creating recommendation engine..." << std::endl; - const auto engine {Recommendation::createEngine(db)}; - std::cout << "Recommendation engine created!" << std::endl; + std::cout << "Creating recommendation recommendationService..." << std::endl; + const auto recommendationService {Recommendation::createRecommendationService(db)}; + std::cout << "Recommendation recommendationService created!" << std::endl; - std::cout << "Loading recommendation engine..." << std::endl; - engine->load(false); + std::cout << "Loading recommendation recommendationService..." << std::endl; + recommendationService->load(false); unsigned maxSimilarityCount {vm["max"].as()}; - std::cout << "Recommendation engine loaded!" << std::endl; + std::cout << "Recommendation recommendationService loaded!" << std::endl; if (vm.count("tracks")) - dumpTracksRecommendation(db, *engine, maxSimilarityCount); + dumpTracksRecommendation(db, *recommendationService, maxSimilarityCount); if (vm.count("releases")) - dumpReleasesRecommendation(db, *engine, maxSimilarityCount); + dumpReleasesRecommendation(db, *recommendationService, maxSimilarityCount); if (vm.count("artists")) - dumpArtistsRecommendation(db, *engine, maxSimilarityCount); + dumpArtistsRecommendation(db, *recommendationService, maxSimilarityCount); } catch( std::exception& e) {