Try to reuse the db track entry if the track file just moved, fixes #612
This commit is contained in:
@@ -256,6 +256,7 @@ namespace lms::db
|
|||||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_media_library_release_idx ON track(media_library_id, release_id)");
|
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_media_library_release_idx ON track(media_library_id, release_id)");
|
||||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_mbid_idx ON track(mbid)");
|
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_mbid_idx ON track(mbid)");
|
||||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_name_idx ON track(name)");
|
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_name_idx ON track(name)");
|
||||||
|
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_name_file_size_idx ON track(name, file_size)");
|
||||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_name_nocase_idx ON track(name COLLATE NOCASE)");
|
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_name_nocase_idx ON track(name COLLATE NOCASE)");
|
||||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_original_date_idx ON track(original_date)");
|
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_original_date_idx ON track(original_date)");
|
||||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_recording_mbid_idx ON track(recording_mbid)");
|
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_recording_mbid_idx ON track(recording_mbid)");
|
||||||
|
|||||||
@@ -180,6 +180,9 @@ namespace lms::db
|
|||||||
if (params.hasEmbeddedImage.has_value())
|
if (params.hasEmbeddedImage.has_value())
|
||||||
query.where("t.has_cover = ?").bind(params.hasEmbeddedImage.value());
|
query.where("t.has_cover = ?").bind(params.hasEmbeddedImage.value());
|
||||||
|
|
||||||
|
if (params.fileSize.has_value())
|
||||||
|
query.where("t.file_size = ?").bind(static_cast<long long>(params.fileSize.value()));
|
||||||
|
|
||||||
switch (params.sortMethod)
|
switch (params.sortMethod)
|
||||||
{
|
{
|
||||||
case TrackSortMethod::None:
|
case TrackSortMethod::None:
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ namespace lms::db
|
|||||||
std::optional<int> discNumber; // matching this disc number
|
std::optional<int> discNumber; // matching this disc number
|
||||||
DirectoryId directory; // if set, tracks in this directory
|
DirectoryId directory; // if set, tracks in this directory
|
||||||
std::optional<bool> hasEmbeddedImage; // if set, tracks that have or not embedded images
|
std::optional<bool> hasEmbeddedImage; // if set, tracks that have or not embedded images
|
||||||
|
std::optional<std::size_t> fileSize; // if set, tracks that match this file size
|
||||||
|
|
||||||
FindParameters& setFilters(const Filters& _filters)
|
FindParameters& setFilters(const Filters& _filters)
|
||||||
{
|
{
|
||||||
@@ -186,6 +187,11 @@ namespace lms::db
|
|||||||
hasEmbeddedImage = _hasEmbeddedImage;
|
hasEmbeddedImage = _hasEmbeddedImage;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
FindParameters& setFileSize(std::optional<std::size_t> _fileSize)
|
||||||
|
{
|
||||||
|
fileSize = _fileSize;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Track() = default;
|
Track() = default;
|
||||||
|
|||||||
@@ -345,6 +345,45 @@ namespace lms::scanner
|
|||||||
return db::Advisory::UnSet;
|
return db::Advisory::UnSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db::Track::pointer findMovedTrackBySizeAndMetaData(db::Session& session, const metadata::Track& parsedTrack, const FileInfo& fileInfo)
|
||||||
|
{
|
||||||
|
db::Track::FindParameters params;
|
||||||
|
// Add as many fields as possible to limit errors
|
||||||
|
params.setName(parsedTrack.title);
|
||||||
|
if (parsedTrack.medium)
|
||||||
|
{
|
||||||
|
if (parsedTrack.medium->position)
|
||||||
|
params.setDiscNumber(*parsedTrack.medium->position);
|
||||||
|
if (parsedTrack.medium->release)
|
||||||
|
params.setReleaseName(parsedTrack.medium->release->name);
|
||||||
|
}
|
||||||
|
if (parsedTrack.position)
|
||||||
|
params.setTrackNumber(*parsedTrack.position);
|
||||||
|
params.setHasEmbeddedImage(parsedTrack.hasCover);
|
||||||
|
params.setFileSize(fileInfo.fileSize);
|
||||||
|
|
||||||
|
bool error{};
|
||||||
|
db::Track::pointer res;
|
||||||
|
db::Track::find(session, params, [&](const db::Track::pointer& track) {
|
||||||
|
// Check that the track is truly no longer where it was during the last scan
|
||||||
|
std::error_code ec;
|
||||||
|
if (std::filesystem::exists(track->getAbsoluteFilePath(), ec))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
LMS_LOG(DBUPDATER, DEBUG, "Found too many candidates for file move. New file = " << fileInfo.relativePath << ", candidate = " << track->getAbsoluteFilePath() << ", previous candidate = " << res->getAbsoluteFilePath());
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
res = track;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
res = db::Track::pointer{};
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
class AudioFileScanOperation : public IFileScanOperation
|
class AudioFileScanOperation : public IFileScanOperation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -463,6 +502,17 @@ namespace lms::scanner
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!track)
|
||||||
|
{
|
||||||
|
// maybe the file just moved?
|
||||||
|
track = findMovedTrackBySizeAndMetaData(dbSession, *_parsedTrack, *fileInfo);
|
||||||
|
if (track)
|
||||||
|
{
|
||||||
|
LMS_LOG(DBUPDATER, DEBUG, "Considering track " << _file << " moved from " << track->getAbsoluteFilePath());
|
||||||
|
track.modify()->setAbsoluteFilePath(_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We estimate this is an audio file if the duration is not null
|
// We estimate this is an audio file if the duration is not null
|
||||||
if (_parsedTrack->audioProperties.duration == std::chrono::milliseconds::zero())
|
if (_parsedTrack->audioProperties.duration == std::chrono::milliseconds::zero())
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user