Subsonic API: added a way to filter files per media folder id when using directory commands
This commit is contained in:
@@ -205,6 +205,9 @@ namespace lms::scanner
|
||||
|
||||
void ScanStepAssociateArtistImages::process(ScanContext& context)
|
||||
{
|
||||
if (_abortScan)
|
||||
return;
|
||||
|
||||
if (context.stats.nbChanges() == 0)
|
||||
return;
|
||||
|
||||
@@ -224,6 +227,9 @@ namespace lms::scanner
|
||||
ArtistImageAssociationContainer artistImageAssociations;
|
||||
while (fetchNextArtistImagesToUpdate(searchContext, artistImageAssociations))
|
||||
{
|
||||
if (_abortScan)
|
||||
return;
|
||||
|
||||
updateArtistImages(session, artistImageAssociations);
|
||||
context.currentStepStats.processedElems += readBatchSize;
|
||||
_progressCallback(context.currentStepStats);
|
||||
|
||||
@@ -104,18 +104,20 @@ namespace lms::scanner
|
||||
return res;
|
||||
}
|
||||
|
||||
Directory::pointer getOrCreateDirectory(Session& session, const std::filesystem::path& path, const std::filesystem::path& rootPath)
|
||||
Directory::pointer getOrCreateDirectory(Session& session, const std::filesystem::path& path, const MediaLibrary::pointer& mediaLibrary)
|
||||
{
|
||||
Directory::pointer directory{ Directory::find(session, path) };
|
||||
if (!directory)
|
||||
{
|
||||
Directory::pointer parentDirectory;
|
||||
if (path != rootPath)
|
||||
parentDirectory = getOrCreateDirectory(session, path.parent_path(), rootPath);
|
||||
if (path != mediaLibrary->getPath())
|
||||
parentDirectory = getOrCreateDirectory(session, path.parent_path(), mediaLibrary);
|
||||
|
||||
directory = session.create<Directory>(path);
|
||||
directory.modify()->setParent(parentDirectory);
|
||||
directory.modify()->setMediaLibrary(mediaLibrary);
|
||||
}
|
||||
// Don't update library if it does not match, will be updated elsewhere
|
||||
|
||||
return directory;
|
||||
}
|
||||
@@ -350,12 +352,13 @@ namespace lms::scanner
|
||||
|
||||
std::vector<FileScanResult> scanResults;
|
||||
|
||||
std::filesystem::path currentDirectory;
|
||||
core::pathUtils::exploreFilesRecursive(
|
||||
mediaLibrary.rootDirectory, [&](std::error_code ec, const std::filesystem::path& path) {
|
||||
LMS_SCOPED_TRACE_DETAILED("Scanner", "OnExploreFile");
|
||||
|
||||
if (_abortScan)
|
||||
return false;
|
||||
return false; // stop iterating
|
||||
|
||||
if (ec)
|
||||
{
|
||||
@@ -364,22 +367,33 @@ namespace lms::scanner
|
||||
}
|
||||
else
|
||||
{
|
||||
bool fileToProcess{};
|
||||
bool fileMatched{};
|
||||
if (core::pathUtils::hasFileAnyExtension(path, _settings.supportedAudioFileExtensions))
|
||||
{
|
||||
fileToProcess = true;
|
||||
fileMatched = true;
|
||||
if (checkAudioFileNeedScan(context, path, mediaLibrary))
|
||||
_fileScanQueue.pushScanRequest(path, FileScanQueue::ScanRequestType::AudioFile);
|
||||
}
|
||||
else if (core::pathUtils::hasFileAnyExtension(path, _settings.supportedImageFileExtensions))
|
||||
{
|
||||
fileToProcess = true;
|
||||
fileMatched = true;
|
||||
if (checkImageFileNeedScan(context, path))
|
||||
_fileScanQueue.pushScanRequest(path, FileScanQueue::ScanRequestType::ImageFile);
|
||||
}
|
||||
|
||||
if (fileToProcess)
|
||||
if (fileMatched)
|
||||
{
|
||||
// Not very efficient way to update media_library for directories
|
||||
if (path.has_parent_path())
|
||||
{
|
||||
const std::filesystem::path directory{ path.parent_path() };
|
||||
if (directory != currentDirectory)
|
||||
{
|
||||
updateDirectoryIfNeeded(currentDirectory, mediaLibrary);
|
||||
currentDirectory = directory;
|
||||
}
|
||||
}
|
||||
|
||||
context.currentStepStats.processedElems++;
|
||||
_progressCallback(context.currentStepStats);
|
||||
}
|
||||
@@ -415,17 +429,19 @@ namespace lms::scanner
|
||||
return false;
|
||||
}
|
||||
|
||||
if (context.scanOptions.fullScan)
|
||||
return true;
|
||||
|
||||
bool needUpdateLibrary{};
|
||||
if (!context.scanOptions.fullScan)
|
||||
db::Session& dbSession{ _db.getTLSSession() };
|
||||
|
||||
{
|
||||
auto transaction{ dbSession.createReadTransaction() };
|
||||
|
||||
// Skip file if last write is the same
|
||||
db::Session& dbSession{ _db.getTLSSession() };
|
||||
auto transaction{ _db.getTLSSession().createReadTransaction() };
|
||||
|
||||
const Track::pointer track{ Track::findByPath(dbSession, file) };
|
||||
|
||||
if (track
|
||||
&& track->getLastWriteTime().toTime_t() == lastWriteTime.toTime_t()
|
||||
&& track->getLastWriteTime() == lastWriteTime
|
||||
&& track->getScanVersion() == _settings.scanVersion)
|
||||
{
|
||||
// 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
|
||||
@@ -442,8 +458,7 @@ namespace lms::scanner
|
||||
|
||||
if (needUpdateLibrary)
|
||||
{
|
||||
db::Session& dbSession{ _db.getTLSSession() };
|
||||
auto transaction{ _db.getTLSSession().createWriteTransaction() };
|
||||
auto transaction{ dbSession.createWriteTransaction() };
|
||||
|
||||
Track::pointer track{ Track::findByPath(dbSession, file) };
|
||||
assert(track);
|
||||
@@ -632,8 +647,9 @@ namespace lms::scanner
|
||||
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()->setDirectory(getOrCreateDirectory(dbSession, file.parent_path(), libraryInfo.rootDirectory));
|
||||
MediaLibrary::pointer mediaLibrary{ MediaLibrary::find(dbSession, libraryInfo.id) }; // may be null if settings are updated in // => next scan will correct this
|
||||
track.modify()->setMediaLibrary(mediaLibrary);
|
||||
track.modify()->setDirectory(getOrCreateDirectory(dbSession, file.parent_path(), mediaLibrary));
|
||||
|
||||
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
|
||||
@@ -762,7 +778,8 @@ namespace lms::scanner
|
||||
image.modify()->setFileSize(fileInfo->fileSize);
|
||||
image.modify()->setHeight(imageInfo->height);
|
||||
image.modify()->setWidth(imageInfo->width);
|
||||
image.modify()->setDirectory(getOrCreateDirectory(dbSession, file.parent_path(), libraryInfo.rootDirectory));
|
||||
MediaLibrary::pointer mediaLibrary{ MediaLibrary::find(dbSession, libraryInfo.id) }; // may be null if settings are updated in // => next scan will correct this
|
||||
image.modify()->setDirectory(getOrCreateDirectory(dbSession, file.parent_path(), mediaLibrary));
|
||||
|
||||
if (added)
|
||||
{
|
||||
@@ -775,4 +792,34 @@ namespace lms::scanner
|
||||
stats.updates++;
|
||||
}
|
||||
}
|
||||
|
||||
void ScanStepScanFiles::updateDirectoryIfNeeded(const std::filesystem::path& dirPath, const ScannerSettings::MediaLibraryInfo& libraryInfo)
|
||||
{
|
||||
db::Session& dbSession{ _db.getTLSSession() };
|
||||
|
||||
const bool needUpdateLibrary{ [&] {
|
||||
auto transaction{ dbSession.createReadTransaction() };
|
||||
|
||||
Directory::pointer directory{ Directory::find(dbSession, dirPath) };
|
||||
if (!directory)
|
||||
return false; // we create directories only of we find images or tracks inside
|
||||
|
||||
MediaLibrary::pointer currentLibrary{ directory->getMediaLibrary() };
|
||||
return !currentLibrary || currentLibrary->getId() != libraryInfo.id;
|
||||
}() };
|
||||
|
||||
if (needUpdateLibrary)
|
||||
{
|
||||
auto transaction{ dbSession.createWriteTransaction() };
|
||||
|
||||
Directory::pointer directory{ Directory::find(dbSession, dirPath) };
|
||||
assert(directory);
|
||||
directory.modify()->setMediaLibrary(MediaLibrary::find(dbSession, libraryInfo.id)); // may be null if settings are updated in // => next scan will correct this
|
||||
}
|
||||
|
||||
if (dirPath != libraryInfo.rootDirectory && dirPath.has_parent_path())
|
||||
{
|
||||
updateDirectoryIfNeeded(dirPath.parent_path(), libraryInfo);
|
||||
}
|
||||
}
|
||||
} // namespace lms::scanner
|
||||
|
||||
@@ -49,6 +49,8 @@ namespace lms::scanner
|
||||
void processAudioFileScanData(ScanContext& context, const std::filesystem::path& path, const metadata::Track* trackMetadata, const ScannerSettings::MediaLibraryInfo& libraryInfo);
|
||||
void processImageFileScanData(ScanContext& context, const std::filesystem::path& path, const ImageInfo* imageInfo, const ScannerSettings::MediaLibraryInfo& libraryInfo);
|
||||
|
||||
void updateDirectoryIfNeeded(const std::filesystem::path& directory, const ScannerSettings::MediaLibraryInfo& libraryInfo);
|
||||
|
||||
std::unique_ptr<metadata::IParser> _metadataParser;
|
||||
const std::vector<std::string> _extraTagsToParse;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user