Added relative file path+file size in DB
This commit is contained in:
@@ -34,7 +34,7 @@ namespace lms::db
|
||||
{
|
||||
namespace
|
||||
{
|
||||
static constexpr Version LMS_DATABASE_VERSION{ 54 };
|
||||
static constexpr Version LMS_DATABASE_VERSION{ 55 };
|
||||
}
|
||||
|
||||
VersionInfo::VersionInfo()
|
||||
@@ -430,6 +430,18 @@ SELECT
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV54(Session& session)
|
||||
{
|
||||
// Add file size + relative file path
|
||||
session.getDboSession()->execute("ALTER TABLE track RENAME COLUMN file_path TO absolute_file_path");
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD file_size BIGINT NOT NULL DEFAULT(0)");
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD relative_file_path TEXT NOT NULL DEFAULT ''");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
|
||||
void doDbMigration(Session& session)
|
||||
{
|
||||
static const std::string outdatedMsg{ "Outdated database, please rebuild it (delete the .db file and restart)" };
|
||||
@@ -461,6 +473,7 @@ SELECT
|
||||
{51, migrateFromV51},
|
||||
{52, migrateFromV52},
|
||||
{53, migrateFromV53},
|
||||
{54, migrateFromV54},
|
||||
};
|
||||
|
||||
{
|
||||
@@ -487,6 +500,7 @@ SELECT
|
||||
|
||||
while (version < LMS_DATABASE_VERSION)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "MigrationStep");
|
||||
LMS_LOG(DB, INFO, "Migrating database from version " << version << " to " << version + 1 << "...");
|
||||
|
||||
auto itMigrationFunc{ migrationFunctions.find(version) };
|
||||
|
||||
@@ -243,7 +243,7 @@ namespace lms::db
|
||||
return utils::fetchQueryResults<Release::pointer>(session.getDboSession()->query<Wt::Dbo::ptr<Release>>("SELECT DISTINCT r from release r")
|
||||
.join("track t ON t.release_id = r.id")
|
||||
.where("r.name = ?").bind(std::string(name, 0, _maxNameLength))
|
||||
.where("t.file_path LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind(utils::escapeLikeKeyword(releaseDirectory.string()) + "%"));
|
||||
.where("t.absolute_file_path LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind(utils::escapeLikeKeyword(releaseDirectory.string()) + "%"));
|
||||
}
|
||||
|
||||
Release::pointer Release::find(Session& session, const core::UUID& mbid)
|
||||
|
||||
@@ -167,7 +167,7 @@ namespace lms::db
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS release_mbid_idx ON release(mbid)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS release_type_name_idx ON release_type(name)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_id_idx ON track(id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_path_idx ON track(file_path)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_absolute_path_idx ON track(absolute_file_path)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_name_idx ON track(name)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_name_nocase_idx ON track(name COLLATE NOCASE)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_mbid_idx ON track(mbid)");
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "core/ILogger.hpp"
|
||||
|
||||
#include "IdTypeTraits.hpp"
|
||||
#include "PathTraits.hpp"
|
||||
#include "SqlQuery.hpp"
|
||||
#include "StringViewTraits.hpp"
|
||||
#include "Utils.hpp"
|
||||
@@ -195,14 +196,9 @@ namespace lms::db
|
||||
}
|
||||
}
|
||||
|
||||
Track::Track(const std::filesystem::path& p)
|
||||
: _filePath{ p.string() }
|
||||
Track::pointer Track::create(Session& session)
|
||||
{
|
||||
}
|
||||
|
||||
Track::pointer Track::create(Session& session, const std::filesystem::path& p)
|
||||
{
|
||||
return session.getDboSession()->add(std::unique_ptr<Track> {new Track{ p }});
|
||||
return session.getDboSession()->add(std::make_unique<Track>());
|
||||
}
|
||||
|
||||
std::size_t Track::getCount(Session& session)
|
||||
@@ -216,7 +212,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Track>().where("file_path = ?").bind(p.string()));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Track>().where("absolute_file_path = ?").bind(p.string()));
|
||||
}
|
||||
|
||||
Track::pointer Track::find(Session& session, TrackId id)
|
||||
@@ -269,30 +265,6 @@ namespace lms::db
|
||||
.where("recording_mbid = ?").bind(mbid.getAsString()));
|
||||
}
|
||||
|
||||
RangeResults<Track::PathResult> Track::findPaths(Session& session, std::optional<Range> range)
|
||||
{
|
||||
using QueryResultType = std::tuple<TrackId, std::string>;
|
||||
session.checkReadTransaction();
|
||||
|
||||
// TODO Dbo traits on filesystem
|
||||
auto query{ session.getDboSession()->query<QueryResultType>("SELECT id, file_path FROM track") };
|
||||
|
||||
RangeResults<QueryResultType> queryResults{ utils::execRangeQuery<QueryResultType>(query, range) };
|
||||
|
||||
RangeResults<PathResult> res;
|
||||
res.range = queryResults.range;
|
||||
res.moreResults = queryResults.moreResults;
|
||||
res.results.reserve(queryResults.results.size());
|
||||
|
||||
std::transform(std::cbegin(queryResults.results), std::cend(queryResults.results), std::back_inserter(res.results),
|
||||
[](const QueryResultType& queryResult)
|
||||
{
|
||||
return PathResult{ std::get<TrackId>(queryResult), std::move(std::get<std::string>(queryResult)) };
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Track::findIdsTrackMBIDDuplicates(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
@@ -392,6 +364,18 @@ namespace lms::db
|
||||
return utils::execRangeQuery<TrackId>(query, range);
|
||||
}
|
||||
|
||||
void Track::setAbsoluteFilePath(const std::filesystem::path& filePath)
|
||||
{
|
||||
assert(filePath.is_absolute());
|
||||
_absoluteFilePath = filePath;
|
||||
}
|
||||
|
||||
void Track::setRelativeFilePath(const std::filesystem::path& filePath)
|
||||
{
|
||||
assert(filePath.is_relative());
|
||||
_relativeFilePath = filePath;
|
||||
}
|
||||
|
||||
void Track::clearArtistLinks()
|
||||
{
|
||||
_trackArtistLinks.clear();
|
||||
|
||||
@@ -120,7 +120,6 @@ namespace lms::db
|
||||
static RangeResults<pointer> find(Session& session, const FindParameters& parameters);
|
||||
static void find(Session& session, const FindParameters& parameters, const std::function<void(const Track::pointer&)>& func);
|
||||
static void find(Session& session, const FindParameters& parameters, bool& moreResults, const std::function<void(const Track::pointer&)>& func);
|
||||
static RangeResults<PathResult> findPaths(Session& session, std::optional<Range> range = std::nullopt);
|
||||
static RangeResults<TrackId> findIdsTrackMBIDDuplicates(Session& session, std::optional<Range> range = std::nullopt);
|
||||
static RangeResults<TrackId> findIdsWithRecordingMBIDAndMissingFeatures(Session& session, std::optional<Range> range = std::nullopt);
|
||||
|
||||
@@ -131,7 +130,9 @@ namespace lms::db
|
||||
void setTotalTrack(std::optional<int> totalTrack) { _totalTrack = totalTrack; }
|
||||
void setDiscSubtitle(const std::string& name) { _discSubtitle = name; }
|
||||
void setName(const std::string& name) { _name = std::string(name, 0, _maxNameLength); }
|
||||
void setPath(const std::filesystem::path& filePath) { _filePath = filePath; }
|
||||
void setAbsoluteFilePath(const std::filesystem::path& filePath);
|
||||
void setRelativeFilePath(const std::filesystem::path& filePath);
|
||||
void setFileSize(std::size_t fileSize) { _fileSize = fileSize; }
|
||||
void setDuration(std::chrono::milliseconds duration) { _duration = duration; }
|
||||
void setBitrate(std::size_t bitrate) { _bitrate = bitrate; }
|
||||
void setLastWriteTime(Wt::WDateTime time) { _fileLastWrite = time; }
|
||||
@@ -154,32 +155,34 @@ namespace lms::db
|
||||
void setClusters(const std::vector<ObjectPtr<Cluster>>& clusters);
|
||||
void setMediaLibrary(ObjectPtr<MediaLibrary> mediaLibrary) { _mediaLibrary = getDboPtr(mediaLibrary); }
|
||||
|
||||
std::size_t getScanVersion() const { return _scanVersion; }
|
||||
std::optional<std::size_t> getTrackNumber() const { return _trackNumber; }
|
||||
std::optional<std::size_t> getTotalTrack() const { return _totalTrack; }
|
||||
std::optional<std::size_t> getDiscNumber() const { return _discNumber; }
|
||||
std::size_t getScanVersion() const { return _scanVersion; }
|
||||
std::optional<std::size_t> getTrackNumber() const { return _trackNumber; }
|
||||
std::optional<std::size_t> getTotalTrack() const { return _totalTrack; }
|
||||
std::optional<std::size_t> getDiscNumber() const { return _discNumber; }
|
||||
const std::string& getDiscSubtitle() const { return _discSubtitle; }
|
||||
std::string getName() const { return _name; }
|
||||
std::filesystem::path getPath() const { return _filePath; }
|
||||
std::chrono::milliseconds getDuration() const { return _duration; }
|
||||
std::size_t getBitrate() const { return _bitrate; }
|
||||
std::string getName() const { return _name; }
|
||||
const std::filesystem::path& getAbsoluteFilePath() const { return _absoluteFilePath; }
|
||||
const std::filesystem::path& getRelativeFilePath() const { return _relativeFilePath; }
|
||||
long long getFileSize() const { return _fileSize; }
|
||||
std::chrono::milliseconds getDuration() const { return _duration; }
|
||||
std::size_t getBitrate() const { return _bitrate; }
|
||||
const Wt::WDateTime& getLastWritten() const { return _fileLastWrite; }
|
||||
const Wt::WDate& getDate() const { return _date; }
|
||||
std::optional<int> getYear() const { return _year; }
|
||||
std::optional<int> getYear() const { return _year; }
|
||||
const Wt::WDate& getOriginalDate() const { return _originalDate; }
|
||||
std::optional<int> getOriginalYear() const { return _originalYear; };
|
||||
Wt::WDateTime getLastWriteTime() const { return _fileLastWrite; }
|
||||
Wt::WDateTime getAddedTime() const { return _fileAdded; }
|
||||
bool hasCover() const { return _hasCover; }
|
||||
std::optional<core::UUID> getTrackMBID() const { return core::UUID::fromString(_trackMBID); }
|
||||
std::optional<core::UUID> getRecordingMBID() const { return core::UUID::fromString(_recordingMBID); }
|
||||
std::optional<std::string> getCopyright() const;
|
||||
std::optional<std::string> getCopyrightURL() const;
|
||||
std::optional<float> getTrackReplayGain() const { return _trackReplayGain; }
|
||||
std::optional<float> getReleaseReplayGain() const { return _releaseReplayGain; }
|
||||
std::string_view getArtistDisplayName() const { return _artistDisplayName; }
|
||||
std::optional<int> getOriginalYear() const { return _originalYear; };
|
||||
const Wt::WDateTime& getLastWriteTime() const { return _fileLastWrite; }
|
||||
const Wt::WDateTime& getAddedTime() const { return _fileAdded; }
|
||||
bool hasCover() const { return _hasCover; }
|
||||
std::optional<core::UUID> getTrackMBID() const { return core::UUID::fromString(_trackMBID); }
|
||||
std::optional<core::UUID> getRecordingMBID() const { return core::UUID::fromString(_recordingMBID); }
|
||||
std::optional<std::string> getCopyright() const;
|
||||
std::optional<std::string> getCopyrightURL() const;
|
||||
std::optional<float> getTrackReplayGain() const { return _trackReplayGain; }
|
||||
std::optional<float> getReleaseReplayGain() const { return _releaseReplayGain; }
|
||||
std::string_view getArtistDisplayName() const { return _artistDisplayName; }
|
||||
// no artistLinkTypes means get all
|
||||
std::vector<ObjectPtr<Artist>> getArtists(core::EnumSet<TrackArtistLinkType> artistLinkTypes) const; // no type means all
|
||||
std::vector<ObjectPtr<Artist>> getArtists(core::EnumSet<TrackArtistLinkType> artistLinkTypes) const; // no type means all
|
||||
std::vector<ArtistId> getArtistIds(core::EnumSet<TrackArtistLinkType> artistLinkTypes) const; // no type means all
|
||||
std::vector<ObjectPtr<TrackArtistLink>> getArtistLinks() const;
|
||||
ObjectPtr<Release> getRelease() const { return _release; }
|
||||
@@ -204,7 +207,9 @@ namespace lms::db
|
||||
Wt::Dbo::field(a, _year, "year");
|
||||
Wt::Dbo::field(a, _originalDate, "original_date");
|
||||
Wt::Dbo::field(a, _originalYear, "original_year");
|
||||
Wt::Dbo::field(a, _filePath, "file_path");
|
||||
Wt::Dbo::field(a, _absoluteFilePath, "absolute_file_path");
|
||||
Wt::Dbo::field(a, _relativeFilePath, "relative_file_path");
|
||||
Wt::Dbo::field(a, _fileSize, "file_size");
|
||||
Wt::Dbo::field(a, _fileLastWrite, "file_last_write");
|
||||
Wt::Dbo::field(a, _fileAdded, "file_added");
|
||||
Wt::Dbo::field(a, _hasCover, "has_cover");
|
||||
@@ -223,8 +228,7 @@ namespace lms::db
|
||||
|
||||
private:
|
||||
friend class Session;
|
||||
Track(const std::filesystem::path& p);
|
||||
static pointer create(Session& session, const std::filesystem::path& p);
|
||||
static pointer create(Session& session);
|
||||
|
||||
static constexpr std::size_t _maxNameLength{ 256 };
|
||||
static constexpr std::size_t _maxCopyrightLength{ 256 };
|
||||
@@ -237,12 +241,14 @@ namespace lms::db
|
||||
std::string _discSubtitle;
|
||||
std::string _name;
|
||||
std::chrono::duration<int, std::milli> _duration{};
|
||||
int _bitrate; // in bps
|
||||
int _bitrate{}; // in bps
|
||||
Wt::WDate _date;
|
||||
std::optional<int> _year;
|
||||
Wt::WDate _originalDate;
|
||||
std::optional<int> _originalYear;
|
||||
std::string _filePath;
|
||||
std::filesystem::path _absoluteFilePath; // full path
|
||||
std::filesystem::path _relativeFilePath; // relative to root (that may be deleted)
|
||||
long long _fileSize{};
|
||||
Wt::WDateTime _fileLastWrite;
|
||||
Wt::WDateTime _fileAdded;
|
||||
bool _hasCover{};
|
||||
@@ -270,5 +276,3 @@ namespace lms::db
|
||||
std::ostream& operator<<(std::ostream& os, const TrackInfo& trackInfo);
|
||||
}
|
||||
} // namespace lms::db
|
||||
|
||||
|
||||
|
||||
@@ -79,10 +79,10 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Artist_findByRangedIdBased)
|
||||
{
|
||||
ScopedTrack track1{ session, "MyTrackFile1" };
|
||||
ScopedTrack track2a{ session, "MyTrackFile2a" };
|
||||
ScopedTrack track2b{ session, "MyTrackFile2b" };
|
||||
ScopedTrack track3{ session, "MyTrackFile3" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2a{ session };
|
||||
ScopedTrack track2b{ session };
|
||||
ScopedTrack track3{ session };
|
||||
ScopedArtist artist1{ session, "MyArtist1" };
|
||||
ScopedArtist artist2{ session, "MyArtist2" };
|
||||
ScopedArtist artist3{ session, "MyArtist3" };
|
||||
@@ -232,7 +232,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Artist_singleTrack)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
|
||||
{
|
||||
@@ -302,7 +302,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Artist_singleTrack_mediaLibrary)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
ScopedMediaLibrary library{ session };
|
||||
ScopedMediaLibrary otherLibrary{ session };
|
||||
@@ -335,7 +335,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Artist_singleTracktMultiRoles)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
@@ -398,7 +398,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Artist_singleTrackMultiArtists)
|
||||
{
|
||||
ScopedTrack track{ session, "track" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedArtist artist1{ session, "artist1" };
|
||||
ScopedArtist artist2{ session, "artist2" };
|
||||
ASSERT_NE(artist1.getId(), artist2.getId());
|
||||
@@ -458,7 +458,7 @@ namespace lms::db::tests
|
||||
TEST_F(DatabaseFixture, Artist_findByName)
|
||||
{
|
||||
ScopedArtist artist{ session, "AAA" };
|
||||
ScopedTrack track{ session, "MyTrack" }; // filters does not work on orphans
|
||||
ScopedTrack track{ session }; // filters does not work on orphans
|
||||
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
@@ -576,8 +576,8 @@ namespace lms::db::tests
|
||||
TEST_F(DatabaseFixture, Artist_nonReleaseTracks)
|
||||
{
|
||||
ScopedArtist artist{ session, "artist" };
|
||||
ScopedTrack track1{ session, "MyTrack1" };
|
||||
ScopedTrack track2{ session, "MyTrack2" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
|
||||
{
|
||||
@@ -608,7 +608,7 @@ namespace lms::db::tests
|
||||
TEST_F(DatabaseFixture, Artist_findByRelease)
|
||||
{
|
||||
ScopedArtist artist{ session, "artist" };
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
|
||||
{
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Cluster_singleTrack)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedClusterType clusterType{ session, "MyClusterType" };
|
||||
|
||||
{
|
||||
@@ -160,7 +160,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Cluster_singleTrackWithSeveralClusters)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedClusterType clusterType{ session, "MyClusterType" };
|
||||
|
||||
ScopedCluster cluster1{ session, clusterType.lockAndGet(), "MyCluster1" };
|
||||
@@ -215,7 +215,7 @@ namespace lms::db::tests
|
||||
|
||||
for (std::size_t i{}; i < 10; ++i)
|
||||
{
|
||||
tracks.emplace_back(session, "MyTrack" + std::to_string(i));
|
||||
tracks.emplace_back(session);
|
||||
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
@@ -270,7 +270,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Cluster_singleTrackSingleReleaseSingleCluster)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrackFile" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
|
||||
{
|
||||
@@ -345,7 +345,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, SingleTrackSingleArtistMultiClusters)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrackFile" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
ScopedClusterType clusterType{ session, "MyType" };
|
||||
ScopedCluster cluster1{ session, clusterType.lockAndGet(), "Cluster1" };
|
||||
@@ -406,7 +406,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, SingleTrackSingleArtistMultiRolesMultiClusters)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrackFile" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
ScopedClusterType clusterType{ session, "MyType" };
|
||||
ScopedCluster cluster{ session, clusterType.lockAndGet(), "MyCluster" };
|
||||
@@ -450,7 +450,7 @@ namespace lms::db::tests
|
||||
|
||||
for (std::size_t i{}; i < nbTracks; ++i)
|
||||
{
|
||||
tracks.emplace_back(session, "MyTrackFile" + std::to_string(i));
|
||||
tracks.emplace_back(session);
|
||||
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
TrackArtistLink::create(session, tracks.back().get(), artist.get(), TrackArtistLinkType::Artist);
|
||||
@@ -486,7 +486,7 @@ namespace lms::db::tests
|
||||
|
||||
for (std::size_t i{}; i < 10; ++i)
|
||||
{
|
||||
tracks.emplace_back(session, "MyTrack" + std::to_string(i));
|
||||
tracks.emplace_back(session);
|
||||
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
@@ -515,7 +515,7 @@ namespace lms::db::tests
|
||||
|
||||
for (std::size_t i{}; i < 5; ++i)
|
||||
{
|
||||
tracks.emplace_back(session, "MyTrack" + std::to_string(i));
|
||||
tracks.emplace_back(session);
|
||||
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
@@ -525,7 +525,7 @@ namespace lms::db::tests
|
||||
|
||||
for (std::size_t i{ 5 }; i < 10; ++i)
|
||||
{
|
||||
tracks.emplace_back(session, "MyTrack" + std::to_string(i));
|
||||
tracks.emplace_back(session);
|
||||
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
@@ -555,7 +555,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, SingleTrackSingleReleaseSingleArtistSingleCluster)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
ScopedClusterType clusterType{ session, "MyType" };
|
||||
@@ -597,7 +597,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, SingleTrackSingleReleaseSingleArtistMultiClusters)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
ScopedClusterType clusterType{ session, "MyClusterType" };
|
||||
@@ -636,7 +636,7 @@ namespace lms::db::tests
|
||||
|
||||
for (std::size_t i{}; i < 20; ++i)
|
||||
{
|
||||
tracks.emplace_back(session, "MyTrack" + std::to_string(i));
|
||||
tracks.emplace_back(session);
|
||||
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
|
||||
@@ -669,7 +669,7 @@ namespace lms::db::tests
|
||||
|
||||
for (std::size_t i{}; i < 20; ++i)
|
||||
{
|
||||
tracks.emplace_back(session, "MyTrack" + std::to_string(i));
|
||||
tracks.emplace_back(session);
|
||||
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
|
||||
@@ -729,7 +729,7 @@ namespace lms::db::tests
|
||||
std::list<ScopedTrack> tracks;
|
||||
for (std::size_t i{}; i < 10; ++i)
|
||||
{
|
||||
tracks.emplace_back(session, "MyTrack" + std::to_string(i));
|
||||
tracks.emplace_back(session);
|
||||
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
|
||||
@@ -744,7 +744,7 @@ namespace lms::db::tests
|
||||
cluster1.get().modify()->addTrack(tracks.back().get());
|
||||
}
|
||||
|
||||
tracks.emplace_back(session, "MyTrack" + std::to_string(tracks.size()));
|
||||
tracks.emplace_back(session);
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
TrackArtistLink::create(session, tracks.back().get(), artist3.get(), TrackArtistLinkType::Artist);
|
||||
@@ -810,7 +810,7 @@ namespace lms::db::tests
|
||||
std::list<ScopedTrack> tracks;
|
||||
for (std::size_t i{}; i < 10; ++i)
|
||||
{
|
||||
tracks.emplace_back(session, "MyTrack" + std::to_string(i));
|
||||
tracks.emplace_back(session);
|
||||
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
|
||||
@@ -825,7 +825,7 @@ namespace lms::db::tests
|
||||
cluster1.get().modify()->addTrack(tracks.back().get());
|
||||
}
|
||||
|
||||
tracks.emplace_back(session, "MyTrack" + std::to_string(tracks.size()));
|
||||
tracks.emplace_back(session);
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
tracks.back().get().modify()->setRelease(release3.get());
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace lms::db::tests
|
||||
|
||||
for (std::size_t i{}; i < nbTracks; ++i)
|
||||
{
|
||||
tracks.emplace_back(session, "MyTrack" + std::to_string(i));
|
||||
tracks.emplace_back(session);
|
||||
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, SingleTrackSingleReleaseSingleArtist)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getAll)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
|
||||
{
|
||||
@@ -59,7 +59,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_get)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedListen listen{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, Wt::WDateTime {Wt::WDate{2000, 1, 2}, Wt::WTime{12, 0, 1}} };
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_get_multi)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedListen listen3{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, Wt::WDateTime {Wt::WDate{2000, 1, 2}, Wt::WTime{12, 0, 3}} };
|
||||
ScopedListen listen1{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, Wt::WDateTime {Wt::WDate{2000, 1, 2}, Wt::WTime{12, 0, 1}} };
|
||||
@@ -112,7 +112,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_get_byDateTime)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
const Wt::WDateTime dateTime1{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
const Wt::WDateTime dateTime2{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 2} };
|
||||
@@ -145,7 +145,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getTopArtists)
|
||||
{
|
||||
ScopedTrack track1{ session, "MyTrack" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
const Wt::WDateTime dateTime1{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
ScopedListen listen1{ session, user.lockAndGet(), track1.lockAndGet(), ScrobblingBackend::Internal, dateTime1 };
|
||||
@@ -162,7 +162,7 @@ namespace lms::db::tests
|
||||
EXPECT_EQ(artists.moreResults, false);
|
||||
}
|
||||
|
||||
ScopedTrack track2{ session, "MyTrack2" };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedArtist artist1{ session, "MyArtist1" };
|
||||
ScopedListen listen2{ session, user.lockAndGet(), track2.lockAndGet(), ScrobblingBackend::Internal, dateTime1.addSecs(1) };
|
||||
|
||||
@@ -226,9 +226,9 @@ namespace lms::db::tests
|
||||
TEST_F(DatabaseFixture, Listen_getTopArtists_multi)
|
||||
{
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedTrack track1{ session, "MyTrack1" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedArtist artist1{ session, "MyArtist1" };
|
||||
ScopedTrack track2{ session, "MyTrack2" };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedArtist artist2{ session, "MyArtist2" };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
|
||||
@@ -293,7 +293,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getTopArtists_cluster)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
@@ -337,7 +337,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getTopArtists_mediaLibrary)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
const Wt::WDateTime dateTime1{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
@@ -403,7 +403,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getTopReleases)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
@@ -453,8 +453,8 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getTopReleases_multi)
|
||||
{
|
||||
ScopedTrack track1{ session, "MyTrack" };
|
||||
ScopedTrack track2{ session, "MyTrack" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
ScopedListen listen1{ session, user.lockAndGet(), track1.lockAndGet(), ScrobblingBackend::Internal, dateTime };
|
||||
@@ -513,7 +513,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getTopReleases_cluster)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
ScopedListen listen{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime };
|
||||
@@ -558,7 +558,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getTopReleases_mediaLibrary)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
@@ -615,7 +615,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getTopTracks)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
|
||||
@@ -660,7 +660,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getTopTracks_artist)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
@@ -714,8 +714,8 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getTopTrack_multi)
|
||||
{
|
||||
ScopedTrack track1{ session, "MyTrack1" };
|
||||
ScopedTrack track2{ session, "MyTrack2" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
ScopedListen listen1{ session, user.lockAndGet(), track1.lockAndGet(), ScrobblingBackend::Internal, dateTime };
|
||||
@@ -766,7 +766,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getTopTracks_cluster)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
ScopedListen listen{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime };
|
||||
@@ -805,7 +805,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getTopTracks_mediaLibrary)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
ScopedMediaLibrary library{ session };
|
||||
@@ -860,7 +860,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getRecentArtists)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
|
||||
@@ -937,9 +937,9 @@ namespace lms::db::tests
|
||||
TEST_F(DatabaseFixture, Listen_getRecentArtists_multi)
|
||||
{
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedTrack track1{ session, "MyTrack1" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedArtist artist1{ session, "MyArtist1" };
|
||||
ScopedTrack track2{ session, "MyTrack2" };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedArtist artist2{ session, "MyArtist2" };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
|
||||
@@ -1003,7 +1003,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getRecentArtists_cluster)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate{2000, 1, 2}, Wt::WTime{12,0, 1} };
|
||||
@@ -1048,7 +1048,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getRecentArtists_mediaLibrary)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
ScopedMediaLibrary library{ session };
|
||||
@@ -1086,7 +1086,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getRecentReleases)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
|
||||
@@ -1137,7 +1137,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getMostRecentRelease)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
|
||||
@@ -1189,8 +1189,8 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getRecentReleases_multi)
|
||||
{
|
||||
ScopedTrack track1{ session, "MyTrack1" };
|
||||
ScopedTrack track2{ session, "MyTrack2" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedRelease release1{ session, "MyRelease1" };
|
||||
ScopedRelease release2{ session, "MyRelease2" };
|
||||
@@ -1265,7 +1265,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getRecentReleases_cluster)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedClusterType clusterType{ session, "MyType" };
|
||||
ScopedCluster cluster{ session, clusterType.lockAndGet(), "MyCluster" };
|
||||
@@ -1322,7 +1322,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getRecentReleases_mediaLibrary)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
ScopedMediaLibrary library{ session };
|
||||
@@ -1362,7 +1362,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getRecentTracks)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
|
||||
{
|
||||
@@ -1409,7 +1409,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getRecentTracks_mediaLibrary)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedMediaLibrary library{ session };
|
||||
ScopedMediaLibrary otherLibrary{ session };
|
||||
@@ -1448,7 +1448,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getCount_track)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
|
||||
{
|
||||
@@ -1482,8 +1482,8 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getCount_release)
|
||||
{
|
||||
ScopedTrack track1{ session, "MyTrack" };
|
||||
ScopedTrack track2{ session, "MyTrack" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
|
||||
@@ -1530,7 +1530,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getMostRecentTrack)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
|
||||
{
|
||||
@@ -1576,8 +1576,8 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getRecentTracks_multi)
|
||||
{
|
||||
ScopedTrack track1{ session, "MyTrack1" };
|
||||
ScopedTrack track2{ session, "MyTrack2" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
|
||||
const Wt::WDateTime dateTime{ Wt::WDate {2000, 1, 2}, Wt::WTime {12,0, 1} };
|
||||
@@ -1644,7 +1644,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Listen_getRecentTracks_cluster)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate {2000, 1, 2}, Wt::WTime {12,0, 1} };
|
||||
ScopedListen listen{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime };
|
||||
|
||||
@@ -76,10 +76,10 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Release_findByRangedIdBased)
|
||||
{
|
||||
ScopedTrack track1{ session, "MyTrackFile1" };
|
||||
ScopedTrack track2a{ session, "MyTrackFile2a" };
|
||||
ScopedTrack track2b{ session, "MyTrackFile2b" };
|
||||
ScopedTrack track3{ session, "MyTrackFile3" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2a{ session };
|
||||
ScopedTrack track2b{ session };
|
||||
ScopedTrack track3{ session };
|
||||
ScopedRelease release1{ session, "MyRelease1" };
|
||||
ScopedRelease release2{ session, "MyRelease2" };
|
||||
ScopedRelease release3{ session, "MyRelease3" };
|
||||
@@ -172,7 +172,7 @@ namespace lms::db::tests
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
|
||||
@@ -229,7 +229,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Release_singleTrack_mediaLibrary)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
ScopedMediaLibrary library{ session };
|
||||
ScopedMediaLibrary otherLibrary{ session };
|
||||
@@ -257,17 +257,17 @@ namespace lms::db::tests
|
||||
{
|
||||
ScopedRelease release1{ session, "MyRelease" };
|
||||
ScopedRelease release2{ session, "MyRelease" };
|
||||
ScopedTrack track1{ session, "MyTrack" };
|
||||
ScopedTrack track2{ session, "MyTrack" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
|
||||
track1.get().modify()->setRelease(release1.get());
|
||||
track1.get().modify()->setPath("/tmp/foo/foo.mp3");
|
||||
track1.get().modify()->setAbsoluteFilePath("/tmp/foo/foo.mp3");
|
||||
|
||||
track2.get().modify()->setRelease(release2.get());
|
||||
track2.get().modify()->setPath("/tmp/bar/bar.mp3");
|
||||
track2.get().modify()->setAbsoluteFilePath("/tmp/bar/bar.mp3");
|
||||
}
|
||||
|
||||
{
|
||||
@@ -296,12 +296,12 @@ namespace lms::db::tests
|
||||
ScopedRelease release6{ session, "_yRelease" };
|
||||
|
||||
// filters does not work on orphans
|
||||
ScopedTrack track1{ session, "MyTrack" };
|
||||
ScopedTrack track2{ session, "MyTrack" };
|
||||
ScopedTrack track3{ session, "MyTrack" };
|
||||
ScopedTrack track4{ session, "MyTrack" };
|
||||
ScopedTrack track5{ session, "MyTrack" };
|
||||
ScopedTrack track6{ session, "MyTrack" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedTrack track3{ session };
|
||||
ScopedTrack track4{ session };
|
||||
ScopedTrack track5{ session };
|
||||
ScopedTrack track6{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
@@ -362,7 +362,7 @@ namespace lms::db::tests
|
||||
EXPECT_FALSE(release1->getTotalDisc());
|
||||
}
|
||||
|
||||
ScopedTrack track1{ session, "MyTrack" };
|
||||
ScopedTrack track1{ session };
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
|
||||
@@ -391,7 +391,7 @@ namespace lms::db::tests
|
||||
EXPECT_EQ(*release1->getTotalDisc(), 6);
|
||||
}
|
||||
|
||||
ScopedTrack track2{ session, "MyTrack2" };
|
||||
ScopedTrack track2{ session };
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
|
||||
@@ -416,7 +416,7 @@ namespace lms::db::tests
|
||||
EXPECT_FALSE(release2->getTotalDisc());
|
||||
}
|
||||
|
||||
ScopedTrack track3{ session, "MyTrack3" };
|
||||
ScopedTrack track3{ session };
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
|
||||
@@ -443,10 +443,10 @@ namespace lms::db::tests
|
||||
ScopedRelease release1{ session, "MyRelease1" };
|
||||
ScopedRelease release2{ session, "MyRelease2" };
|
||||
|
||||
ScopedTrack track1A{ session, "MyTrack1A" };
|
||||
ScopedTrack track1B{ session, "MyTrack1B" };
|
||||
ScopedTrack track2A{ session, "MyTrack2A" };
|
||||
ScopedTrack track2B{ session, "MyTrack2B" };
|
||||
ScopedTrack track1A{ session };
|
||||
ScopedTrack track1B{ session };
|
||||
ScopedTrack track2A{ session };
|
||||
ScopedTrack track2B{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
@@ -496,10 +496,10 @@ namespace lms::db::tests
|
||||
const Wt::WDate release1Date{ Wt::WDate {1994, 2, 3} };
|
||||
const Wt::WDate release1OriginalDate{ Wt::WDate {1993, 4, 5} };
|
||||
|
||||
ScopedTrack track1A{ session, "MyTrack1A" };
|
||||
ScopedTrack track1B{ session, "MyTrack1B" };
|
||||
ScopedTrack track2A{ session, "MyTrack2A" };
|
||||
ScopedTrack track2B{ session, "MyTrack2B" };
|
||||
ScopedTrack track1A{ session };
|
||||
ScopedTrack track1B{ session };
|
||||
ScopedTrack track2A{ session };
|
||||
ScopedTrack track2B{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
@@ -548,10 +548,10 @@ namespace lms::db::tests
|
||||
const int release1Year{ 1994 };
|
||||
const int release1OriginalYear{ 1993 };
|
||||
|
||||
ScopedTrack track1A{ session, "MyTrack1A" };
|
||||
ScopedTrack track1B{ session, "MyTrack1B" };
|
||||
ScopedTrack track2A{ session, "MyTrack2A" };
|
||||
ScopedTrack track2B{ session, "MyTrack2B" };
|
||||
ScopedTrack track1A{ session };
|
||||
ScopedTrack track1B{ session };
|
||||
ScopedTrack track2A{ session };
|
||||
ScopedTrack track2B{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
@@ -597,7 +597,7 @@ namespace lms::db::tests
|
||||
TEST_F(DatabaseFixture, Release_writtenAfter)
|
||||
{
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
|
||||
const Wt::WDateTime dateTime{ Wt::WDate {1950, 1, 1}, Wt::WTime {12, 30, 20} };
|
||||
|
||||
@@ -629,7 +629,7 @@ namespace lms::db::tests
|
||||
TEST_F(DatabaseFixture, Release_artist)
|
||||
{
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedArtist artist{ session, "MyArtist" };
|
||||
ScopedArtist artist2{ session, "MyArtist2" };
|
||||
{
|
||||
@@ -690,8 +690,8 @@ namespace lms::db::tests
|
||||
TEST_F(DatabaseFixture, Release_getDiscCount)
|
||||
{
|
||||
ScopedRelease release{ session, "MyRelease" };
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track2{ session, "MyTrack2" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedTrack track2{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
@@ -816,8 +816,8 @@ namespace lms::db::tests
|
||||
ScopedRelease release2{ session, "MyRelease2" };
|
||||
const Wt::WDate release2Date{ Wt::WDate {1994, 2, 3} };
|
||||
|
||||
ScopedTrack track1{ session, "MyTrack1" };
|
||||
ScopedTrack track2{ session, "MyTrack2" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
|
||||
ASSERT_LT(release2Date, release1Date);
|
||||
ASSERT_GT(release2Date, release1OriginalDate);
|
||||
@@ -879,9 +879,9 @@ namespace lms::db::tests
|
||||
TEST_F(DatabaseFixture, Release_meanBitrate)
|
||||
{
|
||||
ScopedRelease release1{ session, "MyRelease1" };
|
||||
ScopedTrack track1{ session, "MyTrack1" };
|
||||
ScopedTrack track2{ session, "MyTrack2" };
|
||||
ScopedTrack track3{ session, "MyTrack3" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedTrack track3{ session };
|
||||
|
||||
auto checkExpectedBitrate = [&](std::size_t bitrate)
|
||||
{
|
||||
@@ -920,9 +920,9 @@ namespace lms::db::tests
|
||||
ScopedRelease release2{ session, "MyRelease2" };
|
||||
ScopedRelease release3{ session, "MyRelease2" };
|
||||
|
||||
ScopedTrack track1{ session, "MyTrack1" };
|
||||
ScopedTrack track2{ session, "MyTrack2" };
|
||||
ScopedTrack track3{ session, "MyTrack3" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedTrack track3{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, StarredTrack)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedUser user2{ session, "MyUser2" };
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Starredtrack_PendingDestroy)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedStarredTrack starredTrack{ session, track.lockAndGet(), user.lockAndGet(), FeedbackBackend::Internal };
|
||||
|
||||
@@ -96,8 +96,8 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, StarredTrack_dateTime)
|
||||
{
|
||||
ScopedTrack track1{ session, "MyTrack1" };
|
||||
ScopedTrack track2{ session, "MyTrack2" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
|
||||
ScopedStarredTrack starredTrack1{ session, track1.lockAndGet(), user.lockAndGet(), FeedbackBackend::Internal };
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace lms::db::tests
|
||||
}
|
||||
}
|
||||
|
||||
ScopedTrack track{ session, "MyTrackFile" };
|
||||
ScopedTrack track{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
@@ -65,9 +65,9 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Track_findByRangedIdBased)
|
||||
{
|
||||
ScopedTrack track1{ session, "MyTrackFile1" };
|
||||
ScopedTrack track2{ session, "MyTrackFile1" };
|
||||
ScopedTrack track3{ session, "MyTrackFile1" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedTrack track3{ session };
|
||||
ScopedMediaLibrary library{ session };
|
||||
ScopedMediaLibrary otherLibrary{ session };
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Track_MediaLibrary)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrackFile" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedMediaLibrary library{ session };
|
||||
ScopedMediaLibrary otherLibrary{ session };
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Track_noMediaLibrary)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrackFile" };
|
||||
ScopedTrack track{ session };
|
||||
{
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
MediaLibrary::pointer mediaLibrary{ track->getMediaLibrary() };
|
||||
@@ -200,8 +200,8 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, MultipleTracks)
|
||||
{
|
||||
ScopedTrack track1{ session, "MyTrackFile1" };
|
||||
ScopedTrack track2{ session, "MyTrackFile2" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
@@ -214,12 +214,12 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, MultipleTracksSearchByFilter)
|
||||
{
|
||||
ScopedTrack track1{ session, "" };
|
||||
ScopedTrack track2{ session, "" };
|
||||
ScopedTrack track3{ session, "" };
|
||||
ScopedTrack track4{ session, "" };
|
||||
ScopedTrack track5{ session, "" };
|
||||
ScopedTrack track6{ session, "" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
ScopedTrack track3{ session };
|
||||
ScopedTrack track4{ session };
|
||||
ScopedTrack track5{ session };
|
||||
ScopedTrack track6{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
@@ -260,7 +260,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Track_date)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
const Wt::WDate date{ 1995, 5, 5 };
|
||||
const Wt::WDate originalDate{ 1994, 2, 2 };
|
||||
{
|
||||
@@ -298,7 +298,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, Track_writtenAfter)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
|
||||
const Wt::WDateTime dateTime{ Wt::WDate {1950, 1, 1}, Wt::WTime {12, 30, 20} };
|
||||
|
||||
@@ -325,4 +325,21 @@ namespace lms::db::tests
|
||||
EXPECT_EQ(tracks.results.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DatabaseFixture, Track_path)
|
||||
{
|
||||
ScopedTrack track{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
track.get().modify()->setAbsoluteFilePath("/root/foo/file.path");
|
||||
track.get().modify()->setRelativeFilePath("foo/file.path");
|
||||
}
|
||||
|
||||
{
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
EXPECT_EQ(track->getAbsoluteFilePath(), "/root/foo/file.path");
|
||||
EXPECT_EQ(track->getRelativeFilePath(), "foo/file.path");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, TrackBookmark)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace lms::db::tests
|
||||
|
||||
TEST_F(DatabaseFixture, TrackFeatures)
|
||||
{
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
|
||||
{
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace lms::db::tests
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedTrackList trackList1{ session, "MyTrackList1", TrackListType::Playlist, false, user.lockAndGet() };
|
||||
ScopedTrackList trackList2{ session, "MyTrackList2", TrackListType::Playlist, false, user.lockAndGet() };
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
@@ -79,7 +79,7 @@ namespace lms::db::tests
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedTrackList trackList2{ session, "MyTrackList2", TrackListType::Playlist, false, user.lockAndGet() };
|
||||
ScopedTrackList trackList1{ session, "MyTrackList1", TrackListType::Playlist, false, user.lockAndGet() };
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
@@ -131,7 +131,7 @@ namespace lms::db::tests
|
||||
|
||||
for (std::size_t i{}; i < 10; ++i)
|
||||
{
|
||||
tracks.emplace_back(session, "MyTrack" + std::to_string(i));
|
||||
tracks.emplace_back(session);
|
||||
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
session.create<TrackListEntry>(tracks.back().get(), trackList.get());
|
||||
@@ -158,7 +158,7 @@ namespace lms::db::tests
|
||||
ScopedTrackList trackList2{ session, "MyTrackList2", TrackListType::Playlist, false, user.lockAndGet() };
|
||||
ScopedClusterType clusterType{ session, "MyClusterType" };
|
||||
ScopedCluster cluster{ session, clusterType.lockAndGet(), "MyCluster" };
|
||||
ScopedTrack track{ session, "MyTrack" };
|
||||
ScopedTrack track{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
@@ -187,8 +187,8 @@ namespace lms::db::tests
|
||||
{
|
||||
ScopedUser user{ session, "MyUser" };
|
||||
ScopedTrackList trackList{ session, "MyTrackList", TrackListType::Playlist, false, user.lockAndGet() };
|
||||
ScopedTrack track1{ session, "MyTrack" };
|
||||
ScopedTrack track2{ session, "MyTrack" };
|
||||
ScopedTrack track1{ session };
|
||||
ScopedTrack track2{ session };
|
||||
|
||||
{
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace lms::cover
|
||||
res = TrackInfo{};
|
||||
|
||||
res->hasCover = track->hasCover();
|
||||
res->trackPath = track->getPath();
|
||||
res->trackPath = track->getAbsoluteFilePath();
|
||||
|
||||
if (const db::Release::pointer & release{ track->getRelease() })
|
||||
{
|
||||
@@ -366,7 +366,7 @@ namespace lms::cover
|
||||
const Track::pointer& track{ tracks.results.front() };
|
||||
res = ReleaseInfo{};
|
||||
res->firstTrackId = track->getId();
|
||||
res->releaseDirectory = track->getPath().parent_path();
|
||||
res->releaseDirectory = track->getAbsoluteFilePath().parent_path();
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -424,9 +424,9 @@ namespace lms::cover
|
||||
|
||||
const auto releaseArtists{ Artist::findIds(session, artistFindParams) };
|
||||
if (releaseArtists.results.size() == 1)
|
||||
releasePaths.insert(track->getPath().parent_path());
|
||||
releasePaths.insert(track->getAbsoluteFilePath().parent_path());
|
||||
else
|
||||
multiArtistReleasePaths.insert(track->getPath().parent_path());
|
||||
multiArtistReleasePaths.insert(track->getAbsoluteFilePath().parent_path());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace lms::scanner
|
||||
const Track::pointer track{ Track::find(session, trackId) };
|
||||
if (auto trackMBID{ track->getTrackMBID() })
|
||||
{
|
||||
LMS_LOG(DBUPDATER, INFO, "Found duplicated track MBID [" << trackMBID->getAsString() << "], file: " << track->getPath().string() << " - " << track->getName());
|
||||
LMS_LOG(DBUPDATER, INFO, "Found duplicated track MBID [" << trackMBID->getAsString() << "], file: " << track->getAbsoluteFilePath().string() << " - " << track->getName());
|
||||
context.stats.duplicates.emplace_back(ScanDuplicate{ track->getId(), DuplicateReason::SameTrackMBID });
|
||||
context.currentStepStats.processedElems++;
|
||||
_progressCallback(context.currentStepStats);
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace lms::scanner
|
||||
{
|
||||
endReached = false;
|
||||
|
||||
if (!checkFile(track->getPath()))
|
||||
if (!checkFile(track->getAbsoluteFilePath()))
|
||||
tracksToRemove.push_back(track);
|
||||
|
||||
context.currentStepStats.processedElems++;
|
||||
|
||||
@@ -42,6 +42,66 @@ namespace lms::scanner
|
||||
|
||||
namespace
|
||||
{
|
||||
struct FileInfo
|
||||
{
|
||||
Wt::WDateTime lastWriteTime;
|
||||
std::filesystem::path relativePath;
|
||||
std::size_t fileSize{};
|
||||
};
|
||||
|
||||
Wt::WDateTime retrieveFileGetLastWrite(const std::filesystem::path& file)
|
||||
{
|
||||
Wt::WDateTime res;
|
||||
|
||||
try
|
||||
{
|
||||
res = core::pathUtils::getLastWriteTime(file);
|
||||
}
|
||||
catch (core::LmsException& e)
|
||||
{
|
||||
LMS_LOG(DBUPDATER, ERROR, "Cannot get last write time: " << e.what());
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::optional<FileInfo> retrieveFileInfo(const std::filesystem::path& file, const std::filesystem::path& rootPath)
|
||||
{
|
||||
std::optional<FileInfo> res;
|
||||
res.emplace();
|
||||
|
||||
res->lastWriteTime = retrieveFileGetLastWrite(file);
|
||||
if (!res->lastWriteTime.isValid())
|
||||
{
|
||||
res.reset();
|
||||
return res;
|
||||
}
|
||||
|
||||
{
|
||||
std::error_code ec;
|
||||
res->relativePath = std::filesystem::relative(file, rootPath, ec);
|
||||
if (ec)
|
||||
{
|
||||
LMS_LOG(DBUPDATER, ERROR, "Cannot get relative file path for '" << file.string() << "' from '" << rootPath.string() << "': " << ec.message());
|
||||
res.reset();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::error_code ec;
|
||||
res->fileSize = std::filesystem::file_size(file, ec);
|
||||
if (ec)
|
||||
{
|
||||
LMS_LOG(DBUPDATER, ERROR, "Cannot get file size for '" << file.string() << "': " << ec.message());
|
||||
res.reset();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Artist::pointer createArtist(Session& session, const metadata::Artist& artistInfo)
|
||||
{
|
||||
Artist::pointer artist{ session.create<Artist>(artistInfo.name) };
|
||||
@@ -389,14 +449,11 @@ namespace lms::scanner
|
||||
bool ScanStepScanFiles::checkFileNeedScan(ScanContext& context, const std::filesystem::path& file, const ScannerSettings::MediaLibraryInfo& libraryInfo)
|
||||
{
|
||||
ScanStats& stats{ context.stats };
|
||||
Wt::WDateTime lastWriteTime;
|
||||
try
|
||||
|
||||
Wt::WDateTime lastWriteTime{ retrieveFileGetLastWrite(file) };
|
||||
// Should rarely fail as we are currently iterating it
|
||||
if (!lastWriteTime.isValid())
|
||||
{
|
||||
lastWriteTime = core::pathUtils::getLastWriteTime(file);
|
||||
}
|
||||
catch (core::LmsException& e)
|
||||
{
|
||||
LMS_LOG(DBUPDATER, ERROR, e.what());
|
||||
stats.skips++;
|
||||
return false;
|
||||
}
|
||||
@@ -416,7 +473,7 @@ namespace lms::scanner
|
||||
)
|
||||
{
|
||||
// this file may have been moved from one library to another, then we just need to update the media library id instead of a full rescan
|
||||
auto trackMediaLibrary{ track->getMediaLibrary() };
|
||||
const auto trackMediaLibrary{ track->getMediaLibrary() };
|
||||
if (trackMediaLibrary && trackMediaLibrary->getId() == libraryInfo.id)
|
||||
{
|
||||
stats.skips++;
|
||||
@@ -451,6 +508,8 @@ namespace lms::scanner
|
||||
|
||||
for (const MetaDataScanResult& scanResult : scanResults)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED("Scanner", "ProcessScanResult");
|
||||
|
||||
if (_abortScan)
|
||||
return;
|
||||
|
||||
@@ -474,14 +533,10 @@ namespace lms::scanner
|
||||
void ScanStepScanFiles::processFileMetaData(ScanContext& context, const std::filesystem::path& file, const metadata::Track& trackMetadata, const ScannerSettings::MediaLibraryInfo& libraryInfo)
|
||||
{
|
||||
ScanStats& stats{ context.stats };
|
||||
Wt::WDateTime lastWriteTime;
|
||||
try
|
||||
|
||||
const std::optional<FileInfo> fileInfo{ retrieveFileInfo(file, libraryInfo.rootDirectory) };
|
||||
if (!fileInfo)
|
||||
{
|
||||
lastWriteTime = core::pathUtils::getLastWriteTime(file);
|
||||
}
|
||||
catch (core::LmsException& e)
|
||||
{
|
||||
LMS_LOG(DBUPDATER, ERROR, e.what());
|
||||
stats.skips++;
|
||||
return;
|
||||
}
|
||||
@@ -493,23 +548,23 @@ namespace lms::scanner
|
||||
{
|
||||
std::vector<Track::pointer> duplicateTracks{ Track::findByMBID(dbSession, *trackMetadata.mbid) };
|
||||
|
||||
// find for existing MBIDs as the file may have just been moved
|
||||
// find for an existing track MBID as the file may have just been moved
|
||||
if (!track && duplicateTracks.size() == 1)
|
||||
{
|
||||
Track::pointer otherTrack{ duplicateTracks.front() };
|
||||
std::error_code ec;
|
||||
if (!std::filesystem::exists(otherTrack->getPath(), ec))
|
||||
if (!std::filesystem::exists(otherTrack->getAbsoluteFilePath(), ec))
|
||||
{
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Considering track '" << file.string() << "' moved from '" << otherTrack->getPath() << "'");
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Considering track '" << file.string() << "' moved from '" << otherTrack->getAbsoluteFilePath() << "'");
|
||||
track = otherTrack;
|
||||
track.modify()->setPath(file);
|
||||
track.modify()->setAbsoluteFilePath(file);
|
||||
}
|
||||
}
|
||||
|
||||
// Skip duplicate track MBID
|
||||
if (_settings.skipDuplicateMBID)
|
||||
{
|
||||
for (Track::pointer otherTrack : duplicateTracks)
|
||||
for (Track::pointer& otherTrack : duplicateTracks)
|
||||
{
|
||||
// Skip ourselves
|
||||
if (track && track->getId() == otherTrack->getId())
|
||||
@@ -525,7 +580,7 @@ namespace lms::scanner
|
||||
continue;
|
||||
}
|
||||
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Skipped '" << file.string() << "' (similar MBID in '" << otherTrack->getPath().string() << "')");
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Skipped '" << file.string() << "' (similar MBID in '" << otherTrack->getAbsoluteFilePath().string() << "')");
|
||||
// As this MBID already exists, just remove what we just scanned
|
||||
if (track)
|
||||
{
|
||||
@@ -565,22 +620,21 @@ namespace lms::scanner
|
||||
|
||||
// If file already exists, update its data
|
||||
// Otherwise, create it
|
||||
bool added{};
|
||||
if (!track)
|
||||
{
|
||||
track = dbSession.create<Track>(file);
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Adding '" << file.string() << "'");
|
||||
stats.additions++;
|
||||
}
|
||||
else
|
||||
{
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Updating '" << file.string() << "'");
|
||||
|
||||
stats.updates++;
|
||||
track = dbSession.create<Track>();
|
||||
track.modify()->setAbsoluteFilePath(file);
|
||||
added = true;
|
||||
}
|
||||
|
||||
// Track related data
|
||||
assert(track);
|
||||
|
||||
track.modify()->setRelativeFilePath(fileInfo->relativePath);
|
||||
track.modify()->setFileSize(fileInfo->fileSize);
|
||||
track.modify()->setLastWriteTime(fileInfo->lastWriteTime);
|
||||
|
||||
track.modify()->setMediaLibrary(MediaLibrary::find(dbSession, libraryInfo.id)); // may be null if settings are updated in // => next scan will correct this
|
||||
track.modify()->clearArtistLinks();
|
||||
// Do not fallback on artists with the same name but having a MBID for artist and releaseArtists, as it may be corrected by properly tagging files
|
||||
@@ -628,7 +682,6 @@ namespace lms::scanner
|
||||
track.modify()->setReleaseReplayGain(trackMetadata.medium ? trackMetadata.medium->replayGain : std::nullopt);
|
||||
track.modify()->setDiscSubtitle(trackMetadata.medium ? trackMetadata.medium->name : "");
|
||||
track.modify()->setClusters(getOrCreateClusters(dbSession, trackMetadata));
|
||||
track.modify()->setLastWriteTime(lastWriteTime);
|
||||
track.modify()->setName(title);
|
||||
track.modify()->setDuration(trackMetadata.duration);
|
||||
track.modify()->setBitrate(trackMetadata.bitrate);
|
||||
@@ -657,5 +710,16 @@ namespace lms::scanner
|
||||
track.modify()->setCopyrightURL(trackMetadata.copyrightURL);
|
||||
track.modify()->setTrackReplayGain(trackMetadata.replayGain);
|
||||
track.modify()->setArtistDisplayName(trackMetadata.artistDisplayName);
|
||||
|
||||
if (added)
|
||||
{
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Added '" << file.string() << "'");
|
||||
stats.additions++;
|
||||
}
|
||||
else
|
||||
{
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Updated '" << file.string() << "'");
|
||||
stats.updates++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace lms::api::subsonic
|
||||
if (!track)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
parameters.inputParameters.trackPath = track->getPath();
|
||||
parameters.inputParameters.trackPath = track->getAbsoluteFilePath();
|
||||
parameters.inputParameters.duration = track->getDuration();
|
||||
parameters.estimateContentLength = estimateContentLength;
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace lms::api::subsonic
|
||||
// same codec => apply max bitrate
|
||||
// otherwise => apply default bitrate (because we can't really compare bitrates between formats) + max bitrate)
|
||||
std::size_t bitrate{};
|
||||
if (requestedFormat && isOutputFormatCompatible(track->getPath(), *requestedFormat))
|
||||
if (requestedFormat && isOutputFormatCompatible(track->getAbsoluteFilePath(), *requestedFormat))
|
||||
{
|
||||
if (maxBitRate == 0 || track->getBitrate() <= maxBitRate)
|
||||
{
|
||||
@@ -205,7 +205,7 @@ namespace lms::api::subsonic
|
||||
if (!track)
|
||||
throw RequestedDataNotFoundError{};
|
||||
|
||||
trackPath = track->getPath();
|
||||
trackPath = track->getAbsoluteFilePath();
|
||||
}
|
||||
|
||||
resourceHandler = av::createRawResourceHandler(trackPath);
|
||||
|
||||
@@ -59,39 +59,6 @@ namespace lms::api::subsonic
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string getTrackPath(const Track::pointer& track)
|
||||
{
|
||||
std::string path;
|
||||
|
||||
// The track path has to be relative from the root
|
||||
const auto release{ track->getRelease() };
|
||||
if (release)
|
||||
{
|
||||
auto artists{ release->getReleaseArtists() };
|
||||
if (artists.empty())
|
||||
artists = release->getArtists();
|
||||
|
||||
if (artists.size() > 1)
|
||||
path = "Various Artists/";
|
||||
else if (artists.size() == 1)
|
||||
path = utils::makeNameFilesystemCompatible(artists.front()->getName()) + "/";
|
||||
|
||||
path += utils::makeNameFilesystemCompatible(track->getRelease()->getName()) + "/";
|
||||
}
|
||||
|
||||
if (track->getDiscNumber())
|
||||
path += std::to_string(*track->getDiscNumber()) + "-";
|
||||
if (track->getTrackNumber())
|
||||
path += std::to_string(*track->getTrackNumber()) + "-";
|
||||
|
||||
path += utils::makeNameFilesystemCompatible(track->getName());
|
||||
|
||||
if (track->getPath().has_extension())
|
||||
path += track->getPath().extension();
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
Response::Node createSongNode(RequestContext& context, const Track::pointer& track, const User::pointer& user)
|
||||
@@ -110,19 +77,13 @@ namespace lms::api::subsonic
|
||||
if (track->getYear())
|
||||
trackResponse.setAttribute("year", *track->getYear());
|
||||
trackResponse.setAttribute("playCount", core::Service<scrobbling::IScrobblingService>::get()->getCount(user->getId(), 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)
|
||||
trackResponse.setAttribute("size", fileSize);
|
||||
}
|
||||
trackResponse.setAttribute("path", track->getRelativeFilePath().string());
|
||||
trackResponse.setAttribute("size", track->getFileSize());
|
||||
|
||||
if (track->getPath().has_extension())
|
||||
if (track->getAbsoluteFilePath().has_extension())
|
||||
{
|
||||
auto extension{ track->getPath().extension() };
|
||||
trackResponse.setAttribute("suffix", extension.string().substr(1));
|
||||
auto extension{ track->getAbsoluteFilePath().extension() };
|
||||
trackResponse.setAttribute("suffix", extension.string().substr(1) /* skip leading .*/);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -157,7 +118,7 @@ namespace lms::api::subsonic
|
||||
trackResponse.setAttribute("bitRate", (track->getBitrate() / 1000));
|
||||
trackResponse.setAttribute("type", "music");
|
||||
trackResponse.setAttribute("created", core::stringUtils::toISO8601String(track->getLastWritten()));
|
||||
trackResponse.setAttribute("contentType", av::getMimeType(track->getPath().extension()));
|
||||
trackResponse.setAttribute("contentType", av::getMimeType(track->getAbsoluteFilePath().extension()));
|
||||
|
||||
if (const Wt::WDateTime dateTime{ core::Service<feedback::IFeedbackService>::get()->getStarredDateTime(user->getId(), track->getId()) }; dateTime.isValid())
|
||||
trackResponse.setAttribute("starred", core::stringUtils::toISO8601String(dateTime));
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace lms::ui
|
||||
if (!track)
|
||||
continue;
|
||||
|
||||
response.out() << track->getPath().string();
|
||||
response.out() << track->getAbsoluteFilePath().string();
|
||||
if (auto mbid{ track->getTrackMBID() })
|
||||
response.out() << " (Track MBID " << mbid->getAsString() << ")";
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace lms::ui
|
||||
// TODO: save in DB and aggregate all this
|
||||
for (const Track::pointer& track : Track::find(LmsApp->getDbSession(), Track::FindParameters{}.setRelease(releaseId).setRange(Range{ 0, 1 })).results)
|
||||
{
|
||||
if (const auto audioFile{ av::parseAudioFile(track->getPath()) })
|
||||
if (const auto audioFile{ av::parseAudioFile(track->getAbsoluteFilePath()) })
|
||||
{
|
||||
const std::optional<av::StreamInfo> audioStream{ audioFile->getBestStreamInfo() };
|
||||
if (audioStream)
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace lms::ui::TrackListHelpers
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto audioFile{ av::parseAudioFile(track->getPath()) })
|
||||
if (const auto audioFile{ av::parseAudioFile(track->getAbsoluteFilePath()) })
|
||||
{
|
||||
const std::optional<av::StreamInfo> audioStream{ audioFile->getBestStreamInfo() };
|
||||
if (audioStream)
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace lms::ui
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return track->getPath();
|
||||
return track->getAbsoluteFilePath();
|
||||
}
|
||||
|
||||
std::optional<std::filesystem::path> getTrackPathFromURLArgs(const Wt::Http::Request& request)
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace lms::ui
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
parameters.inputParameters.trackPath = track->getPath();
|
||||
parameters.inputParameters.trackPath = track->getAbsoluteFilePath();
|
||||
parameters.inputParameters.duration = track->getDuration();
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace lms::ui
|
||||
if (auto trackNumber{ track->getTrackNumber() })
|
||||
fileName << std::setw(2) << std::setfill('0') << *trackNumber << " - ";
|
||||
|
||||
fileName << core::stringUtils::replaceInString(track->getName(), "/", "_") << track->getPath().filename().extension().string();
|
||||
fileName << core::stringUtils::replaceInString(track->getName(), "/", "_") << track->getAbsoluteFilePath().extension().string();
|
||||
|
||||
return fileName.str();
|
||||
}
|
||||
@@ -152,7 +152,7 @@ namespace lms::ui
|
||||
fileName += releaseName + "/";
|
||||
fileName += getTrackPathName(track);
|
||||
|
||||
files.emplace_back(zip::Entry{ fileName, track->getPath() });
|
||||
files.emplace_back(zip::Entry{ fileName, track->getAbsoluteFilePath() });
|
||||
}
|
||||
|
||||
return zip::createArchiveZipper(files);
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace lms
|
||||
|
||||
for (std::size_t i{}; i < params.trackCountPerRelease; ++i)
|
||||
{
|
||||
Track::pointer track{ context.session.create<Track>(params.trackPath) };
|
||||
Track::pointer track{ context.session.create<Track>() };
|
||||
|
||||
track.modify()->setName("Track-" + std::string{ core::UUID::generate().getAsString() });
|
||||
track.modify()->setDiscNumber(1);
|
||||
|
||||
Reference in New Issue
Block a user