SubsonicAPI: optimized search for tracks
This commit is contained in:
@@ -34,6 +34,9 @@
|
||||
#include "utils/String.hpp"
|
||||
#include "utils/Utils.hpp"
|
||||
|
||||
namespace Cover
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
struct TrackInfo
|
||||
@@ -44,8 +47,7 @@ namespace
|
||||
std::optional<Database::ReleaseId> releaseId;
|
||||
};
|
||||
|
||||
std::optional<TrackInfo>
|
||||
getTrackInfo(Database::Session& dbSession, Database::TrackId trackId)
|
||||
std::optional<TrackInfo> getTrackInfo(Database::Session& dbSession, Database::TrackId trackId)
|
||||
{
|
||||
std::optional<TrackInfo> res;
|
||||
|
||||
@@ -82,25 +84,20 @@ namespace
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Cover {
|
||||
|
||||
using namespace Image;
|
||||
|
||||
static
|
||||
bool
|
||||
isFileSupported(const std::filesystem::path& file, const std::vector<std::filesystem::path>& extensions)
|
||||
bool isFileSupported(const std::filesystem::path& file, const std::vector<std::filesystem::path>& extensions)
|
||||
{
|
||||
return (std::find(std::cbegin(extensions), std::cend(extensions), file.extension()) != std::cend(extensions));
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ICoverService>
|
||||
createCoverService(Database::Db& db, const std::filesystem::path& execPath, const std::filesystem::path& defaultCoverPath)
|
||||
std::unique_ptr<ICoverService> createCoverService(Database::Db& db, const std::filesystem::path& execPath, const std::filesystem::path& defaultCoverPath)
|
||||
{
|
||||
return std::make_unique<CoverService>(db, execPath, defaultCoverPath);
|
||||
}
|
||||
|
||||
using namespace Image;
|
||||
|
||||
CoverService::CoverService(Database::Db& db,
|
||||
const std::filesystem::path& execPath,
|
||||
const std::filesystem::path& defaultCoverPath)
|
||||
@@ -134,8 +131,7 @@ CoverService::CoverService(Database::Db& db,
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<IEncodedImage>
|
||||
CoverService::getFromAvMediaFile(const Av::IAudioFile& input, ImageSize width) const
|
||||
std::unique_ptr<IEncodedImage> CoverService::getFromAvMediaFile(const Av::IAudioFile& input, ImageSize width) const
|
||||
{
|
||||
std::unique_ptr<IEncodedImage> image;
|
||||
|
||||
@@ -159,8 +155,7 @@ CoverService::getFromAvMediaFile(const Av::IAudioFile& input, ImageSize width) c
|
||||
return image;
|
||||
}
|
||||
|
||||
std::unique_ptr<IEncodedImage>
|
||||
CoverService::getFromCoverFile(const std::filesystem::path& p, ImageSize width) const
|
||||
std::unique_ptr<IEncodedImage> CoverService::getFromCoverFile(const std::filesystem::path& p, ImageSize width) const
|
||||
{
|
||||
std::unique_ptr<IEncodedImage> image;
|
||||
|
||||
@@ -178,8 +173,7 @@ CoverService::getFromCoverFile(const std::filesystem::path& p, ImageSize width)
|
||||
return image;
|
||||
}
|
||||
|
||||
std::shared_ptr<IEncodedImage>
|
||||
CoverService::getDefault(ImageSize width)
|
||||
std::shared_ptr<IEncodedImage> CoverService::getDefault(ImageSize width)
|
||||
{
|
||||
{
|
||||
std::shared_lock lock{ _cacheMutex };
|
||||
@@ -202,8 +196,7 @@ CoverService::getDefault(ImageSize width)
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<IEncodedImage>
|
||||
CoverService::getFromDirectory(const std::filesystem::path& directory, ImageSize width) const
|
||||
std::unique_ptr<IEncodedImage> CoverService::getFromDirectory(const std::filesystem::path& directory, ImageSize width) const
|
||||
{
|
||||
const std::multimap<std::string, std::filesystem::path> coverPaths{ getCoverPaths(directory) };
|
||||
|
||||
@@ -241,8 +234,7 @@ CoverService::getFromDirectory(const std::filesystem::path& directory, ImageSize
|
||||
return image;
|
||||
}
|
||||
|
||||
std::unique_ptr<IEncodedImage>
|
||||
CoverService::getFromSameNamedFile(const std::filesystem::path& filePath, ImageSize width) const
|
||||
std::unique_ptr<IEncodedImage> CoverService::getFromSameNamedFile(const std::filesystem::path& filePath, ImageSize width) const
|
||||
{
|
||||
std::unique_ptr<IEncodedImage> res;
|
||||
|
||||
@@ -262,8 +254,7 @@ CoverService::getFromSameNamedFile(const std::filesystem::path& filePath, ImageS
|
||||
return res;
|
||||
}
|
||||
|
||||
bool
|
||||
CoverService::checkCoverFile(const std::filesystem::path& filePath) const
|
||||
bool CoverService::checkCoverFile(const std::filesystem::path& filePath) const
|
||||
{
|
||||
std::error_code ec;
|
||||
|
||||
@@ -285,8 +276,7 @@ CoverService::checkCoverFile(const std::filesystem::path& filePath) const
|
||||
return true;
|
||||
}
|
||||
|
||||
std::multimap<std::string, std::filesystem::path>
|
||||
CoverService::getCoverPaths(const std::filesystem::path& directoryPath) const
|
||||
std::multimap<std::string, std::filesystem::path> CoverService::getCoverPaths(const std::filesystem::path& directoryPath) const
|
||||
{
|
||||
std::multimap<std::string, std::filesystem::path> res;
|
||||
std::error_code ec;
|
||||
@@ -306,8 +296,7 @@ CoverService::getCoverPaths(const std::filesystem::path& directoryPath) const
|
||||
return res;
|
||||
}
|
||||
|
||||
std::unique_ptr<IEncodedImage>
|
||||
CoverService::getFromTrack(const std::filesystem::path& p, ImageSize width) const
|
||||
std::unique_ptr<IEncodedImage> CoverService::getFromTrack(const std::filesystem::path& p, ImageSize width) const
|
||||
{
|
||||
std::unique_ptr<IEncodedImage> image;
|
||||
|
||||
@@ -323,14 +312,12 @@ CoverService::getFromTrack(const std::filesystem::path& p, ImageSize width) cons
|
||||
return image;
|
||||
}
|
||||
|
||||
std::shared_ptr<IEncodedImage>
|
||||
CoverService::getFromTrack(Database::TrackId trackId, ImageSize width)
|
||||
std::shared_ptr<IEncodedImage> CoverService::getFromTrack(Database::TrackId trackId, ImageSize width)
|
||||
{
|
||||
return getFromTrack(_db.getTLSSession(), trackId, width, true /* allow release fallback*/);
|
||||
}
|
||||
|
||||
std::shared_ptr<IEncodedImage>
|
||||
CoverService::getFromTrack(Database::Session& dbSession, Database::TrackId trackId, ImageSize width, bool allowReleaseFallback)
|
||||
std::shared_ptr<IEncodedImage> CoverService::getFromTrack(Database::Session& dbSession, Database::TrackId trackId, ImageSize width, bool allowReleaseFallback)
|
||||
{
|
||||
using namespace Database;
|
||||
|
||||
@@ -367,8 +354,7 @@ CoverService::getFromTrack(Database::Session& dbSession, Database::TrackId track
|
||||
return cover;
|
||||
}
|
||||
|
||||
std::shared_ptr<IEncodedImage>
|
||||
CoverService::getFromRelease(Database::ReleaseId releaseId, ImageSize width)
|
||||
std::shared_ptr<IEncodedImage> CoverService::getFromRelease(Database::ReleaseId releaseId, ImageSize width)
|
||||
{
|
||||
using namespace Database;
|
||||
const CacheEntryDesc cacheEntryDesc{ releaseId, width };
|
||||
@@ -395,13 +381,11 @@ CoverService::getFromRelease(Database::ReleaseId releaseId, ImageSize width)
|
||||
|
||||
if (!tracks.results.empty())
|
||||
{
|
||||
if (const Track::pointer track {Track::find(session, tracks.results.front())})
|
||||
{
|
||||
const Track::pointer& track{ tracks.results.front() };
|
||||
res = ReleaseInfo{};
|
||||
res->firstTrackId = track->getId();
|
||||
res->releaseDirectory = track->getPath().parent_path();
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
} };
|
||||
@@ -422,8 +406,7 @@ CoverService::getFromRelease(Database::ReleaseId releaseId, ImageSize width)
|
||||
return cover;
|
||||
}
|
||||
|
||||
void
|
||||
CoverService::flushCache()
|
||||
void CoverService::flushCache()
|
||||
{
|
||||
std::unique_lock lock{ _cacheMutex };
|
||||
|
||||
@@ -434,16 +417,14 @@ CoverService::flushCache()
|
||||
_cache.clear();
|
||||
}
|
||||
|
||||
void
|
||||
CoverService::setJpegQuality(unsigned quality)
|
||||
void CoverService::setJpegQuality(unsigned quality)
|
||||
{
|
||||
_jpegQuality = Utils::clamp<unsigned>(quality, 1, 100);
|
||||
|
||||
LMS_LOG(COVER, INFO) << "JPEG export quality = " << _jpegQuality;
|
||||
}
|
||||
|
||||
void
|
||||
CoverService::saveToCache(const CacheEntryDesc& entryDesc, std::shared_ptr<IEncodedImage> image)
|
||||
void CoverService::saveToCache(const CacheEntryDesc& entryDesc, std::shared_ptr<IEncodedImage> image)
|
||||
{
|
||||
std::unique_lock lock{ _cacheMutex };
|
||||
|
||||
@@ -458,8 +439,7 @@ CoverService::saveToCache(const CacheEntryDesc& entryDesc, std::shared_ptr<IEnco
|
||||
_cache[entryDesc] = image;
|
||||
}
|
||||
|
||||
std::shared_ptr<IEncodedImage>
|
||||
CoverService::loadFromCache(const CacheEntryDesc& entryDesc)
|
||||
std::shared_ptr<IEncodedImage> CoverService::loadFromCache(const CacheEntryDesc& entryDesc)
|
||||
{
|
||||
std::shared_lock lock{ _cacheMutex };
|
||||
|
||||
|
||||
@@ -39,11 +39,12 @@ namespace Database
|
||||
{
|
||||
namespace
|
||||
{
|
||||
Wt::Dbo::Query<TrackId> createQuery(Session& session, const Track::FindParameters& params)
|
||||
template <typename ResultType>
|
||||
Wt::Dbo::Query<ResultType> createQuery(Session& session, std::string_view itemToSelect, const Track::FindParameters& params)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
auto query{ session.getDboSession().query<TrackId>(params.distinct ? "SELECT DISTINCT t.id FROM track t" : "SELECT t.id FROM track t") };
|
||||
auto query{ session.getDboSession().query<ResultType>(params.distinct ? "SELECT DISTINCT " + std::string{ itemToSelect } + " FROM track t" : "SELECT t.id FROM track t") };
|
||||
|
||||
assert(params.keywords.empty() || params.name.empty());
|
||||
for (std::string_view keyword : params.keywords)
|
||||
@@ -168,6 +169,21 @@ namespace Database
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
template <typename ResultType>
|
||||
Wt::Dbo::Query<ResultType> createQuery(Session& session, const Track::FindParameters& params)
|
||||
{
|
||||
std::string_view itemToSelect;
|
||||
|
||||
if constexpr (std::is_same_v<ResultType, TrackId>)
|
||||
itemToSelect = "t.id";
|
||||
else if constexpr (std::is_same_v<ResultType, Wt::Dbo::ptr<Track>>)
|
||||
itemToSelect = "t";
|
||||
else
|
||||
static_assert("Unhandled type");
|
||||
|
||||
return createQuery<ResultType>(session, itemToSelect, params);
|
||||
}
|
||||
}
|
||||
|
||||
Track::Track(const std::filesystem::path& p)
|
||||
@@ -257,7 +273,7 @@ namespace Database
|
||||
return res;
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Track::findTrackMBIDDuplicates(Session& session, Range range)
|
||||
RangeResults<TrackId> Track::findIdsTrackMBIDDuplicates(Session& session, Range range)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
@@ -267,7 +283,7 @@ namespace Database
|
||||
return Utils::execQuery(query, range);
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Track::findWithRecordingMBIDAndMissingFeatures(Session& session, Range range)
|
||||
RangeResults<TrackId> Track::findIdsWithRecordingMBIDAndMissingFeatures(Session& session, Range range)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
@@ -295,16 +311,23 @@ namespace Database
|
||||
return std::vector<ClusterId>(res.begin(), res.end());
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Track::find(Session& session, const FindParameters& parameters)
|
||||
RangeResults<TrackId> Track::findIds(Session& session, const FindParameters& parameters)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
auto query{ createQuery(session, parameters) };
|
||||
|
||||
auto query{ createQuery<TrackId>(session, parameters) };
|
||||
return Utils::execQuery(query, parameters.range);
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Track::findSimilarTracks(Session& session, const std::vector<TrackId>& tracks, Range range)
|
||||
RangeResults<Track::pointer> Track::find(Session& session, const FindParameters& parameters)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Track>>(session, parameters) };
|
||||
return Utils::execQuery(query, parameters.range);
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Track::findSimilarTrackIds(Session& session, const std::vector<TrackId>& tracks, Range range)
|
||||
{
|
||||
assert(!tracks.empty());
|
||||
session.checkSharedLocked();
|
||||
|
||||
@@ -21,11 +21,10 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -111,12 +110,13 @@ class Track final : public Object<Track, TrackId>
|
||||
static bool exists(Session& session, TrackId id);
|
||||
static std::vector<pointer> findByRecordingMBID(Session& session, const UUID& MBID);
|
||||
static std::vector<pointer> findByMBID(Session& session, const UUID& MBID);
|
||||
static RangeResults<TrackId> findSimilarTracks(Session& session, const std::vector<TrackId>& trackIds, Range range);
|
||||
static RangeResults<TrackId> findSimilarTrackIds(Session& session, const std::vector<TrackId>& trackIds, Range range);
|
||||
|
||||
static RangeResults<TrackId> find(Session& session, const FindParameters& parameters);
|
||||
static RangeResults<TrackId> findIds(Session& session, const FindParameters& parameters);
|
||||
static RangeResults<pointer> find(Session& session, const FindParameters& parameters);
|
||||
static RangeResults<PathResult> findPaths(Session& session, Range range);
|
||||
static RangeResults<TrackId> findTrackMBIDDuplicates(Session& session, Range range);
|
||||
static RangeResults<TrackId> findWithRecordingMBIDAndMissingFeatures(Session& session, Range range);
|
||||
static RangeResults<TrackId> findIdsTrackMBIDDuplicates(Session& session, Range range);
|
||||
static RangeResults<TrackId> findIdsWithRecordingMBIDAndMissingFeatures(Session& session, Range range);
|
||||
|
||||
// Accessors
|
||||
void setScanVersion(std::size_t version) { _scanVersion = version; }
|
||||
|
||||
@@ -105,18 +105,18 @@ TEST_F(DatabaseFixture, Artist_singleTrack)
|
||||
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
auto tracks {Track::find(session, Track::FindParameters{}.setName("MyTrackName").setArtistName("MyArtist"))};
|
||||
auto tracks{ Track::findIds(session, Track::FindParameters{}.setName("MyTrackName").setArtistName("MyArtist")) };
|
||||
ASSERT_EQ(tracks.results.size(), 1);
|
||||
EXPECT_EQ(tracks.results.front(), track.getId());
|
||||
}
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
auto tracks {Track::find(session, Track::FindParameters{}.setName("MyTrackName").setArtistName("MyArtistFoo"))};
|
||||
auto tracks{ Track::findIds(session, Track::FindParameters{}.setName("MyTrackName").setArtistName("MyArtistFoo")) };
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
}
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
auto tracks {Track::find(session, Track::FindParameters{}.setName("MyTrackNameFoo").setArtistName("MyArtist"))};
|
||||
auto tracks{ Track::findIds(session, Track::FindParameters{}.setName("MyTrackNameFoo").setArtistName("MyArtist")) };
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
}
|
||||
{
|
||||
@@ -166,17 +166,17 @@ TEST_F(DatabaseFixture, Artist_singleTracktMultiRoles)
|
||||
|
||||
EXPECT_EQ(track->getArtistLinks().size(), 3);
|
||||
|
||||
auto tracks {Track::find(session, Track::FindParameters {}.setArtist(artist.getId()))};
|
||||
auto tracks{ Track::findIds(session, Track::FindParameters {}.setArtist(artist.getId())) };
|
||||
EXPECT_EQ(tracks.results.size(), 1);
|
||||
|
||||
tracks = Track::find(session, Track::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::ReleaseArtist}));
|
||||
tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist.getId(), { TrackArtistLinkType::ReleaseArtist }));
|
||||
EXPECT_EQ(tracks.results.size(), 1);
|
||||
tracks = Track::find(session, Track::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Artist}));
|
||||
tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist.getId(), { TrackArtistLinkType::Artist }));
|
||||
EXPECT_EQ(tracks.results.size(), 1);
|
||||
tracks = Track::find(session, Track::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Writer}));
|
||||
tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist.getId(), { TrackArtistLinkType::Writer }));
|
||||
EXPECT_EQ(tracks.results.size(), 1);
|
||||
|
||||
tracks = Track::find(session, Track::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Composer}));
|
||||
tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist.getId(), { TrackArtistLinkType::Composer }));
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
}
|
||||
|
||||
@@ -227,24 +227,24 @@ TEST_F(DatabaseFixture, Artist_singleTrackMultiArtists)
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
|
||||
auto tracks {Track::find(session, Track::FindParameters {}.setArtist(artist1->getId()))};
|
||||
auto tracks{ Track::findIds(session, Track::FindParameters {}.setArtist(artist1->getId())) };
|
||||
ASSERT_EQ(tracks.results.size(), 1);
|
||||
EXPECT_EQ(tracks.results.front(), track->getId());
|
||||
|
||||
tracks = Track::find(session, Track::FindParameters {}.setArtist(artist2->getId()));
|
||||
tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist2->getId()));
|
||||
ASSERT_EQ(tracks.results.size(), 1);
|
||||
EXPECT_EQ(tracks.results.front(), track->getId());
|
||||
|
||||
tracks = Track::find(session, Track::FindParameters {}.setArtist(artist1->getId(), {TrackArtistLinkType::ReleaseArtist}));
|
||||
tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist1->getId(), { TrackArtistLinkType::ReleaseArtist }));
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
|
||||
tracks = Track::find(session, Track::FindParameters {}.setArtist(artist1->getId(), {TrackArtistLinkType::Artist}));
|
||||
tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist1->getId(), { TrackArtistLinkType::Artist }));
|
||||
EXPECT_EQ(tracks.results.size(), 1);
|
||||
|
||||
tracks = Track::find(session, Track::FindParameters {}.setArtist(artist2->getId(), {TrackArtistLinkType::ReleaseArtist}));
|
||||
tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist2->getId(), { TrackArtistLinkType::ReleaseArtist }));
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
|
||||
tracks = Track::find(session, Track::FindParameters {}.setArtist(artist2->getId(), {TrackArtistLinkType::Artist}));
|
||||
tracks = Track::findIds(session, Track::FindParameters{}.setArtist(artist2->getId(), { TrackArtistLinkType::Artist }));
|
||||
EXPECT_EQ(tracks.results.size(), 1);
|
||||
}
|
||||
}
|
||||
@@ -377,7 +377,7 @@ TEST_F(DatabaseFixture, Artist_nonReleaseTracks)
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
|
||||
auto tracks {Track::find(session, Track::FindParameters {}.setNonRelease(true).setArtist(artist->getId()))};
|
||||
auto tracks{ Track::findIds(session, Track::FindParameters {}.setNonRelease(true).setArtist(artist->getId())) };
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
}
|
||||
|
||||
@@ -393,7 +393,7 @@ TEST_F(DatabaseFixture, Artist_nonReleaseTracks)
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
|
||||
const auto tracks {Track::find(session, Track::FindParameters {}.setArtist(artist.getId()).setNonRelease(true))};
|
||||
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());
|
||||
}
|
||||
@@ -434,4 +434,3 @@ TEST_F(DatabaseFixture, Artist_findByRelease)
|
||||
EXPECT_EQ(artists.results.front(), artist.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -133,11 +133,11 @@ TEST_F(DatabaseFixture, Cluster_singleTrack)
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
|
||||
auto tracks{ Track::find(session, Track::FindParameters {}.setClusters({cluster1.getId()})) };
|
||||
auto tracks{ Track::findIds(session, Track::FindParameters {}.setClusters({cluster1.getId()})) };
|
||||
ASSERT_EQ(tracks.results.size(), 1);
|
||||
EXPECT_EQ(tracks.results.front(), track.getId());
|
||||
|
||||
tracks = Track::find(session, Track::FindParameters{}.setClusters({ cluster2.getId() }));
|
||||
tracks = Track::findIds(session, Track::FindParameters{}.setClusters({ cluster2.getId() }));
|
||||
EXPECT_TRUE(tracks.results.empty());
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ TEST_F(DatabaseFixture, Cluster_singleTrackWithSeveralClusters)
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
|
||||
const auto tracks{ Track::find(session, Track::FindParameters{}.setClusters(clusterIds)) };
|
||||
const auto tracks{ Track::findIds(session, Track::FindParameters{}.setClusters(clusterIds)) };
|
||||
EXPECT_TRUE(tracks.results.empty());
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ TEST_F(DatabaseFixture, Cluster_singleTrackWithSeveralClusters)
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
|
||||
const auto tracks{ Track::find(session, Track::FindParameters{}.setClusters(clusterIds)) };
|
||||
const auto tracks{ Track::findIds(session, Track::FindParameters{}.setClusters(clusterIds)) };
|
||||
EXPECT_TRUE(tracks.results.empty());
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ TEST_F(DatabaseFixture, Cluster_singleTrackWithSeveralClusters)
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
|
||||
const auto tracks{ Track::find(session, Track::FindParameters{}.setClusters(clusterIds)) };
|
||||
const auto tracks{ Track::findIds(session, Track::FindParameters{}.setClusters(clusterIds)) };
|
||||
ASSERT_FALSE(tracks.results.empty());
|
||||
EXPECT_EQ(tracks.results.front(), track.getId());
|
||||
}
|
||||
@@ -550,7 +550,7 @@ TEST_F(DatabaseFixture, MultipleTracksSingleClusterSimilarity)
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
|
||||
const auto similarTracks{ Track::findSimilarTracks(session, {tracks.front().getId()}, Range {}) };
|
||||
const auto similarTracks{ Track::findSimilarTrackIds(session, {tracks.front().getId()}, Range {}) };
|
||||
EXPECT_EQ(similarTracks.results.size(), tracks.size() - 1);
|
||||
for (const TrackId similarTrackId : similarTracks.results)
|
||||
{
|
||||
@@ -591,14 +591,14 @@ TEST_F(DatabaseFixture, MultipleTracksMultipleClustersSimilarity)
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
|
||||
{
|
||||
auto similarTracks{ Track::findSimilarTracks(session, {tracks.back().getId()}, Range {0, 4}) };
|
||||
auto similarTracks{ Track::findSimilarTrackIds(session, {tracks.back().getId()}, Range {0, 4}) };
|
||||
EXPECT_EQ(similarTracks.results.size(), 4);
|
||||
for (const TrackId similarTrackId : similarTracks.results)
|
||||
EXPECT_TRUE(std::find_if(std::next(std::cbegin(tracks), 5), std::next(std::cend(tracks), -1), [&](const auto& track) { return similarTrackId == track.getId(); }) != std::cend(tracks));
|
||||
}
|
||||
|
||||
{
|
||||
auto similarTracks{ Track::findSimilarTracks(session, {tracks.front().getId()}, Range {}) };
|
||||
auto similarTracks{ Track::findSimilarTrackIds(session, {tracks.front().getId()}, Range {}) };
|
||||
EXPECT_EQ(similarTracks.results.size(), tracks.size() - 1);
|
||||
for (const TrackId similarTrackId : similarTracks.results)
|
||||
EXPECT_TRUE(std::find_if(std::next(std::cbegin(tracks), 1), std::cend(tracks), [&](const auto& track) { return similarTrackId == track.getId(); }) != std::cend(tracks));
|
||||
|
||||
@@ -78,7 +78,7 @@ TEST_F(DatabaseFixture, Release_singleTrack)
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
EXPECT_TRUE(Release::findOrphanIds(session, Range{}).results.empty());
|
||||
|
||||
const auto tracks{ Track::find(session, Track::FindParameters {}.setRelease(release.getId())) };
|
||||
const auto tracks{ Track::findIds(session, Track::FindParameters {}.setRelease(release.getId())) };
|
||||
ASSERT_EQ(tracks.results.size(), 1);
|
||||
EXPECT_EQ(tracks.results.front(), track.getId());
|
||||
}
|
||||
@@ -92,18 +92,18 @@ TEST_F(DatabaseFixture, Release_singleTrack)
|
||||
|
||||
{
|
||||
auto transaction{ session.createUniqueTransaction() };
|
||||
auto tracks{ Track::find(session, Track::FindParameters{}.setName("MyTrackName").setReleaseName("MyReleaseName")) };
|
||||
auto tracks{ Track::findIds(session, Track::FindParameters{}.setName("MyTrackName").setReleaseName("MyReleaseName")) };
|
||||
ASSERT_EQ(tracks.results.size(), 1);
|
||||
EXPECT_EQ(tracks.results.front(), track.getId());
|
||||
}
|
||||
{
|
||||
auto transaction{ session.createUniqueTransaction() };
|
||||
auto tracks{ Track::find(session, Track::FindParameters{}.setName("MyTrackName").setReleaseName("MyReleaseFoo")) };
|
||||
auto tracks{ Track::findIds(session, Track::FindParameters{}.setName("MyTrackName").setReleaseName("MyReleaseFoo")) };
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
}
|
||||
{
|
||||
auto transaction{ session.createUniqueTransaction() };
|
||||
auto tracks{ Track::find(session, Track::FindParameters{}.setName("MyTrackFoo").setReleaseName("MyReleaseName")) };
|
||||
auto tracks{ Track::findIds(session, Track::FindParameters{}.setName("MyTrackFoo").setReleaseName("MyReleaseName")) };
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
}
|
||||
}
|
||||
@@ -111,7 +111,7 @@ TEST_F(DatabaseFixture, Release_singleTrack)
|
||||
{
|
||||
auto transaction{ session.createUniqueTransaction() };
|
||||
|
||||
const auto tracks{ Track::find(session, Track::FindParameters {}.setRelease(release.getId())) };
|
||||
const auto tracks{ Track::findIds(session, Track::FindParameters {}.setRelease(release.getId())) };
|
||||
EXPECT_TRUE(tracks.results.empty());
|
||||
|
||||
auto releases{ Release::findOrphanIds(session, Range {}) };
|
||||
@@ -285,8 +285,8 @@ TEST_F(DatabaseFixture, MultiTracksSingleReleaseFirstTrack)
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
|
||||
EXPECT_TRUE(Track::find(session, Track::FindParameters{}.setRelease(release1.getId())).results.empty());
|
||||
EXPECT_TRUE(Track::find(session, Track::FindParameters{}.setRelease(release2.getId())).results.empty());
|
||||
EXPECT_TRUE(Track::findIds(session, Track::FindParameters{}.setRelease(release1.getId())).results.empty());
|
||||
EXPECT_TRUE(Track::findIds(session, Track::FindParameters{}.setRelease(release2.getId())).results.empty());
|
||||
}
|
||||
|
||||
{
|
||||
@@ -310,13 +310,13 @@ TEST_F(DatabaseFixture, MultiTracksSingleReleaseFirstTrack)
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
|
||||
{
|
||||
const auto tracks{ Track::find(session, Track::FindParameters {}.setRelease(release1.getId()).setSortMethod(TrackSortMethod::Release)) };
|
||||
const auto tracks{ Track::findIds(session, Track::FindParameters {}.setRelease(release1.getId()).setSortMethod(TrackSortMethod::Release)) };
|
||||
ASSERT_FALSE(tracks.results.empty());
|
||||
EXPECT_EQ(tracks.results.front(), track1A.getId());
|
||||
}
|
||||
|
||||
{
|
||||
const auto tracks{ Track::find(session, Track::FindParameters {}.setRelease(release2.getId()).setSortMethod(TrackSortMethod::Release)) };
|
||||
const auto tracks{ Track::findIds(session, Track::FindParameters {}.setRelease(release2.getId()).setSortMethod(TrackSortMethod::Release)) };
|
||||
ASSERT_FALSE(tracks.results.empty());
|
||||
EXPECT_EQ(tracks.results.front(), track2B.getId());
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ TEST_F(DatabaseFixture, StarredTrack)
|
||||
EXPECT_FALSE(starredTrack);
|
||||
EXPECT_EQ(StarredTrack::getCount(session), 0);
|
||||
|
||||
auto tracks {Track::find(session, Track::FindParameters {})};
|
||||
auto tracks {Track::findIds(session, Track::FindParameters {})};
|
||||
EXPECT_EQ(tracks.results.size(), 1);
|
||||
}
|
||||
|
||||
@@ -53,13 +53,13 @@ TEST_F(DatabaseFixture, StarredTrack)
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
|
||||
auto tracks {Track::find(session, Track::FindParameters {})};
|
||||
auto tracks {Track::findIds(session, Track::FindParameters {})};
|
||||
EXPECT_EQ(tracks.results.size(), 1);
|
||||
|
||||
tracks = Track::find(session, Track::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal));
|
||||
tracks = Track::findIds(session, Track::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal));
|
||||
EXPECT_EQ(tracks.results.size(), 1);
|
||||
|
||||
tracks = Track::find(session, Track::FindParameters {}.setStarringUser(user2.getId(), FeedbackBackend::Internal));
|
||||
tracks = Track::findIds(session, Track::FindParameters {}.setStarringUser(user2.getId(), FeedbackBackend::Internal));
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
}
|
||||
}
|
||||
@@ -73,11 +73,11 @@ TEST_F(DatabaseFixture, Starredtrack_PendingDestroy)
|
||||
{
|
||||
auto transaction {session.createUniqueTransaction()};
|
||||
|
||||
auto tracks {Track::find(session, Track::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal))};
|
||||
auto tracks {Track::findIds(session, Track::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal))};
|
||||
EXPECT_EQ(tracks.results.size(), 1);
|
||||
|
||||
starredTrack.get().modify()->setSyncState(SyncState::PendingRemove);
|
||||
tracks = Track::find(session, Track::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal));
|
||||
tracks = Track::findIds(session, Track::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal));
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
}
|
||||
}
|
||||
@@ -96,7 +96,7 @@ TEST_F(DatabaseFixture, StarredTrack_dateTime)
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
|
||||
auto tracks {Track::find(session, Track::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal))};
|
||||
auto tracks {Track::findIds(session, Track::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal))};
|
||||
EXPECT_EQ(tracks.results.size(), 2);
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ TEST_F(DatabaseFixture, StarredTrack_dateTime)
|
||||
starredTrack1.get().modify()->setDateTime(dateTime);
|
||||
starredTrack2.get().modify()->setDateTime(dateTime.addSecs(-1));
|
||||
|
||||
auto tracks {Track::find(session, Track::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal).setSortMethod(TrackSortMethod::StarredDateDesc))};
|
||||
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());
|
||||
@@ -117,7 +117,7 @@ TEST_F(DatabaseFixture, StarredTrack_dateTime)
|
||||
starredTrack1.get().modify()->setDateTime(dateTime);
|
||||
starredTrack2.get().modify()->setDateTime(dateTime.addSecs(1));
|
||||
|
||||
auto tracks {Track::find(session, Track::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal).setSortMethod(TrackSortMethod::StarredDateDesc))};
|
||||
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());
|
||||
|
||||
@@ -28,6 +28,7 @@ TEST_F(DatabaseFixture, Track)
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
EXPECT_EQ(Track::find(session, Track::FindParameters{}).results.size(), 0);
|
||||
EXPECT_EQ(Track::findIds(session, Track::FindParameters{}).results.size(), 0);
|
||||
EXPECT_EQ(Track::getCount(session), 0);
|
||||
EXPECT_FALSE(Track::exists(session, 0));
|
||||
}
|
||||
@@ -83,22 +84,22 @@ TEST_F(DatabaseFixture, MultipleTracksSearchByFilter)
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
|
||||
{
|
||||
const auto tracks {Track::find(session, Track::FindParameters {}.setKeywords({"Track"}))};
|
||||
const auto tracks{ Track::findIds(session, Track::FindParameters {}.setKeywords({"Track"})) };
|
||||
EXPECT_EQ(tracks.results.size(), 6);
|
||||
}
|
||||
{
|
||||
const auto tracks {Track::find(session, Track::FindParameters {}.setKeywords({"MyTrack"}))};
|
||||
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(); }));
|
||||
}
|
||||
{
|
||||
const auto tracks {Track::find(session, Track::FindParameters {}.setKeywords({"MyTrack%"}))};
|
||||
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());
|
||||
}
|
||||
{
|
||||
const auto tracks {Track::find(session, Track::FindParameters {}.setKeywords({"%MyTrack"}))};
|
||||
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());
|
||||
@@ -142,19 +143,19 @@ TEST_F(DatabaseFixture, Track_writtenAfter)
|
||||
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
const auto tracks {Track::find(session, Track::FindParameters {})};
|
||||
const auto tracks{ Track::findIds(session, Track::FindParameters {}) };
|
||||
EXPECT_EQ(tracks.results.size(), 1);
|
||||
}
|
||||
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
const auto tracks {Track::find(session, Track::FindParameters {}.setWrittenAfter(dateTime.addSecs(-1)))};
|
||||
const auto tracks{ Track::findIds(session, Track::FindParameters {}.setWrittenAfter(dateTime.addSecs(-1))) };
|
||||
EXPECT_EQ(tracks.results.size(), 1);
|
||||
}
|
||||
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
const auto tracks {Track::find(session, Track::FindParameters {}.setWrittenAfter(dateTime.addSecs(+1)))};
|
||||
const auto tracks{ Track::findIds(session, Track::FindParameters {}.setWrittenAfter(dateTime.addSecs(+1))) };
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,10 +49,10 @@ TEST_F(DatabaseFixture, SingleTrackListSingleTrack)
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
|
||||
auto tracks {Track::find(session, Track::FindParameters {}.setTrackList(trackList1.getId()))};
|
||||
auto tracks {Track::findIds(session, Track::FindParameters {}.setTrackList(trackList1.getId()))};
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
|
||||
tracks = Track::find(session, Track::FindParameters {}.setTrackList(trackList2.getId()));
|
||||
tracks = Track::findIds(session, Track::FindParameters {}.setTrackList(trackList2.getId()));
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
}
|
||||
|
||||
@@ -65,11 +65,11 @@ TEST_F(DatabaseFixture, SingleTrackListSingleTrack)
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
|
||||
auto tracks {Track::find(session, Track::FindParameters {}.setTrackList(trackList1.getId()))};
|
||||
auto tracks {Track::findIds(session, Track::FindParameters {}.setTrackList(trackList1.getId()))};
|
||||
ASSERT_EQ(tracks.results.size(), 1);
|
||||
EXPECT_EQ(tracks.results.front(), track.getId());
|
||||
|
||||
tracks = Track::find(session, Track::FindParameters {}.setTrackList(trackList2.getId()));
|
||||
tracks = Track::findIds(session, Track::FindParameters {}.setTrackList(trackList2.getId()));
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace Feedback
|
||||
Session& session{ _db.getTLSSession() };
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
|
||||
return Track::find(session, params);
|
||||
return Track::findIds(session, params);
|
||||
}
|
||||
} // ns Feedback
|
||||
|
||||
|
||||
@@ -32,8 +32,7 @@ namespace Recommendation
|
||||
{
|
||||
using namespace Database;
|
||||
|
||||
std::unique_ptr<IPlaylistGeneratorService>
|
||||
createPlaylistGeneratorService(Db& db, Recommendation::IRecommendationService& recommendationService)
|
||||
std::unique_ptr<IPlaylistGeneratorService> createPlaylistGeneratorService(Db& db, Recommendation::IRecommendationService& recommendationService)
|
||||
{
|
||||
return std::make_unique<PlaylistGeneratorService>(db, recommendationService);
|
||||
}
|
||||
@@ -47,8 +46,7 @@ namespace Recommendation
|
||||
_constraints.push_back(std::make_unique<PlaylistGeneratorConstraint::DuplicateTracks>());
|
||||
}
|
||||
|
||||
std::vector<TrackId>
|
||||
PlaylistGeneratorService::extendPlaylist(TrackListId tracklistId, std::size_t maxCount) const
|
||||
std::vector<TrackId> PlaylistGeneratorService::extendPlaylist(TrackListId tracklistId, std::size_t maxCount) const
|
||||
{
|
||||
LMS_LOG(RECOMMENDATION, DEBUG) << "Requested to extend playlist by " << maxCount << " similar tracks";
|
||||
|
||||
@@ -97,8 +95,7 @@ namespace Recommendation
|
||||
return std::vector(std::cbegin(finalResult) + startingTracks.size(), std::cend(finalResult));
|
||||
}
|
||||
|
||||
TrackContainer
|
||||
PlaylistGeneratorService::getTracksFromTrackList(Database::TrackListId tracklistId) const
|
||||
TrackContainer PlaylistGeneratorService::getTracksFromTrackList(Database::TrackListId tracklistId) const
|
||||
{
|
||||
TrackContainer tracks;
|
||||
|
||||
@@ -110,7 +107,7 @@ namespace Recommendation
|
||||
params.setSortMethod(TrackSortMethod::TrackList);
|
||||
params.setDistinct(false);
|
||||
|
||||
for (const TrackId trackId : Track::find(dbSession, params).results)
|
||||
for (const TrackId trackId : Track::findIds(dbSession, params).results)
|
||||
tracks.push_back(trackId);
|
||||
|
||||
return tracks;
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Recommendation {
|
||||
Session& dbSession{ _db.getTLSSession() };
|
||||
auto transaction{ dbSession.createSharedTransaction() };
|
||||
|
||||
const auto similarTrackIds{ Track::findSimilarTracks(dbSession, trackIds, Range {0, maxCount}) };
|
||||
const auto similarTrackIds{ Track::findSimilarTrackIds(dbSession, trackIds, Range {0, maxCount}) };
|
||||
return std::move(similarTrackIds.results);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Scanner
|
||||
Session& session {_db.getTLSSession()};
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
|
||||
const RangeResults<TrackId> tracks = Track::findTrackMBIDDuplicates(session, Range {});
|
||||
const RangeResults<TrackId> tracks = Track::findIdsTrackMBIDDuplicates(session, Range {});
|
||||
for (const TrackId trackId : tracks.results)
|
||||
{
|
||||
const Track::pointer track {Track::find(session, trackId)};
|
||||
|
||||
@@ -44,8 +44,7 @@ namespace
|
||||
{
|
||||
using namespace Scrobbling::ListenBrainz;
|
||||
|
||||
std::optional<Wt::Json::Object>
|
||||
listenToJsonPayload(Database::Session& session, const Scrobbling::Listen& listen, const Wt::WDateTime& timePoint)
|
||||
std::optional<Wt::Json::Object> listenToJsonPayload(Database::Session& session, const Scrobbling::Listen& listen, const Wt::WDateTime& timePoint)
|
||||
{
|
||||
auto transaction{ session.createSharedTransaction() };
|
||||
|
||||
@@ -107,8 +106,7 @@ namespace
|
||||
return payload;
|
||||
}
|
||||
|
||||
std::string
|
||||
listenToJsonString(Database::Session& session, const Scrobbling::Listen& listen, const Wt::WDateTime& timePoint, std::string_view listenType)
|
||||
std::string listenToJsonString(Database::Session& session, const Scrobbling::Listen& listen, const Wt::WDateTime& timePoint, std::string_view listenType)
|
||||
{
|
||||
std::string res;
|
||||
|
||||
@@ -124,8 +122,7 @@ namespace
|
||||
return res;
|
||||
}
|
||||
|
||||
std::optional<std::size_t>
|
||||
parseListenCount(std::string_view msgBody)
|
||||
std::optional<std::size_t> parseListenCount(std::string_view msgBody)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -142,8 +139,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
Database::TrackId
|
||||
tryGetMatchingTrack(Database::Session& session, const Listen& listen)
|
||||
Database::TrackId tryGetMatchingTrack(Database::Session& session, const Listen& listen)
|
||||
{
|
||||
using namespace Database;
|
||||
|
||||
@@ -192,7 +188,7 @@ namespace
|
||||
if (listen.trackNumber)
|
||||
params.setTrackNumber(*listen.trackNumber);
|
||||
|
||||
const auto tracks {Track::find(session, params)};
|
||||
const auto tracks{ Track::findIds(session, params) };
|
||||
// conservative behavior: in case of multiple matches: reject
|
||||
if (tracks.results.size() == 1)
|
||||
{
|
||||
@@ -224,21 +220,18 @@ namespace Scrobbling::ListenBrainz
|
||||
scheduleSync(std::chrono::seconds{ 30 });
|
||||
}
|
||||
|
||||
void
|
||||
ListensSynchronizer::enqueListen(const TimedListen& listen)
|
||||
void ListensSynchronizer::enqueListen(const TimedListen& listen)
|
||||
{
|
||||
assert(listen.listenedAt.isValid());
|
||||
enqueListen(listen, listen.listenedAt);
|
||||
}
|
||||
|
||||
void
|
||||
ListensSynchronizer::enqueListenNow(const Scrobbling::Listen& listen)
|
||||
void ListensSynchronizer::enqueListenNow(const Scrobbling::Listen& listen)
|
||||
{
|
||||
enqueListen(listen, {});
|
||||
}
|
||||
|
||||
void
|
||||
ListensSynchronizer::enqueListen(const Scrobbling::Listen& listen, const Wt::WDateTime& timePoint)
|
||||
void ListensSynchronizer::enqueListen(const Scrobbling::Listen& listen, const Wt::WDateTime& timePoint)
|
||||
{
|
||||
Http::ClientPOSTRequestParameters request;
|
||||
request.relativeUrl = "/1/submit-listens";
|
||||
@@ -291,8 +284,7 @@ namespace Scrobbling::ListenBrainz
|
||||
_client.sendPOSTRequest(std::move(request));
|
||||
}
|
||||
|
||||
bool
|
||||
ListensSynchronizer::saveListen(const TimedListen& listen, Database::SyncState scrobblingState)
|
||||
bool ListensSynchronizer::saveListen(const TimedListen& listen, Database::SyncState scrobblingState)
|
||||
{
|
||||
using namespace Database;
|
||||
|
||||
@@ -325,8 +317,7 @@ namespace Scrobbling::ListenBrainz
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ListensSynchronizer::enquePendingListens()
|
||||
void ListensSynchronizer::enquePendingListens()
|
||||
{
|
||||
std::vector<TimedListen> pendingListens;
|
||||
|
||||
@@ -362,8 +353,7 @@ namespace Scrobbling::ListenBrainz
|
||||
enqueListen(pendingListen);
|
||||
}
|
||||
|
||||
ListensSynchronizer::UserContext&
|
||||
ListensSynchronizer::getUserContext(Database::UserId userId)
|
||||
ListensSynchronizer::UserContext& ListensSynchronizer::getUserContext(Database::UserId userId)
|
||||
{
|
||||
assert(_strand.running_in_this_thread());
|
||||
|
||||
@@ -376,8 +366,7 @@ namespace Scrobbling::ListenBrainz
|
||||
return itContext->second;
|
||||
}
|
||||
|
||||
bool
|
||||
ListensSynchronizer::isSyncing() const
|
||||
bool ListensSynchronizer::isSyncing() const
|
||||
{
|
||||
return std::any_of(std::cbegin(_userContexts), std::cend(_userContexts), [](const auto& contextEntry)
|
||||
{
|
||||
@@ -385,8 +374,7 @@ namespace Scrobbling::ListenBrainz
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
ListensSynchronizer::scheduleSync(std::chrono::seconds fromNow)
|
||||
void ListensSynchronizer::scheduleSync(std::chrono::seconds fromNow)
|
||||
{
|
||||
if (_syncListensPeriod.count() == 0 || _maxSyncListenCount == 0)
|
||||
return;
|
||||
@@ -409,8 +397,7 @@ namespace Scrobbling::ListenBrainz
|
||||
}));
|
||||
}
|
||||
|
||||
void
|
||||
ListensSynchronizer::startSync()
|
||||
void ListensSynchronizer::startSync()
|
||||
{
|
||||
LOG(DEBUG) << "Starting sync!";
|
||||
|
||||
@@ -432,8 +419,7 @@ namespace Scrobbling::ListenBrainz
|
||||
scheduleSync(_syncListensPeriod);
|
||||
}
|
||||
|
||||
void
|
||||
ListensSynchronizer::startSync(UserContext& context)
|
||||
void ListensSynchronizer::startSync(UserContext& context)
|
||||
{
|
||||
context.syncing = true;
|
||||
context.listenBrainzUserName = "";
|
||||
@@ -445,8 +431,7 @@ namespace Scrobbling::ListenBrainz
|
||||
enqueValidateToken(context);
|
||||
}
|
||||
|
||||
void
|
||||
ListensSynchronizer::onSyncEnded(UserContext& context)
|
||||
void ListensSynchronizer::onSyncEnded(UserContext& context)
|
||||
{
|
||||
_strand.dispatch([this, &context]
|
||||
{
|
||||
@@ -458,8 +443,7 @@ namespace Scrobbling::ListenBrainz
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
ListensSynchronizer::enqueValidateToken(UserContext& context)
|
||||
void ListensSynchronizer::enqueValidateToken(UserContext& context)
|
||||
{
|
||||
assert(context.listenBrainzUserName.empty());
|
||||
|
||||
@@ -492,8 +476,7 @@ namespace Scrobbling::ListenBrainz
|
||||
_client.sendGETRequest(std::move(request));
|
||||
}
|
||||
|
||||
void
|
||||
ListensSynchronizer::enqueGetListenCount(UserContext& context)
|
||||
void ListensSynchronizer::enqueGetListenCount(UserContext& context)
|
||||
{
|
||||
assert(!context.listenBrainzUserName.empty());
|
||||
|
||||
@@ -529,8 +512,7 @@ namespace Scrobbling::ListenBrainz
|
||||
_client.sendGETRequest(std::move(request));
|
||||
}
|
||||
|
||||
void
|
||||
ListensSynchronizer::enqueGetListens(UserContext& context)
|
||||
void ListensSynchronizer::enqueGetListens(UserContext& context)
|
||||
{
|
||||
assert(!context.listenBrainzUserName.empty());
|
||||
|
||||
@@ -556,8 +538,7 @@ namespace Scrobbling::ListenBrainz
|
||||
_client.sendGETRequest(std::move(request));
|
||||
}
|
||||
|
||||
void
|
||||
ListensSynchronizer::processGetListensResponse(std::string_view msgBody, UserContext& context)
|
||||
void ListensSynchronizer::processGetListensResponse(std::string_view msgBody, UserContext& context)
|
||||
{
|
||||
Database::Session& session{ _db.getTLSSession() };
|
||||
|
||||
|
||||
@@ -204,16 +204,13 @@ namespace API::Subsonic
|
||||
if (!user)
|
||||
throw UserNotAuthorizedError{};
|
||||
|
||||
const auto trackIds{ Track::find(context.dbSession, Track::FindParameters {}.setSortMethod(TrackSortMethod::Random).setRange({0, size})) };
|
||||
const auto tracks{ Track::find(context.dbSession, Track::FindParameters {}.setSortMethod(TrackSortMethod::Random).setRange({0, size})) };
|
||||
|
||||
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||
|
||||
Response::Node& randomSongsNode{ response.createNode("randomSongs") };
|
||||
for (const TrackId trackId : trackIds.results)
|
||||
{
|
||||
const Track::pointer track{ Track::find(context.dbSession, trackId) };
|
||||
for (const Track::pointer& track : tracks.results)
|
||||
randomSongsNode.addArrayChild("song", createSongNode(context, track, user));
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -250,12 +247,9 @@ namespace API::Subsonic
|
||||
params.setClusters({ cluster->getId() });
|
||||
params.setRange({ offset, size });
|
||||
|
||||
auto trackIds{ Track::find(context.dbSession, params) };
|
||||
for (const TrackId trackId : trackIds.results)
|
||||
{
|
||||
const Track::pointer track{ Track::find(context.dbSession, trackId) };
|
||||
const auto tracks{ Track::find(context.dbSession, params) };
|
||||
for (const Track::pointer& track : tracks.results)
|
||||
songsByGenreNode.addArrayChild("song", createSongNode(context, track, user));
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ namespace API::Subsonic
|
||||
params.setRange({ 0, meanTrackCountPerArtist });
|
||||
params.setSortMethod(TrackSortMethod::Random);
|
||||
|
||||
const auto artistTracks{ Track::find(context.dbSession, params) };
|
||||
const auto artistTracks{ Track::findIds(context.dbSession, params) };
|
||||
tracks.insert(std::end(tracks),
|
||||
std::begin(artistTracks.results),
|
||||
std::end(artistTracks.results));
|
||||
@@ -225,7 +225,7 @@ namespace API::Subsonic
|
||||
params.setRange({ 0, meanTrackCountPerRelease });
|
||||
params.setSortMethod(TrackSortMethod::Random);
|
||||
|
||||
const auto releaseTracks{ Track::find(context.dbSession, params) };
|
||||
const auto releaseTracks{ Track::findIds(context.dbSession, params) };
|
||||
tracks.insert(std::end(tracks),
|
||||
std::begin(releaseTracks.results),
|
||||
std::end(releaseTracks.results));
|
||||
@@ -349,12 +349,9 @@ namespace API::Subsonic
|
||||
directoryNode.setAttribute("name", Utils::makeNameFilesystemCompatible(release->getName()));
|
||||
|
||||
const auto tracks{ Track::find(context.dbSession, Track::FindParameters {}.setRelease(*releaseId).setSortMethod(TrackSortMethod::Release)) };
|
||||
for (const TrackId trackId : tracks.results)
|
||||
{
|
||||
const Track::pointer track{ Track::find(context.dbSession, trackId) };
|
||||
for (const Track::pointer& track : tracks.results)
|
||||
directoryNode.addArrayChild("child", createSongNode(context, track, user));
|
||||
}
|
||||
}
|
||||
else
|
||||
throw BadParameterGenericError{ "id" };
|
||||
|
||||
@@ -432,11 +429,8 @@ namespace API::Subsonic
|
||||
Response::Node albumNode{ createAlbumNode(context, release, user, true /* id3 */) };
|
||||
|
||||
const auto tracks{ Track::find(context.dbSession, Track::FindParameters {}.setRelease(id).setSortMethod(TrackSortMethod::Release)) };
|
||||
for (const TrackId trackId : tracks.results)
|
||||
{
|
||||
const Track::pointer track{ Track::find(context.dbSession, trackId) };
|
||||
for (const Track::pointer& track : tracks.results)
|
||||
albumNode.addArrayChild("song", createSongNode(context, track, user));
|
||||
}
|
||||
|
||||
response.addNode("album", std::move(albumNode));
|
||||
|
||||
|
||||
@@ -86,8 +86,7 @@ namespace API::Subsonic
|
||||
params.setKeywords(keywords);
|
||||
params.setRange({ albumOffset, albumCount });
|
||||
|
||||
RangeResults<Release::pointer> releases{ Release::find(context.dbSession, params) };
|
||||
for (const Release::pointer& release : releases.results)
|
||||
for (const Release::pointer& release : Release::find(context.dbSession, params).results)
|
||||
searchResult2Node.addArrayChild("album", createAlbumNode(context, release, user, id3));
|
||||
}
|
||||
|
||||
@@ -97,13 +96,9 @@ namespace API::Subsonic
|
||||
params.setKeywords(keywords);
|
||||
params.setRange({ songOffset, songCount });
|
||||
|
||||
RangeResults<TrackId> trackIds{ Track::find(context.dbSession, params) };
|
||||
for (const TrackId trackId : trackIds.results)
|
||||
{
|
||||
const auto track{ Track::find(context.dbSession, trackId) };
|
||||
for (const Track::pointer& track : Track::find(context.dbSession, params).results)
|
||||
searchResult2Node.addArrayChild("song", createSongNode(context, track, user));
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -110,6 +110,7 @@ namespace API::Subsonic
|
||||
trackResponse.setAttribute("playCount", Listen::getCount(context.dbSession, user->getId(), user->getScrobblingBackend(), track->getId()));
|
||||
trackResponse.setAttribute("path", getTrackPath(track));
|
||||
{
|
||||
// TODO, store this in DB
|
||||
std::error_code ec;
|
||||
const auto fileSize{ std::filesystem::file_size(track->getPath(), ec) };
|
||||
if (!ec)
|
||||
|
||||
+33
-65
@@ -51,8 +51,8 @@
|
||||
#include "ModalManager.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace UserInterface {
|
||||
|
||||
namespace UserInterface
|
||||
{
|
||||
namespace
|
||||
{
|
||||
class CreateTrackListModel : public Wt::WFormModel
|
||||
@@ -235,33 +235,28 @@ PlayQueue::PlayQueue()
|
||||
updateInfo();
|
||||
}
|
||||
|
||||
bool
|
||||
PlayQueue::isRepeatAllSet() const
|
||||
bool PlayQueue::isRepeatAllSet() const
|
||||
{
|
||||
return _repeatBtn->checkState() == Wt::CheckState::Checked;
|
||||
}
|
||||
|
||||
bool
|
||||
PlayQueue::isRadioModeSet() const
|
||||
bool PlayQueue::isRadioModeSet() const
|
||||
{
|
||||
return _radioBtn->checkState() == Wt::CheckState::Checked;
|
||||
}
|
||||
|
||||
Database::TrackList::pointer
|
||||
PlayQueue::getQueue() const
|
||||
Database::TrackList::pointer PlayQueue::getQueue() const
|
||||
{
|
||||
return Database::TrackList::find(LmsApp->getDbSession(), _queueId);
|
||||
}
|
||||
|
||||
bool
|
||||
PlayQueue::isFull() const
|
||||
bool PlayQueue::isFull() const
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
return getQueue()->getCount() == getCapacity();
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::clearTracks()
|
||||
void PlayQueue::clearTracks()
|
||||
{
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createUniqueTransaction() };
|
||||
@@ -273,8 +268,7 @@ PlayQueue::clearTracks()
|
||||
updateInfo();
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::stop()
|
||||
void PlayQueue::stop()
|
||||
{
|
||||
updateCurrentTrack(false);
|
||||
_trackPos.reset();
|
||||
@@ -282,8 +276,7 @@ PlayQueue::stop()
|
||||
trackUnselected.emit();
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::loadTrack(std::size_t pos, bool play)
|
||||
void PlayQueue::loadTrack(std::size_t pos, bool play)
|
||||
{
|
||||
updateCurrentTrack(false);
|
||||
|
||||
@@ -323,8 +316,7 @@ PlayQueue::loadTrack(std::size_t pos, bool play)
|
||||
trackSelected.emit(trackId, play, replayGain ? *replayGain : 0);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::playPrevious()
|
||||
void PlayQueue::playPrevious()
|
||||
{
|
||||
if (!_trackPos)
|
||||
return;
|
||||
@@ -335,8 +327,7 @@ PlayQueue::playPrevious()
|
||||
loadTrack(*_trackPos - 1, true);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::playNext()
|
||||
void PlayQueue::playNext()
|
||||
{
|
||||
if (!_trackPos)
|
||||
{
|
||||
@@ -347,21 +338,18 @@ PlayQueue::playNext()
|
||||
loadTrack(*_trackPos + 1, true);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::onPlaybackEnded()
|
||||
void PlayQueue::onPlaybackEnded()
|
||||
{
|
||||
playNext();
|
||||
}
|
||||
|
||||
std::size_t
|
||||
PlayQueue::getCount()
|
||||
std::size_t PlayQueue::getCount()
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
return getQueue()->getCount();
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::initTrackLists()
|
||||
void PlayQueue::initTrackLists()
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createUniqueTransaction() };
|
||||
|
||||
@@ -384,8 +372,7 @@ PlayQueue::initTrackLists()
|
||||
_queueId = queue->getId();
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::updateInfo()
|
||||
void PlayQueue::updateInfo()
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
|
||||
@@ -396,8 +383,7 @@ PlayQueue::updateInfo()
|
||||
trackCountChanged.emit(trackCount);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::updateCurrentTrack(bool selected)
|
||||
void PlayQueue::updateCurrentTrack(bool selected)
|
||||
{
|
||||
if (!_trackPos || *_trackPos >= static_cast<std::size_t>(_entriesContainer->getCount()))
|
||||
return;
|
||||
@@ -409,8 +395,7 @@ PlayQueue::updateCurrentTrack(bool selected)
|
||||
entry->toggleStyleClass("Lms-entry-playing", selected);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::enqueueTracks(const std::vector<Database::TrackId>& trackIds)
|
||||
void PlayQueue::enqueueTracks(const std::vector<Database::TrackId>& trackIds)
|
||||
{
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createUniqueTransaction() };
|
||||
@@ -438,8 +423,7 @@ PlayQueue::enqueueTracks(const std::vector<Database::TrackId>& trackIds)
|
||||
_entriesContainer->setHasMore();
|
||||
}
|
||||
|
||||
std::vector<Database::TrackId>
|
||||
PlayQueue::getAndClearNextTracks()
|
||||
std::vector<Database::TrackId> PlayQueue::getAndClearNextTracks()
|
||||
{
|
||||
std::vector<Database::TrackId> tracks;
|
||||
|
||||
@@ -468,22 +452,19 @@ PlayQueue::getAndClearNextTracks()
|
||||
return tracks;
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::play(const std::vector<Database::TrackId>& trackIds)
|
||||
void PlayQueue::play(const std::vector<Database::TrackId>& trackIds)
|
||||
{
|
||||
playAtIndex(trackIds, 0);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::playNext(const std::vector<Database::TrackId>& trackIds)
|
||||
void PlayQueue::playNext(const std::vector<Database::TrackId>& trackIds)
|
||||
{
|
||||
std::vector<Database::TrackId> nextTracks{ getAndClearNextTracks() };
|
||||
nextTracks.insert(std::cbegin(nextTracks), std::cbegin(trackIds), std::cend(trackIds));
|
||||
playOrAddLast(nextTracks);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::playShuffled(const std::vector<Database::TrackId>& trackIds)
|
||||
void PlayQueue::playShuffled(const std::vector<Database::TrackId>& trackIds)
|
||||
{
|
||||
clearTracks();
|
||||
std::vector<Database::TrackId> shuffledTrackIds{ trackIds };
|
||||
@@ -492,24 +473,21 @@ PlayQueue::playShuffled(const std::vector<Database::TrackId>& trackIds)
|
||||
loadTrack(0, true);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::playOrAddLast(const std::vector<Database::TrackId>& trackIds)
|
||||
void PlayQueue::playOrAddLast(const std::vector<Database::TrackId>& trackIds)
|
||||
{
|
||||
enqueueTracks(trackIds);
|
||||
if (!_isTrackSelected)
|
||||
loadTrack(0, true);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::playAtIndex(const std::vector<Database::TrackId>& trackIds, std::size_t index)
|
||||
void PlayQueue::playAtIndex(const std::vector<Database::TrackId>& trackIds, std::size_t index)
|
||||
{
|
||||
clearTracks();
|
||||
enqueueTracks(trackIds);
|
||||
loadTrack(index, true);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::addSome()
|
||||
void PlayQueue::addSome()
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
|
||||
@@ -519,8 +497,7 @@ PlayQueue::addSome()
|
||||
addEntry(tracklistEntry);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::addEntry(const Database::TrackListEntry::pointer& tracklistEntry)
|
||||
void PlayQueue::addEntry(const Database::TrackListEntry::pointer& tracklistEntry)
|
||||
{
|
||||
const Database::TrackListEntryId tracklistEntryId{ tracklistEntry->getId() };
|
||||
const auto track{ tracklistEntry->getTrack() };
|
||||
@@ -625,8 +602,7 @@ PlayQueue::addEntry(const Database::TrackListEntry::pointer& tracklistEntry)
|
||||
->setLink(Wt::WLink{ std::make_unique<DownloadTrackResource>(trackId) });
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::enqueueRadioTracksIfNeeded()
|
||||
void PlayQueue::enqueueRadioTracksIfNeeded()
|
||||
{
|
||||
if (!isRadioModeSet())
|
||||
return;
|
||||
@@ -646,15 +622,13 @@ PlayQueue::enqueueRadioTracksIfNeeded()
|
||||
enqueueRadioTracks();
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::enqueueRadioTracks()
|
||||
void PlayQueue::enqueueRadioTracks()
|
||||
{
|
||||
std::vector<Database::TrackId> trackIds = Service<Recommendation::IPlaylistGeneratorService>::get()->extendPlaylist(_queueId, 15);
|
||||
enqueueTracks(trackIds);
|
||||
}
|
||||
|
||||
std::optional<float>
|
||||
PlayQueue::getReplayGain(std::size_t pos, const Database::Track::pointer& track) const
|
||||
std::optional<float> PlayQueue::getReplayGain(std::size_t pos, const Database::Track::pointer& track) const
|
||||
{
|
||||
const auto& settings{ LmsApp->getMediaPlayer().getSettings() };
|
||||
if (!settings)
|
||||
@@ -707,8 +681,7 @@ PlayQueue::getReplayGain(std::size_t pos, const Database::Track::pointer& track)
|
||||
return settings->replayGain.preAmpGainIfNoInfo;
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::saveAsTrackList()
|
||||
void PlayQueue::saveAsTrackList()
|
||||
{
|
||||
auto modal{ std::make_unique<Template>(Wt::WString::tr("Lms.PlayQueue.template.save-as-tracklist")) };
|
||||
modal->addFunction("id", &Wt::WTemplate::Functions::id);
|
||||
@@ -795,8 +768,7 @@ PlayQueue::saveAsTrackList()
|
||||
LmsApp->getModalManager().show(std::move(modal));
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::exportToNewTrackList(const Wt::WString& name)
|
||||
void PlayQueue::exportToNewTrackList(const Wt::WString& name)
|
||||
{
|
||||
using namespace Database;
|
||||
|
||||
@@ -812,8 +784,7 @@ PlayQueue::exportToNewTrackList(const Wt::WString& name)
|
||||
exportToTrackList(trackListId);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::exportToTrackList(Database::TrackListId trackListId)
|
||||
void PlayQueue::exportToTrackList(Database::TrackListId trackListId)
|
||||
{
|
||||
using namespace Database;
|
||||
|
||||
@@ -829,10 +800,7 @@ PlayQueue::exportToTrackList(Database::TrackListId trackListId)
|
||||
params.setSortMethod(TrackSortMethod::TrackList);
|
||||
|
||||
const auto tracks{ Track::find(session, params) };
|
||||
for (const TrackId trackId : tracks.results)
|
||||
session.create<TrackListEntry>(Track::find(session, trackId), trackList);
|
||||
for (const Track::pointer& track : tracks.results)
|
||||
session.create<TrackListEntry>(track, trackList);
|
||||
}
|
||||
|
||||
|
||||
} // namespace UserInterface
|
||||
|
||||
|
||||
@@ -369,12 +369,12 @@ Artist::addSomeNonReleaseTracks()
|
||||
params.setNonRelease(true);
|
||||
|
||||
const auto tracks {Track::find(LmsApp->getDbSession(), params)};
|
||||
for (const TrackId trackId : tracks.results)
|
||||
for (const Track::pointer& track : tracks.results)
|
||||
{
|
||||
// TODO handle this with range
|
||||
if (_trackContainer->getCount() == _tracksMaxCount)
|
||||
break;
|
||||
|
||||
const Track::pointer track {Track::find(LmsApp->getDbSession(), trackId)};
|
||||
_trackContainer->add(TrackListHelpers::createEntry(track, _playQueueController, _filters));
|
||||
|
||||
areTracksAdded = true;
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
namespace UserInterface
|
||||
{
|
||||
|
||||
static
|
||||
std::vector<Database::TrackId>
|
||||
getArtistsTracks(Database::Session& session, const std::vector<Database::ArtistId>& artistsId, const std::vector<Database::ClusterId>& clusters, std::size_t maxTrackCount)
|
||||
namespace
|
||||
{
|
||||
std::vector<Database::TrackId> getArtistsTracks(Database::Session& session, const std::vector<Database::ArtistId>& artistsId, const std::vector<Database::ClusterId>& clusters, std::size_t maxTrackCount)
|
||||
{
|
||||
assert(maxTrackCount);
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace UserInterface
|
||||
params.setClusters(clusters);
|
||||
params.setRange({ 0, maxTrackCount - res.size() });
|
||||
|
||||
const auto tracks {Database::Track::find(session, params)};
|
||||
const auto tracks{ Database::Track::findIds(session, params) };
|
||||
|
||||
res.reserve(res.size() + tracks.results.size());
|
||||
res.insert(std::end(res), std::cbegin(tracks.results), std::cend(tracks.results));
|
||||
@@ -59,9 +59,7 @@ namespace UserInterface
|
||||
return res;
|
||||
}
|
||||
|
||||
static
|
||||
std::vector<Database::TrackId>
|
||||
getReleasesTracks(Database::Session& session, const std::vector<Database::ReleaseId>& releasesId, const std::vector<Database::ClusterId>& clusters, std::size_t maxTrackCount)
|
||||
std::vector<Database::TrackId> getReleasesTracks(Database::Session& session, const std::vector<Database::ReleaseId>& releasesId, const std::vector<Database::ClusterId>& clusters, std::size_t maxTrackCount)
|
||||
{
|
||||
using namespace Database;
|
||||
assert(maxTrackCount);
|
||||
@@ -78,7 +76,7 @@ namespace UserInterface
|
||||
params.setClusters(clusters);
|
||||
params.setRange({ 0, maxTrackCount - res.size() });
|
||||
|
||||
const auto tracks {Database::Track::find(session, params)};
|
||||
const auto tracks{ Database::Track::findIds(session, params) };
|
||||
|
||||
res.reserve(res.size() + tracks.results.size());
|
||||
res.insert(std::end(res), std::cbegin(tracks.results), std::cend(tracks.results));
|
||||
@@ -90,9 +88,7 @@ namespace UserInterface
|
||||
return res;
|
||||
}
|
||||
|
||||
static
|
||||
std::vector<Database::TrackId>
|
||||
getTrackListTracks(Database::Session& session, Database::TrackListId trackListId, const std::vector<Database::ClusterId>& clusters, std::size_t maxTrackCount)
|
||||
std::vector<Database::TrackId> getTrackListTracks(Database::Session& session, Database::TrackListId trackListId, const std::vector<Database::ClusterId>& clusters, std::size_t maxTrackCount)
|
||||
{
|
||||
using namespace Database;
|
||||
assert(maxTrackCount);
|
||||
@@ -106,7 +102,8 @@ namespace UserInterface
|
||||
params.setSortMethod(TrackSortMethod::TrackList);
|
||||
params.setDistinct(false);
|
||||
|
||||
return Database::Track::find(session, params).results;
|
||||
return Database::Track::findIds(session, params).results;
|
||||
}
|
||||
}
|
||||
|
||||
PlayQueueController::PlayQueueController(Filters& filters, PlayQueue& playQueue)
|
||||
@@ -115,22 +112,19 @@ namespace UserInterface
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueueController::processCommand(Command command, const std::vector<Database::ArtistId>& artistIds)
|
||||
void PlayQueueController::processCommand(Command command, const std::vector<Database::ArtistId>& artistIds)
|
||||
{
|
||||
const std::vector<Database::TrackId> tracks{ getArtistsTracks(LmsApp->getDbSession(), artistIds, _filters.getClusterIds(), _maxTrackCountToEnqueue) };
|
||||
processCommand(command, tracks);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueueController::processCommand(Command command, const std::vector<Database::ReleaseId>& releaseIds)
|
||||
void PlayQueueController::processCommand(Command command, const std::vector<Database::ReleaseId>& releaseIds)
|
||||
{
|
||||
const std::vector<Database::TrackId> tracks{ getReleasesTracks(LmsApp->getDbSession(), releaseIds, _filters.getClusterIds(), _maxTrackCountToEnqueue) };
|
||||
processCommand(command, tracks);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueueController::processCommand(Command command, const std::vector<Database::TrackId>& trackIds)
|
||||
void PlayQueueController::processCommand(Command command, const std::vector<Database::TrackId>& trackIds)
|
||||
{
|
||||
// consider things are already filtered here, and _maxTrackCount honored playqueue side...
|
||||
switch (command)
|
||||
@@ -150,15 +144,13 @@ namespace UserInterface
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueueController::processCommand(Command command, Database::TrackListId trackListId)
|
||||
void PlayQueueController::processCommand(Command command, Database::TrackListId trackListId)
|
||||
{
|
||||
const std::vector<Database::TrackId> tracks{ getTrackListTracks(LmsApp->getDbSession(), trackListId, _filters.getClusterIds(), _maxTrackCountToEnqueue) };
|
||||
processCommand(command, tracks);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueueController::playTrackInRelease(Database::TrackId trackId)
|
||||
void PlayQueueController::playTrackInRelease(Database::TrackId trackId)
|
||||
{
|
||||
Database::ReleaseId releaseId;
|
||||
{
|
||||
|
||||
@@ -50,10 +50,11 @@
|
||||
|
||||
using namespace Database;
|
||||
|
||||
namespace UserInterface {
|
||||
|
||||
void
|
||||
showReleaseInfoModal(Database::ReleaseId releaseId)
|
||||
namespace UserInterface
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void showReleaseInfoModal(Database::ReleaseId releaseId)
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
|
||||
@@ -137,12 +138,8 @@ showReleaseInfoModal(Database::ReleaseId releaseId)
|
||||
}
|
||||
|
||||
// TODO: save in DB and mean all this
|
||||
for (TrackId trackId : Track::find(LmsApp->getDbSession(), Track::FindParameters {}.setRelease(releaseId).setRange(Range {0, 1})).results)
|
||||
for (const Track::pointer& track : Track::find(LmsApp->getDbSession(), Track::FindParameters{}.setRelease(releaseId).setRange(Range{ 0, 1 })).results)
|
||||
{
|
||||
const Track::pointer track {Track::find(LmsApp->getDbSession(), trackId)};
|
||||
if (!track)
|
||||
continue;
|
||||
|
||||
if (const auto audioFile{ Av::parseAudioFile(track->getPath()) })
|
||||
{
|
||||
const std::optional<Av::StreamInfo> audioStream{ audioFile->getBestStreamInfo() };
|
||||
@@ -169,6 +166,25 @@ showReleaseInfoModal(Database::ReleaseId releaseId)
|
||||
LmsApp->getModalManager().show(std::move(releaseInfo));
|
||||
}
|
||||
|
||||
std::optional<ReleaseId> extractReleaseIdFromInternalPath()
|
||||
{
|
||||
if (wApp->internalPathMatches("/release/mbid/"))
|
||||
{
|
||||
const auto mbid{ UUID::fromString(wApp->internalPathNextPart("/release/mbid/")) };
|
||||
if (mbid)
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
if (const Database::Release::pointer release{ Database::Release::find(LmsApp->getDbSession(), *mbid) })
|
||||
return release->getId();
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return StringUtils::readAs<ReleaseId::ValueType>(wApp->internalPathNextPart("/release/"));
|
||||
}
|
||||
}
|
||||
|
||||
Release::Release(Filters& filters, PlayQueueController& playQueueController)
|
||||
: Template{ Wt::WString::tr("Lms.Explore.Release.template") }
|
||||
, _filters{ filters }
|
||||
@@ -191,29 +207,7 @@ Release::Release(Filters& filters, PlayQueueController& playQueueController)
|
||||
refreshView();
|
||||
}
|
||||
|
||||
static
|
||||
std::optional<ReleaseId>
|
||||
extractReleaseIdFromInternalPath()
|
||||
{
|
||||
if (wApp->internalPathMatches("/release/mbid/"))
|
||||
{
|
||||
const auto mbid {UUID::fromString(wApp->internalPathNextPart("/release/mbid/"))};
|
||||
if (mbid)
|
||||
{
|
||||
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
|
||||
if (const Database::Release::pointer release {Database::Release::find(LmsApp->getDbSession(), *mbid)})
|
||||
return release->getId();
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return StringUtils::readAs<ReleaseId::ValueType>(wApp->internalPathNextPart("/release/"));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Release::refreshView()
|
||||
void Release::refreshView()
|
||||
{
|
||||
if (!wApp->internalPathMatches("/release/"))
|
||||
return;
|
||||
@@ -379,11 +373,9 @@ Release::refreshView()
|
||||
params.setSortMethod(Database::TrackSortMethod::Release);
|
||||
params.setClusters(_filters.getClusterIds());
|
||||
|
||||
const auto tracks {Database::Track::find(LmsApp->getDbSession(), params)};
|
||||
for (const Database::TrackId trackId : tracks.results)
|
||||
for (const Database::Track::pointer& track : Database::Track::find(LmsApp->getDbSession(), params).results)
|
||||
{
|
||||
const Database::Track::pointer track {Database::Track::find(LmsApp->getDbSession(), trackId)};
|
||||
|
||||
const Database::TrackId trackId{ track->getId() };
|
||||
const auto discNumber{ track->getDiscNumber() };
|
||||
|
||||
Wt::WContainerWidget* container;
|
||||
@@ -477,8 +469,7 @@ Release::refreshView()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Release::refreshReleaseArtists(const Database::Release::pointer& release)
|
||||
void Release::refreshReleaseArtists(const Database::Release::pointer& release)
|
||||
{
|
||||
auto container{ Utils::createArtistsAnchorsForRelease(release) };
|
||||
if (container)
|
||||
@@ -488,8 +479,7 @@ Release::refreshReleaseArtists(const Database::Release::pointer& release)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Release::refreshCopyright(const Database::Release::pointer& release)
|
||||
void Release::refreshCopyright(const Database::Release::pointer& release)
|
||||
{
|
||||
std::optional<std::string> copyright{ release->getCopyright() };
|
||||
std::optional<std::string> copyrightURL{ release->getCopyrightURL() };
|
||||
@@ -516,8 +506,7 @@ Release::refreshCopyright(const Database::Release::pointer& release)
|
||||
bindString("copyright", Wt::WString::fromUTF8(*copyright), Wt::TextFormat::Plain);
|
||||
}
|
||||
|
||||
void
|
||||
Release::refreshLinks(const Database::Release::pointer& release)
|
||||
void Release::refreshLinks(const Database::Release::pointer& release)
|
||||
{
|
||||
const auto mbid{ release->getMBID() };
|
||||
if (mbid)
|
||||
@@ -527,8 +516,7 @@ Release::refreshLinks(const Database::Release::pointer& release)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Release::refreshSimilarReleases(const std::vector<ReleaseId>& similarReleasesId)
|
||||
void Release::refreshSimilarReleases(const std::vector<ReleaseId>& similarReleasesId)
|
||||
{
|
||||
if (similarReleasesId.empty())
|
||||
return;
|
||||
@@ -547,4 +535,3 @@ Release::refreshSimilarReleases(const std::vector<ReleaseId>& similarReleasesId)
|
||||
}
|
||||
|
||||
} // namespace UserInterface
|
||||
|
||||
|
||||
@@ -35,8 +35,7 @@ namespace UserInterface
|
||||
{
|
||||
using namespace Database;
|
||||
|
||||
RangeResults<TrackId>
|
||||
TrackCollector::get(Range range)
|
||||
RangeResults<TrackId> TrackCollector::get(Range range)
|
||||
{
|
||||
Feedback::IFeedbackService& feedbackService{ *Service<Feedback::IFeedbackService>::get() };
|
||||
Scrobbling::IScrobblingService& scrobblingService{ *Service<Scrobbling::IScrobblingService>::get() };
|
||||
@@ -73,7 +72,7 @@ namespace UserInterface
|
||||
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
tracks = Track::find(LmsApp->getDbSession(), params);
|
||||
tracks = Track::findIds(LmsApp->getDbSession(), params);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -87,7 +86,7 @@ namespace UserInterface
|
||||
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
tracks = Track::find(LmsApp->getDbSession(), params);
|
||||
tracks = Track::findIds(LmsApp->getDbSession(), params);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -100,7 +99,7 @@ namespace UserInterface
|
||||
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
tracks = Track::find(LmsApp->getDbSession(), params);
|
||||
tracks = Track::findIds(LmsApp->getDbSession(), params);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -112,8 +111,7 @@ namespace UserInterface
|
||||
return tracks;
|
||||
}
|
||||
|
||||
RangeResults<TrackId>
|
||||
TrackCollector::getRandomTracks(Range range)
|
||||
RangeResults<TrackId> TrackCollector::getRandomTracks(Range range)
|
||||
{
|
||||
assert(getMode() == Mode::Random);
|
||||
|
||||
@@ -126,7 +124,7 @@ namespace UserInterface
|
||||
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
_randomTracks = Track::find(LmsApp->getDbSession(), params);
|
||||
_randomTracks = Track::findIds(LmsApp->getDbSession(), params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,4 +132,3 @@ namespace UserInterface
|
||||
}
|
||||
|
||||
} // ns UserInterface
|
||||
|
||||
|
||||
@@ -39,20 +39,18 @@
|
||||
#include "ModalManager.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace UserInterface
|
||||
{
|
||||
using namespace Database;
|
||||
|
||||
namespace
|
||||
{
|
||||
static
|
||||
std::optional<TrackListId>
|
||||
extractTrackListIdFromInternalPath()
|
||||
std::optional<TrackListId> extractTrackListIdFromInternalPath()
|
||||
{
|
||||
return StringUtils::readAs<TrackListId::ValueType>(wApp->internalPathNextPart("/tracklist/"));
|
||||
}
|
||||
}
|
||||
|
||||
namespace UserInterface
|
||||
{
|
||||
TrackList::TrackList(Filters& filters, PlayQueueController& playQueueController)
|
||||
: Template{ Wt::WString::tr("Lms.Explore.TrackList.template") }
|
||||
, _filters{ filters }
|
||||
@@ -74,8 +72,7 @@ namespace UserInterface
|
||||
refreshView();
|
||||
}
|
||||
|
||||
void
|
||||
TrackList::refreshView()
|
||||
void TrackList::refreshView()
|
||||
{
|
||||
if (!wApp->internalPathMatches("/tracklist/"))
|
||||
return;
|
||||
@@ -181,8 +178,7 @@ namespace UserInterface
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
TrackList::addSome()
|
||||
void TrackList::addSome()
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
|
||||
@@ -193,12 +189,8 @@ namespace UserInterface
|
||||
params.setRange({ static_cast<std::size_t>(_container->getCount()), _batchSize });
|
||||
params.setDistinct(false);
|
||||
|
||||
const auto trackIds {Database::Track::find(LmsApp->getDbSession(), params)};
|
||||
for (const TrackId trackId : trackIds.results)
|
||||
{
|
||||
if (const Track::pointer track {Track::find(LmsApp->getDbSession(), trackId)})
|
||||
for (const Track::pointer& track : Database::Track::find(LmsApp->getDbSession(), params).results)
|
||||
_container->add(TrackListHelpers::createEntry(track, _playQueueController, _filters));
|
||||
}
|
||||
}
|
||||
} // namespace UserInterface
|
||||
|
||||
|
||||
@@ -19,10 +19,6 @@
|
||||
|
||||
#include "DownloadResource.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <Wt/Http/Response.h>
|
||||
#include <Wt/WDateTime.h>
|
||||
|
||||
@@ -38,15 +34,15 @@
|
||||
|
||||
#define LOG(level) LMS_LOG(UI, level) << "Download resource: "
|
||||
|
||||
namespace UserInterface {
|
||||
namespace UserInterface
|
||||
{
|
||||
|
||||
DownloadResource::~DownloadResource()
|
||||
{
|
||||
beingDeleted();
|
||||
}
|
||||
|
||||
void
|
||||
DownloadResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Response& response)
|
||||
void DownloadResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Response& response)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -74,16 +70,14 @@ DownloadResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Resp
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
std::string
|
||||
getArtistPathName(Database::Artist::pointer artist)
|
||||
namespace
|
||||
{
|
||||
std::string getArtistPathName(Database::Artist::pointer artist)
|
||||
{
|
||||
return StringUtils::replaceInString(artist->getName(), "/", "_");
|
||||
}
|
||||
|
||||
static
|
||||
std::string
|
||||
getReleaseArtistPathName(Database::Release::pointer release)
|
||||
std::string getReleaseArtistPathName(Database::Release::pointer release)
|
||||
{
|
||||
std::string releaseArtistName;
|
||||
|
||||
@@ -103,9 +97,7 @@ getReleaseArtistPathName(Database::Release::pointer release)
|
||||
return releaseArtistName;
|
||||
}
|
||||
|
||||
static
|
||||
std::string
|
||||
getReleasePathName(Database::Release::pointer release)
|
||||
std::string getReleasePathName(Database::Release::pointer release)
|
||||
{
|
||||
std::string releaseName;
|
||||
|
||||
@@ -115,12 +107,11 @@ getReleasePathName(Database::Release::pointer release)
|
||||
|
||||
return releaseName;
|
||||
}
|
||||
}
|
||||
|
||||
namespace details
|
||||
{
|
||||
static
|
||||
std::string
|
||||
getTrackPathName(Database::Track::pointer track)
|
||||
std::string getTrackPathName(Database::Track::pointer track)
|
||||
{
|
||||
std::ostringstream fileName;
|
||||
|
||||
@@ -134,16 +125,12 @@ namespace details
|
||||
return fileName.str();
|
||||
}
|
||||
|
||||
static
|
||||
std::string
|
||||
getTrackListPathName(Database::TrackList::pointer trackList)
|
||||
std::string getTrackListPathName(Database::TrackList::pointer trackList)
|
||||
{
|
||||
return StringUtils::replaceInString(trackList->getName(), "/", "_");
|
||||
}
|
||||
|
||||
static
|
||||
std::unique_ptr<Zip::IZipper>
|
||||
createZipper(const std::vector<Database::Track::pointer>& tracks)
|
||||
std::unique_ptr<Zip::IZipper> createZipper(const std::vector<Database::Track::pointer>& tracks)
|
||||
{
|
||||
if (tracks.empty())
|
||||
return {};
|
||||
@@ -183,19 +170,12 @@ DownloadArtistResource::DownloadArtistResource(Database::ArtistId artistId)
|
||||
suggestFileName(getArtistPathName(artist) + ".zip");
|
||||
}
|
||||
|
||||
std::unique_ptr<Zip::IZipper>
|
||||
DownloadArtistResource::createZipper()
|
||||
std::unique_ptr<Zip::IZipper> DownloadArtistResource::createZipper()
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
|
||||
const auto trackResults{ Database::Track::find(LmsApp->getDbSession(), Database::Track::FindParameters {}.setArtist(_artistId).setSortMethod(Database::TrackSortMethod::DateDescAndRelease)) };
|
||||
std::vector<Database::Track::pointer> tracks;
|
||||
tracks.reserve(trackResults.results.size());
|
||||
|
||||
for (const Database::TrackId trackId : trackResults.results)
|
||||
tracks.push_back(Database::Track::find(LmsApp->getDbSession(), trackId));
|
||||
|
||||
return details::createZipper(tracks);
|
||||
return details::createZipper(trackResults.results);
|
||||
}
|
||||
|
||||
DownloadReleaseResource::DownloadReleaseResource(Database::ReleaseId releaseId)
|
||||
@@ -209,20 +189,14 @@ DownloadReleaseResource::DownloadReleaseResource(Database::ReleaseId releaseId)
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<Zip::IZipper>
|
||||
DownloadReleaseResource::createZipper()
|
||||
std::unique_ptr<Zip::IZipper> DownloadReleaseResource::createZipper()
|
||||
{
|
||||
using namespace Database;
|
||||
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
|
||||
auto trackResults {Track::find(LmsApp->getDbSession(), Track::FindParameters {}.setRelease(_releaseId).setSortMethod(TrackSortMethod::Release))};
|
||||
|
||||
std::vector<Track::pointer> tracks;
|
||||
tracks.reserve(trackResults.results.size());
|
||||
std::transform(std::cbegin(trackResults.results), std::cend(trackResults.results), std::back_inserter(tracks), [](TrackId trackId){ return Track::find(LmsApp->getDbSession(), trackId); });
|
||||
|
||||
return details::createZipper(tracks);
|
||||
auto tracks{ Track::find(LmsApp->getDbSession(), Track::FindParameters {}.setRelease(_releaseId).setSortMethod(TrackSortMethod::Release)) };
|
||||
return details::createZipper(tracks.results);
|
||||
}
|
||||
|
||||
DownloadTrackResource::DownloadTrackResource(Database::TrackId trackId)
|
||||
@@ -235,8 +209,7 @@ DownloadTrackResource::DownloadTrackResource(Database::TrackId trackId)
|
||||
suggestFileName(details::getTrackPathName(track) + ".zip");
|
||||
}
|
||||
|
||||
std::unique_ptr<Zip::IZipper>
|
||||
DownloadTrackResource::createZipper()
|
||||
std::unique_ptr<Zip::IZipper> DownloadTrackResource::createZipper()
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
|
||||
@@ -260,21 +233,15 @@ DownloadTrackListResource::DownloadTrackListResource(Database::TrackListId track
|
||||
suggestFileName(details::getTrackListPathName(trackList) + ".zip");
|
||||
}
|
||||
|
||||
std::unique_ptr<Zip::IZipper>
|
||||
DownloadTrackListResource::createZipper()
|
||||
std::unique_ptr<Zip::IZipper> DownloadTrackListResource::createZipper()
|
||||
{
|
||||
using namespace Database;
|
||||
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
|
||||
|
||||
Track::FindParameters params;
|
||||
params.setTrackList(_trackListId);
|
||||
const auto trackResults {Track::find(LmsApp->getDbSession(), params)};
|
||||
|
||||
std::vector<Track::pointer> tracks;
|
||||
tracks.reserve(trackResults.results.size());
|
||||
std::transform(std::cbegin(trackResults.results), std::cend(trackResults.results), std::back_inserter(tracks), [](TrackId trackId){ return Track::find(LmsApp->getDbSession(), trackId); });
|
||||
|
||||
return details::createZipper(tracks);
|
||||
const auto tracks{ Track::find(LmsApp->getDbSession(), params) };
|
||||
return details::createZipper(tracks.results);
|
||||
}
|
||||
|
||||
} // namespace UserInterface
|
||||
|
||||
@@ -43,7 +43,7 @@ dumpTrackCovers(Database::Session& session, Image::ImageSize width)
|
||||
RangeResults<Database::TrackId> trackIds;
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
trackIds = Database::Track::find(session, Database::Track::FindParameters {});
|
||||
trackIds = Database::Track::findIds(session, Database::Track::FindParameters {});
|
||||
}
|
||||
|
||||
for (const Database::TrackId trackId : trackIds.results)
|
||||
|
||||
@@ -38,14 +38,12 @@
|
||||
|
||||
using namespace Database;
|
||||
|
||||
static
|
||||
void
|
||||
dumpTracksRecommendation(Session session, Recommendation::IRecommendationService& recommendationService, unsigned maxSimilarityCount)
|
||||
static void dumpTracksRecommendation(Session session, Recommendation::IRecommendationService& recommendationService, unsigned maxSimilarityCount)
|
||||
{
|
||||
const RangeResults<TrackId> trackIds{ [&]
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
return Track::find(session, Track::FindParameters {});
|
||||
return Track::findIds(session, Track::FindParameters{});
|
||||
}() };
|
||||
|
||||
std::cout << "*** Tracks (" << trackIds.results.size() << ") ***" << std::endl;
|
||||
@@ -74,9 +72,7 @@ dumpTracksRecommendation(Session session, Recommendation::IRecommendationService
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
dumpReleasesRecommendation(Session session, Recommendation::IRecommendationService& recommendationService, unsigned maxSimilarityCount)
|
||||
static void dumpReleasesRecommendation(Session session, Recommendation::IRecommendationService& recommendationService, unsigned maxSimilarityCount)
|
||||
{
|
||||
const RangeResults<ReleaseId> releaseIds{ std::invoke([&]
|
||||
{
|
||||
@@ -101,9 +97,7 @@ dumpReleasesRecommendation(Session session, Recommendation::IRecommendationServi
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
dumpArtistsRecommendation(Session session, Recommendation::IRecommendationService& recommendationService, unsigned maxSimilarityCount)
|
||||
static void dumpArtistsRecommendation(Session session, Recommendation::IRecommendationService& recommendationService, unsigned maxSimilarityCount)
|
||||
{
|
||||
const RangeResults<ArtistId> artistIds = std::invoke([&]()
|
||||
{
|
||||
@@ -130,7 +124,6 @@ dumpArtistsRecommendation(Session session, Recommendation::IRecommendationServic
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
try
|
||||
|
||||
Reference in New Issue
Block a user