Moved scanner specific code from core
This commit is contained in:
@@ -35,63 +35,6 @@ namespace lms::core::pathUtils
|
|||||||
return std::filesystem::create_directory(dir);
|
return std::filesystem::create_directory(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool exploreFilesRecursive(const std::filesystem::path& directory, ExploreFileCallback cb, const std::filesystem::path* excludeDirFileName)
|
|
||||||
{
|
|
||||||
std::error_code ec;
|
|
||||||
std::filesystem::directory_iterator itPath{ directory, std::filesystem::directory_options::follow_directory_symlink, ec };
|
|
||||||
|
|
||||||
if (ec)
|
|
||||||
{
|
|
||||||
cb(ec, directory, nullptr);
|
|
||||||
return true; // try to continue exploring anyway
|
|
||||||
}
|
|
||||||
|
|
||||||
if (excludeDirFileName && !excludeDirFileName->empty())
|
|
||||||
{
|
|
||||||
const std::filesystem::path excludePath{ directory / *excludeDirFileName };
|
|
||||||
|
|
||||||
if (std::filesystem::exists(excludePath, ec))
|
|
||||||
{
|
|
||||||
// TODO: handle exclude another way + remove this log
|
|
||||||
LMS_LOG(DBUPDATER, DEBUG, "Found " << excludePath << ": skipping directory");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::filesystem::directory_iterator itEnd;
|
|
||||||
while (itPath != itEnd)
|
|
||||||
{
|
|
||||||
bool continueExploring{ true };
|
|
||||||
|
|
||||||
if (ec)
|
|
||||||
{
|
|
||||||
continueExploring = cb(ec, *itPath, nullptr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const std::filesystem::directory_entry& entry{ *itPath };
|
|
||||||
|
|
||||||
if (entry.is_regular_file())
|
|
||||||
{
|
|
||||||
FileInfo fileInfo;
|
|
||||||
fileInfo.fileSize = entry.file_size();
|
|
||||||
fileInfo.lastWriteTime = Wt::WDateTime{ std::chrono::file_clock::to_sys(entry.last_write_time()) };
|
|
||||||
|
|
||||||
continueExploring = cb(ec, *itPath, &fileInfo);
|
|
||||||
}
|
|
||||||
else if (entry.is_directory())
|
|
||||||
continueExploring = exploreFilesRecursive(*itPath, cb, excludeDirFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!continueExploring)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
itPath.increment(ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasFileAnyExtension(const std::filesystem::path& file, std::span<const std::filesystem::path> supportedExtensions)
|
bool hasFileAnyExtension(const std::filesystem::path& file, std::span<const std::filesystem::path> supportedExtensions)
|
||||||
{
|
{
|
||||||
const std::filesystem::path extension{ stringUtils::stringToLower(file.extension().c_str()) };
|
const std::filesystem::path extension{ stringUtils::stringToLower(file.extension().c_str()) };
|
||||||
|
|||||||
@@ -20,9 +20,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <functional>
|
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <system_error>
|
|
||||||
|
|
||||||
#include <Wt/WDateTime.h>
|
#include <Wt/WDateTime.h>
|
||||||
|
|
||||||
@@ -32,15 +30,6 @@ namespace lms::core::pathUtils
|
|||||||
// Create it if needed
|
// Create it if needed
|
||||||
bool ensureDirectory(const std::filesystem::path& dir);
|
bool ensureDirectory(const std::filesystem::path& dir);
|
||||||
|
|
||||||
struct FileInfo
|
|
||||||
{
|
|
||||||
Wt::WDateTime lastWriteTime; // Last write time of the file since Epoch
|
|
||||||
std::uint64_t fileSize{}; // Size of the file in bytes
|
|
||||||
};
|
|
||||||
using ExploreFileCallback = std::function<bool(std::error_code, const std::filesystem::path&, const FileInfo* fileInfo)>;
|
|
||||||
// returns false if aborted by user
|
|
||||||
bool exploreFilesRecursive(const std::filesystem::path& directory, ExploreFileCallback cb, const std::filesystem::path* excludeDirFileName = {});
|
|
||||||
|
|
||||||
// Check if file's extension is one of provided extensions
|
// Check if file's extension is one of provided extensions
|
||||||
bool hasFileAnyExtension(const std::filesystem::path& file, std::span<const std::filesystem::path> extensions);
|
bool hasFileAnyExtension(const std::filesystem::path& file, std::span<const std::filesystem::path> extensions);
|
||||||
|
|
||||||
|
|||||||
@@ -154,10 +154,7 @@ namespace lms::metadata::taglib::utils
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (file && !file->isValid())
|
if (file && !file->isValid())
|
||||||
{
|
|
||||||
LMS_LOG(METADATA, DEBUG, "File " << file << ": failed to parse by extension");
|
|
||||||
file.reset();
|
file.reset();
|
||||||
}
|
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
@@ -208,10 +205,7 @@ namespace lms::metadata::taglib::utils
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (file && !file->isValid())
|
if (file && !file->isValid())
|
||||||
{
|
|
||||||
LMS_LOG(METADATA, DEBUG, "File " << file << ": failed to parse by content");
|
|
||||||
file.reset();
|
file.reset();
|
||||||
}
|
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
@@ -223,7 +217,12 @@ namespace lms::metadata::taglib::utils
|
|||||||
TagLib::FileStream fileStream{ createFileStream(p) };
|
TagLib::FileStream fileStream{ createFileStream(p) };
|
||||||
std::unique_ptr<TagLib::File> file{ parseFileByExtension(&fileStream, p.extension(), readStyle, readAudioProperties.value()) };
|
std::unique_ptr<TagLib::File> file{ parseFileByExtension(&fileStream, p.extension(), readStyle, readAudioProperties.value()) };
|
||||||
if (!file)
|
if (!file)
|
||||||
|
{
|
||||||
|
LMS_LOG(METADATA, DEBUG, "File " << p << ": failed to parse by extension");
|
||||||
file = parseFileByContent(&fileStream, readStyle, readAudioProperties.value());
|
file = parseFileByContent(&fileStream, readStyle, readAudioProperties.value());
|
||||||
|
if (!file)
|
||||||
|
LMS_LOG(METADATA, DEBUG, "File " << p << ": failed to parse by content");
|
||||||
|
}
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,10 +37,59 @@
|
|||||||
|
|
||||||
namespace lms::scanner
|
namespace lms::scanner
|
||||||
{
|
{
|
||||||
using namespace db;
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
using ExploreFileCallback = std::function<bool(std::error_code, const std::filesystem::path& path, const std::filesystem::directory_entry*)>;
|
||||||
|
bool exploreFilesRecursive(const std::filesystem::path& directory, ExploreFileCallback cb, const std::filesystem::path* excludeDirFileName)
|
||||||
|
{
|
||||||
|
std::error_code ec;
|
||||||
|
std::filesystem::directory_iterator itPath{ directory, std::filesystem::directory_options::follow_directory_symlink, ec };
|
||||||
|
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
cb(ec, directory, nullptr);
|
||||||
|
return true; // try to continue exploring anyway
|
||||||
|
}
|
||||||
|
|
||||||
|
if (excludeDirFileName && !excludeDirFileName->empty())
|
||||||
|
{
|
||||||
|
const std::filesystem::path excludePath{ directory / *excludeDirFileName };
|
||||||
|
if (std::filesystem::exists(excludePath, ec))
|
||||||
|
{
|
||||||
|
LMS_LOG(DBUPDATER, DEBUG, "Found " << excludePath << ": skipping directory");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::filesystem::directory_iterator itEnd;
|
||||||
|
while (itPath != itEnd)
|
||||||
|
{
|
||||||
|
bool continueExploring{ true };
|
||||||
|
|
||||||
|
const std::filesystem::directory_entry& entry{ *itPath };
|
||||||
|
const std::filesystem::path& path{ entry.path() };
|
||||||
|
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
continueExploring = cb(ec, path, nullptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (entry.is_regular_file())
|
||||||
|
continueExploring = cb(ec, path, &entry);
|
||||||
|
else if (entry.is_directory())
|
||||||
|
continueExploring = exploreFilesRecursive(path, cb, excludeDirFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!continueExploring)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
itPath.increment(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
class FileScanJob : public core::IJob
|
class FileScanJob : public core::IJob
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -97,11 +146,11 @@ namespace lms::scanner
|
|||||||
std::vector<std::unique_ptr<core::IJob>> jobsDone;
|
std::vector<std::unique_ptr<core::IJob>> jobsDone;
|
||||||
std::vector<std::unique_ptr<IFileScanOperation>> scanOperations;
|
std::vector<std::unique_ptr<IFileScanOperation>> scanOperations;
|
||||||
|
|
||||||
core::pathUtils::exploreFilesRecursive(
|
exploreFilesRecursive(
|
||||||
mediaLibrary.rootDirectory, [&](std::error_code ec, const std::filesystem::path& path, const core::pathUtils::FileInfo* fileInfo) {
|
mediaLibrary.rootDirectory, [&](std::error_code ec, const std::filesystem::path& path, const std::filesystem::directory_entry* fileEntry) {
|
||||||
LMS_SCOPED_TRACE_DETAILED("Scanner", "OnExploreFile");
|
LMS_SCOPED_TRACE_DETAILED("Scanner", "OnExploreFile");
|
||||||
|
|
||||||
assert((ec && !fileInfo) || (!ec && fileInfo));
|
assert((ec && !fileEntry) || (!ec && fileEntry));
|
||||||
|
|
||||||
if (_abortScan)
|
if (_abortScan)
|
||||||
return false; // stop iterating
|
return false; // stop iterating
|
||||||
@@ -117,8 +166,8 @@ namespace lms::scanner
|
|||||||
|
|
||||||
fileToScan.filePath = path;
|
fileToScan.filePath = path;
|
||||||
fileToScan.mediaLibrary = mediaLibrary;
|
fileToScan.mediaLibrary = mediaLibrary;
|
||||||
fileToScan.lastWriteTime.setTime_t(fileInfo->lastWriteTime.toTime_t()); // sec resolution, as stored in the database
|
fileToScan.lastWriteTime.setTime_t(Wt::WDateTime{ std::chrono::file_clock::to_sys(fileEntry->last_write_time()) }.toTime_t()); // sec resolution, as stored in the database
|
||||||
fileToScan.fileSize = fileInfo->fileSize;
|
fileToScan.fileSize = fileEntry->file_size();
|
||||||
|
|
||||||
if (context.scanOptions.fullScan || scanner->needsScan(fileToScan))
|
if (context.scanOptions.fullScan || scanner->needsScan(fileToScan))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user