Subsonic API: added a way to filter files per media folder id when using directory commands
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "database/Directory.hpp"
|
#include "database/Directory.hpp"
|
||||||
|
|
||||||
|
#include "database/MediaLibrary.hpp"
|
||||||
#include "database/Session.hpp"
|
#include "database/Session.hpp"
|
||||||
|
|
||||||
#include "IdTypeTraits.hpp"
|
#include "IdTypeTraits.hpp"
|
||||||
@@ -43,12 +44,15 @@ namespace lms::db
|
|||||||
query.groupBy("d.id");
|
query.groupBy("d.id");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params.mediaLibrary.isValid())
|
||||||
|
query.where("d.media_library_id = ?").bind(params.mediaLibrary);
|
||||||
|
|
||||||
if (params.parentDirectory.isValid())
|
if (params.parentDirectory.isValid())
|
||||||
query.where("d.parent_directory_id = ?").bind(params.parentDirectory);
|
query.where("d.parent_directory_id = ?").bind(params.parentDirectory);
|
||||||
|
|
||||||
if (params.release.isValid())
|
if (params.release.isValid())
|
||||||
query.where("t.release_id = ?").bind(params.release);
|
query.where("t.release_id = ?").bind(params.release);
|
||||||
|
|
||||||
if (params.artist.isValid())
|
if (params.artist.isValid())
|
||||||
{
|
{
|
||||||
query.join("artist a ON a.id = t_a_l.artist_id")
|
query.join("artist a ON a.id = t_a_l.artist_id")
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace lms::db
|
|||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
static constexpr Version LMS_DATABASE_VERSION{ 61 };
|
static constexpr Version LMS_DATABASE_VERSION{ 62 };
|
||||||
}
|
}
|
||||||
|
|
||||||
VersionInfo::VersionInfo()
|
VersionInfo::VersionInfo()
|
||||||
@@ -631,6 +631,39 @@ SELECT
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
void migrateFromV61(Session& session)
|
||||||
|
{
|
||||||
|
// Added a media_library_id in Directory
|
||||||
|
session.getDboSession()->execute(R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS "directory_backup" (
|
||||||
|
"id" integer primary key autoincrement,
|
||||||
|
"version" integer not null,
|
||||||
|
"absolute_path" text not null,
|
||||||
|
"name" text not null,
|
||||||
|
"parent_directory_id" bigint,
|
||||||
|
"media_library_id" bigint,
|
||||||
|
constraint "fk_directory_parent_directory" foreign key ("parent_directory_id") references "directory" ("id") on delete cascade deferrable initially deferred,
|
||||||
|
constraint "fk_directory_media_library" foreign key ("media_library_id") references "media_library" ("id") on delete set null deferrable initially deferred
|
||||||
|
))");
|
||||||
|
|
||||||
|
// Migrate data, with the new directory_id field set to null
|
||||||
|
session.getDboSession()->execute(R"(INSERT INTO directory_backup
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
version,
|
||||||
|
absolute_path,
|
||||||
|
name,
|
||||||
|
parent_directory_id,
|
||||||
|
NULL
|
||||||
|
FROM directory)");
|
||||||
|
|
||||||
|
session.getDboSession()->execute("DROP TABLE directory");
|
||||||
|
session.getDboSession()->execute("ALTER TABLE directory_backup RENAME TO directory");
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
}
|
||||||
|
|
||||||
bool doDbMigration(Session& session)
|
bool doDbMigration(Session& session)
|
||||||
{
|
{
|
||||||
static const std::string outdatedMsg{ "Outdated database, please rebuild it (delete the .db file and restart)" };
|
static const std::string outdatedMsg{ "Outdated database, please rebuild it (delete the .db file and restart)" };
|
||||||
@@ -668,6 +701,7 @@ SELECT
|
|||||||
{ 58, migrateFromV58 },
|
{ 58, migrateFromV58 },
|
||||||
{ 59, migrateFromV59 },
|
{ 59, migrateFromV59 },
|
||||||
{ 60, migrateFromV60 },
|
{ 60, migrateFromV60 },
|
||||||
|
{ 61, migrateFromV61 },
|
||||||
};
|
};
|
||||||
|
|
||||||
bool migrationPerformed{};
|
bool migrationPerformed{};
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ namespace lms::db
|
|||||||
|
|
||||||
_session.execute("CREATE INDEX IF NOT EXISTS directory_id_idx ON directory(id)");
|
_session.execute("CREATE INDEX IF NOT EXISTS directory_id_idx ON directory(id)");
|
||||||
_session.execute("CREATE INDEX IF NOT EXISTS directory_path_idx ON directory(absolute_path)");
|
_session.execute("CREATE INDEX IF NOT EXISTS directory_path_idx ON directory(absolute_path)");
|
||||||
|
_session.execute("CREATE INDEX IF NOT EXISTS directory_media_library_idx ON directory(media_library_id)");
|
||||||
|
|
||||||
_session.execute("CREATE INDEX IF NOT EXISTS image_artist_idx ON image(artist_id)");
|
_session.execute("CREATE INDEX IF NOT EXISTS image_artist_idx ON image(artist_id)");
|
||||||
_session.execute("CREATE INDEX IF NOT EXISTS image_directory_idx ON image(directory_id)");
|
_session.execute("CREATE INDEX IF NOT EXISTS image_directory_idx ON image(directory_id)");
|
||||||
|
|||||||
@@ -21,22 +21,24 @@
|
|||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <Wt/Dbo/Dbo.h>
|
#include <Wt/Dbo/Dbo.h>
|
||||||
|
|
||||||
#include "core/EnumSet.hpp"
|
#include "core/EnumSet.hpp"
|
||||||
#include "database/ArtistId.hpp"
|
#include "database/ArtistId.hpp"
|
||||||
#include "database/DirectoryId.hpp"
|
#include "database/DirectoryId.hpp"
|
||||||
#include "database/ReleaseId.hpp"
|
#include "database/MediaLibraryId.hpp"
|
||||||
#include "database/Object.hpp"
|
#include "database/Object.hpp"
|
||||||
|
#include "database/ReleaseId.hpp"
|
||||||
#include "database/Types.hpp"
|
#include "database/Types.hpp"
|
||||||
|
|
||||||
namespace lms::db
|
namespace lms::db
|
||||||
{
|
{
|
||||||
class Session;
|
class Session;
|
||||||
|
class MediaLibrary;
|
||||||
|
|
||||||
class Directory final : public Object<Directory, DirectoryId>
|
class Directory final : public Object<Directory, DirectoryId>
|
||||||
{
|
{
|
||||||
@@ -52,6 +54,7 @@ namespace lms::db
|
|||||||
core::EnumSet<TrackArtistLinkType> trackArtistLinkTypes; // and for these link types
|
core::EnumSet<TrackArtistLinkType> trackArtistLinkTypes; // and for these link types
|
||||||
DirectoryId parentDirectory; // If set, directories that have this parent
|
DirectoryId parentDirectory; // If set, directories that have this parent
|
||||||
bool withNoTrack{}; // If set, directories that do not contain any track
|
bool withNoTrack{}; // If set, directories that do not contain any track
|
||||||
|
MediaLibraryId mediaLibrary; // If set, directories in this library
|
||||||
|
|
||||||
FindParameters& setRange(std::optional<Range> _range)
|
FindParameters& setRange(std::optional<Range> _range)
|
||||||
{
|
{
|
||||||
@@ -84,6 +87,11 @@ namespace lms::db
|
|||||||
withNoTrack = _withNoTrack;
|
withNoTrack = _withNoTrack;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
FindParameters& setMediaLibrary(MediaLibraryId _mediaLibrary)
|
||||||
|
{
|
||||||
|
mediaLibrary = _mediaLibrary;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// find
|
// find
|
||||||
@@ -100,10 +108,12 @@ namespace lms::db
|
|||||||
const std::filesystem::path& getAbsolutePath() const { return _absolutePath; }
|
const std::filesystem::path& getAbsolutePath() const { return _absolutePath; }
|
||||||
std::string_view getName() const { return _name; }
|
std::string_view getName() const { return _name; }
|
||||||
ObjectPtr<Directory> getParentDirectory() const { return _parent; }
|
ObjectPtr<Directory> getParentDirectory() const { return _parent; }
|
||||||
|
ObjectPtr<MediaLibrary> getMediaLibrary() const { return _mediaLibrary; }
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
void setAbsolutePath(const std::filesystem::path& p);
|
void setAbsolutePath(const std::filesystem::path& p);
|
||||||
void setParent(ObjectPtr<Directory> parent);
|
void setParent(ObjectPtr<Directory> parent);
|
||||||
|
void setMediaLibrary(ObjectPtr<MediaLibrary> mediaLibrary) { _mediaLibrary = getDboPtr(mediaLibrary); }
|
||||||
|
|
||||||
template<class Action>
|
template<class Action>
|
||||||
void persist(Action& a)
|
void persist(Action& a)
|
||||||
@@ -112,6 +122,7 @@ namespace lms::db
|
|||||||
Wt::Dbo::field(a, _name, "name");
|
Wt::Dbo::field(a, _name, "name");
|
||||||
|
|
||||||
Wt::Dbo::belongsTo(a, _parent, "parent_directory", Wt::Dbo::OnDeleteCascade);
|
Wt::Dbo::belongsTo(a, _parent, "parent_directory", Wt::Dbo::OnDeleteCascade);
|
||||||
|
Wt::Dbo::belongsTo(a, _mediaLibrary, "media_library", Wt::Dbo::OnDeleteSetNull); // don't delete directories on media library removal, we want to wait for the next scan to have a chance to migrate files
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -123,5 +134,6 @@ namespace lms::db
|
|||||||
std::string _name;
|
std::string _name;
|
||||||
|
|
||||||
Wt::Dbo::ptr<Directory> _parent;
|
Wt::Dbo::ptr<Directory> _parent;
|
||||||
|
Wt::Dbo::ptr<MediaLibrary> _mediaLibrary;
|
||||||
};
|
};
|
||||||
} // namespace lms::db
|
} // namespace lms::db
|
||||||
|
|||||||
@@ -205,6 +205,9 @@ namespace lms::scanner
|
|||||||
|
|
||||||
void ScanStepAssociateArtistImages::process(ScanContext& context)
|
void ScanStepAssociateArtistImages::process(ScanContext& context)
|
||||||
{
|
{
|
||||||
|
if (_abortScan)
|
||||||
|
return;
|
||||||
|
|
||||||
if (context.stats.nbChanges() == 0)
|
if (context.stats.nbChanges() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -224,6 +227,9 @@ namespace lms::scanner
|
|||||||
ArtistImageAssociationContainer artistImageAssociations;
|
ArtistImageAssociationContainer artistImageAssociations;
|
||||||
while (fetchNextArtistImagesToUpdate(searchContext, artistImageAssociations))
|
while (fetchNextArtistImagesToUpdate(searchContext, artistImageAssociations))
|
||||||
{
|
{
|
||||||
|
if (_abortScan)
|
||||||
|
return;
|
||||||
|
|
||||||
updateArtistImages(session, artistImageAssociations);
|
updateArtistImages(session, artistImageAssociations);
|
||||||
context.currentStepStats.processedElems += readBatchSize;
|
context.currentStepStats.processedElems += readBatchSize;
|
||||||
_progressCallback(context.currentStepStats);
|
_progressCallback(context.currentStepStats);
|
||||||
|
|||||||
@@ -104,18 +104,20 @@ namespace lms::scanner
|
|||||||
return res;
|
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) };
|
Directory::pointer directory{ Directory::find(session, path) };
|
||||||
if (!directory)
|
if (!directory)
|
||||||
{
|
{
|
||||||
Directory::pointer parentDirectory;
|
Directory::pointer parentDirectory;
|
||||||
if (path != rootPath)
|
if (path != mediaLibrary->getPath())
|
||||||
parentDirectory = getOrCreateDirectory(session, path.parent_path(), rootPath);
|
parentDirectory = getOrCreateDirectory(session, path.parent_path(), mediaLibrary);
|
||||||
|
|
||||||
directory = session.create<Directory>(path);
|
directory = session.create<Directory>(path);
|
||||||
directory.modify()->setParent(parentDirectory);
|
directory.modify()->setParent(parentDirectory);
|
||||||
|
directory.modify()->setMediaLibrary(mediaLibrary);
|
||||||
}
|
}
|
||||||
|
// Don't update library if it does not match, will be updated elsewhere
|
||||||
|
|
||||||
return directory;
|
return directory;
|
||||||
}
|
}
|
||||||
@@ -350,12 +352,13 @@ namespace lms::scanner
|
|||||||
|
|
||||||
std::vector<FileScanResult> scanResults;
|
std::vector<FileScanResult> scanResults;
|
||||||
|
|
||||||
|
std::filesystem::path currentDirectory;
|
||||||
core::pathUtils::exploreFilesRecursive(
|
core::pathUtils::exploreFilesRecursive(
|
||||||
mediaLibrary.rootDirectory, [&](std::error_code ec, const std::filesystem::path& path) {
|
mediaLibrary.rootDirectory, [&](std::error_code ec, const std::filesystem::path& path) {
|
||||||
LMS_SCOPED_TRACE_DETAILED("Scanner", "OnExploreFile");
|
LMS_SCOPED_TRACE_DETAILED("Scanner", "OnExploreFile");
|
||||||
|
|
||||||
if (_abortScan)
|
if (_abortScan)
|
||||||
return false;
|
return false; // stop iterating
|
||||||
|
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
@@ -364,22 +367,33 @@ namespace lms::scanner
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool fileToProcess{};
|
bool fileMatched{};
|
||||||
if (core::pathUtils::hasFileAnyExtension(path, _settings.supportedAudioFileExtensions))
|
if (core::pathUtils::hasFileAnyExtension(path, _settings.supportedAudioFileExtensions))
|
||||||
{
|
{
|
||||||
fileToProcess = true;
|
fileMatched = true;
|
||||||
if (checkAudioFileNeedScan(context, path, mediaLibrary))
|
if (checkAudioFileNeedScan(context, path, mediaLibrary))
|
||||||
_fileScanQueue.pushScanRequest(path, FileScanQueue::ScanRequestType::AudioFile);
|
_fileScanQueue.pushScanRequest(path, FileScanQueue::ScanRequestType::AudioFile);
|
||||||
}
|
}
|
||||||
else if (core::pathUtils::hasFileAnyExtension(path, _settings.supportedImageFileExtensions))
|
else if (core::pathUtils::hasFileAnyExtension(path, _settings.supportedImageFileExtensions))
|
||||||
{
|
{
|
||||||
fileToProcess = true;
|
fileMatched = true;
|
||||||
if (checkImageFileNeedScan(context, path))
|
if (checkImageFileNeedScan(context, path))
|
||||||
_fileScanQueue.pushScanRequest(path, FileScanQueue::ScanRequestType::ImageFile);
|
_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++;
|
context.currentStepStats.processedElems++;
|
||||||
_progressCallback(context.currentStepStats);
|
_progressCallback(context.currentStepStats);
|
||||||
}
|
}
|
||||||
@@ -415,17 +429,19 @@ namespace lms::scanner
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context.scanOptions.fullScan)
|
||||||
|
return true;
|
||||||
|
|
||||||
bool needUpdateLibrary{};
|
bool needUpdateLibrary{};
|
||||||
if (!context.scanOptions.fullScan)
|
db::Session& dbSession{ _db.getTLSSession() };
|
||||||
|
|
||||||
{
|
{
|
||||||
|
auto transaction{ dbSession.createReadTransaction() };
|
||||||
|
|
||||||
// Skip file if last write is the same
|
// 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) };
|
const Track::pointer track{ Track::findByPath(dbSession, file) };
|
||||||
|
|
||||||
if (track
|
if (track
|
||||||
&& track->getLastWriteTime().toTime_t() == lastWriteTime.toTime_t()
|
&& track->getLastWriteTime() == lastWriteTime
|
||||||
&& track->getScanVersion() == _settings.scanVersion)
|
&& 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
|
// 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)
|
if (needUpdateLibrary)
|
||||||
{
|
{
|
||||||
db::Session& dbSession{ _db.getTLSSession() };
|
auto transaction{ dbSession.createWriteTransaction() };
|
||||||
auto transaction{ _db.getTLSSession().createWriteTransaction() };
|
|
||||||
|
|
||||||
Track::pointer track{ Track::findByPath(dbSession, file) };
|
Track::pointer track{ Track::findByPath(dbSession, file) };
|
||||||
assert(track);
|
assert(track);
|
||||||
@@ -632,8 +647,9 @@ namespace lms::scanner
|
|||||||
track.modify()->setFileSize(fileInfo->fileSize);
|
track.modify()->setFileSize(fileInfo->fileSize);
|
||||||
track.modify()->setLastWriteTime(fileInfo->lastWriteTime);
|
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
|
MediaLibrary::pointer mediaLibrary{ 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));
|
track.modify()->setMediaLibrary(mediaLibrary);
|
||||||
|
track.modify()->setDirectory(getOrCreateDirectory(dbSession, file.parent_path(), mediaLibrary));
|
||||||
|
|
||||||
track.modify()->clearArtistLinks();
|
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
|
// 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()->setFileSize(fileInfo->fileSize);
|
||||||
image.modify()->setHeight(imageInfo->height);
|
image.modify()->setHeight(imageInfo->height);
|
||||||
image.modify()->setWidth(imageInfo->width);
|
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)
|
if (added)
|
||||||
{
|
{
|
||||||
@@ -775,4 +792,34 @@ namespace lms::scanner
|
|||||||
stats.updates++;
|
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
|
} // 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 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 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;
|
std::unique_ptr<metadata::IParser> _metadataParser;
|
||||||
const std::vector<std::string> _extraTagsToParse;
|
const std::vector<std::string> _extraTagsToParse;
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ namespace lms::api::subsonic
|
|||||||
|
|
||||||
void findRequestedArtistDirectories(RequestContext& context, const std::vector<std::string_view>& keywords, MediaLibraryId mediaLibrary, Response::Node& searchResultNode)
|
void findRequestedArtistDirectories(RequestContext& context, const std::vector<std::string_view>& keywords, MediaLibraryId mediaLibrary, Response::Node& searchResultNode)
|
||||||
{
|
{
|
||||||
// For now, no need to "accelerate" all this
|
// For now, no need to optimize all this
|
||||||
// Find all the directories that match the name and that do not contain any track (considered by the legacy API as artists)
|
// Find all the directories that match the name and that do not contain any track (considered by the legacy API as artists)
|
||||||
const std::size_t artistCount{ getParameterAs<std::size_t>(context.parameters, "artistCount").value_or(20) };
|
const std::size_t artistCount{ getParameterAs<std::size_t>(context.parameters, "artistCount").value_or(20) };
|
||||||
if (artistCount == 0)
|
if (artistCount == 0)
|
||||||
@@ -126,12 +126,12 @@ namespace lms::api::subsonic
|
|||||||
throw ParameterValueTooHighGenericError{ "artistCount", defaultMaxCountSize };
|
throw ParameterValueTooHighGenericError{ "artistCount", defaultMaxCountSize };
|
||||||
|
|
||||||
const std::size_t artistOffset{ getParameterAs<std::size_t>(context.parameters, "artistOffset").value_or(0) };
|
const std::size_t artistOffset{ getParameterAs<std::size_t>(context.parameters, "artistOffset").value_or(0) };
|
||||||
|
|
||||||
Directory::FindParameters params;
|
Directory::FindParameters params;
|
||||||
params.setKeywords(keywords);
|
params.setKeywords(keywords);
|
||||||
params.setRange(Range{artistOffset, artistCount});
|
params.setRange(Range{ artistOffset, artistCount });
|
||||||
params.setWithNoTrack(true);
|
params.setWithNoTrack(true);
|
||||||
// TODO media
|
params.setMediaLibrary(mediaLibrary);
|
||||||
|
|
||||||
Directory::find(context.dbSession, params, [&](const Directory::pointer& directory) {
|
Directory::find(context.dbSession, params, [&](const Directory::pointer& directory) {
|
||||||
Response::Node childNode;
|
Response::Node childNode;
|
||||||
@@ -333,10 +333,7 @@ namespace lms::api::subsonic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
Response handleSearchRequestCommon(RequestContext& context, bool id3)
|
Response handleSearchRequestCommon(RequestContext& context, bool id3)
|
||||||
{
|
{
|
||||||
// Mandatory params
|
// Mandatory params
|
||||||
|
|||||||
Reference in New Issue
Block a user