Introduced an option to use a release image when no artist image is available, fixes #639

This commit is contained in:
emeric
2025-06-23 22:37:05 +02:00
parent 57692fd8f4
commit 2429888c53
14 changed files with 105 additions and 13 deletions
+11
View File
@@ -78,6 +78,17 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-12">
<div class="form-check">
${artist-image-fallback-to-release class="form-check-input"}
<label class="form-check-label" for="${id:artist-image-fallback-to-release}">
${tr:Lms.Admin.Database.artist-image-fallback-to-release}
</label>
<div class="invalid-feedback">
${artist-image-fallback-to-release-info}
</div>
</div>
</div>
<div class="col-12"> <div class="col-12">
<label class="form-label" for="${id:similarity-engine-type}"> <label class="form-label" for="${id:similarity-engine-type}">
${tr:Lms.Admin.Database.similarity-engine-type} ${tr:Lms.Admin.Database.similarity-engine-type}
+1
View File
@@ -74,6 +74,7 @@
<!--Scan settings--> <!--Scan settings-->
<message id="Lms.Admin.Database.allow-mbid-artist-merge">Allow merging artists without an MBID to those with one</message> <message id="Lms.Admin.Database.allow-mbid-artist-merge">Allow merging artists without an MBID to those with one</message>
<message id="Lms.Admin.Database.artist-image-fallback-to-release">Use an album artwork if no artist image is available</message>
<message id="Lms.Admin.Database.artist-tag-delimiters">Delimiters to be used for splitting artist tags</message> <message id="Lms.Admin.Database.artist-tag-delimiters">Delimiters to be used for splitting artist tags</message>
<message id="Lms.Admin.Database.artists-to-not-split">Artists to not split using the delimiters (one artist per line)</message> <message id="Lms.Admin.Database.artists-to-not-split">Artists to not split using the delimiters (one artist per line)</message>
<message id="Lms.Admin.Database.daily">Daily</message> <message id="Lms.Admin.Database.daily">Daily</message>
+1
View File
@@ -74,6 +74,7 @@
<!--Scan settings--> <!--Scan settings-->
<message id="Lms.Admin.Database.allow-mbid-artist-merge">Permitir la fusión de artistas sin MBID con aquellos que sí lo tienen</message> <message id="Lms.Admin.Database.allow-mbid-artist-merge">Permitir la fusión de artistas sin MBID con aquellos que sí lo tienen</message>
<message id="Lms.Admin.Database.artist-image-fallback-to-release">Usar una imagen del álbum si no hay una imagen disponible del artista</message>
<message id="Lms.Admin.Database.artist-tag-delimiters">Delimitadores usados para separar las etiquetas de los artistas</message> <message id="Lms.Admin.Database.artist-tag-delimiters">Delimitadores usados para separar las etiquetas de los artistas</message>
<message id="Lms.Admin.Database.artists-to-not-split">Artistas que no se deben separar usando los delimitadores (un artista por línea)</message> <message id="Lms.Admin.Database.artists-to-not-split">Artistas que no se deben separar usando los delimitadores (un artista por línea)</message>
<message id="Lms.Admin.Database.daily">Diariamente</message> <message id="Lms.Admin.Database.daily">Diariamente</message>
+1
View File
@@ -74,6 +74,7 @@
<!--Scan settings--> <!--Scan settings-->
<message id="Lms.Admin.Database.allow-mbid-artist-merge">Permettre la fusion des artistes sans MBID avec ceux qui en ont un</message> <message id="Lms.Admin.Database.allow-mbid-artist-merge">Permettre la fusion des artistes sans MBID avec ceux qui en ont un</message>
<message id="Lms.Admin.Database.artist-image-fallback-to-release">Utilizza un'immagine dell'album se non è disponibile un'immagine dell'artista</message>
<message id="Lms.Admin.Database.artist-tag-delimiters">Délimiteurs à utiliser pour séparer les tags d'artistes</message> <message id="Lms.Admin.Database.artist-tag-delimiters">Délimiteurs à utiliser pour séparer les tags d'artistes</message>
<message id="Lms.Admin.Database.artists-to-not-split">Artistes à ne pas séparer en utilisant les délimiteurs (un artiste par ligne)</message> <message id="Lms.Admin.Database.artists-to-not-split">Artistes à ne pas séparer en utilisant les délimiteurs (un artiste par ligne)</message>
<message id="Lms.Admin.Database.daily">Tous les jours</message> <message id="Lms.Admin.Database.daily">Tous les jours</message>
+1
View File
@@ -74,6 +74,7 @@
<!--Scan settings--> <!--Scan settings-->
<message id="Lms.Admin.Database.allow-mbid-artist-merge">Consentire la fusione degli artisti senza MBID con quelli che ne hanno uno</message> <message id="Lms.Admin.Database.allow-mbid-artist-merge">Consentire la fusione degli artisti senza MBID con quelli che ne hanno uno</message>
<message id="Lms.Admin.Database.artist-image-fallback-to-release">Usa l'immagine dell'album se non è disponibile un'immagine dell'artista</message>
<message id="Lms.Admin.Database.artist-tag-delimiters">Delimitatori da utilizzare per separare i tag degli artisti</message> <message id="Lms.Admin.Database.artist-tag-delimiters">Delimitatori da utilizzare per separare i tag degli artisti</message>
<message id="Lms.Admin.Database.artists-to-not-split">Artisti da non suddividere utilizzando i delimitatori (un artista per riga)</message> <message id="Lms.Admin.Database.artists-to-not-split">Artisti da non suddividere utilizzando i delimitatori (un artista per riga)</message>
<message id="Lms.Admin.Database.daily">Giornaliera</message> <message id="Lms.Admin.Database.daily">Giornaliera</message>
+1
View File
@@ -75,6 +75,7 @@
<!--Scan settings--> <!--Scan settings-->
<message id="Lms.Admin.Database.allow-mbid-artist-merge">Pozwól na łączenie artystów bez MBID z tymi, którzy go mają</message> <message id="Lms.Admin.Database.allow-mbid-artist-merge">Pozwól na łączenie artystów bez MBID z tymi, którzy go mają</message>
<message id="Lms.Admin.Database.artist-image-fallback-to-release">Użyj okładki albumu, jeśli zdjęcie artysty nie jest dostępne</message>
<message id="Lms.Admin.Database.artist-tag-delimiters">Znaki rozdzielające artystów</message> <message id="Lms.Admin.Database.artist-tag-delimiters">Znaki rozdzielające artystów</message>
<message id="Lms.Admin.Database.artists-to-not-split">Artyści, których nie należy dzielić przy użyciu separatorów (jeden artysta na linię)</message> <message id="Lms.Admin.Database.artists-to-not-split">Artyści, których nie należy dzielić przy użyciu separatorów (jeden artysta na linię)</message>
<message id="Lms.Admin.Database.daily">Codziennie</message> <message id="Lms.Admin.Database.daily">Codziennie</message>
+1
View File
@@ -75,6 +75,7 @@
<!--Scan settings--> <!--Scan settings-->
<message id="Lms.Admin.Database.daily">每日</message> <message id="Lms.Admin.Database.daily">每日</message>
+8 -1
View File
@@ -35,7 +35,7 @@ namespace lms::db
{ {
namespace namespace
{ {
static constexpr Version LMS_DATABASE_VERSION{ 93 }; static constexpr Version LMS_DATABASE_VERSION{ 94 };
} }
VersionInfo::VersionInfo() VersionInfo::VersionInfo()
@@ -1380,6 +1380,12 @@ FROM artist)");
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET audio_scan_version = audio_scan_version + 1"); utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET audio_scan_version = audio_scan_version + 1");
} }
void migrateFromV93(Session& session)
{
// add artist_image_fallback_to_release in ScanSettings
utils::executeCommand(*session.getDboSession(), "ALTER TABLE scan_settings ADD COLUMN artist_image_fallback_to_release BOOLEAN NOT NULL DEFAULT(false)");
}
bool doDbMigration(Session& session) bool doDbMigration(Session& session)
{ {
constexpr std::string_view outdatedMsg{ "Outdated database, please rebuild it (delete the .db file and restart)" }; constexpr std::string_view outdatedMsg{ "Outdated database, please rebuild it (delete the .db file and restart)" };
@@ -1449,6 +1455,7 @@ FROM artist)");
{ 90, migrateFromV90 }, { 90, migrateFromV90 },
{ 91, migrateFromV91 }, { 91, migrateFromV91 },
{ 92, migrateFromV92 }, { 92, migrateFromV92 },
{ 93, migrateFromV93 },
}; };
bool migrationPerformed{}; bool migrationPerformed{};
+5 -2
View File
@@ -121,16 +121,19 @@ namespace lms::db
void ScanSettings::setSkipSingleReleasePlayLists(bool value) void ScanSettings::setSkipSingleReleasePlayLists(bool value)
{ {
if (_skipSingleReleasePlayLists != value)
_skipSingleReleasePlayLists = value; _skipSingleReleasePlayLists = value;
} }
void ScanSettings::setAllowMBIDArtistMerge(bool value) void ScanSettings::setAllowMBIDArtistMerge(bool value)
{ {
if (_allowMBIDArtistMerge != value)
_allowMBIDArtistMerge = value; _allowMBIDArtistMerge = value;
} }
void ScanSettings::setArtistImageFallbackToReleaseField(bool value)
{
_artistImageFallbackToReleaseField = value;
}
void ScanSettings::incAudioScanVersion() void ScanSettings::incAudioScanVersion()
{ {
_audioScanVersion += 1; _audioScanVersion += 1;
@@ -74,6 +74,7 @@ namespace lms::db
std::vector<std::string> getArtistsToNotSplit() const; std::vector<std::string> getArtistsToNotSplit() const;
bool getSkipSingleReleasePlayLists() const { return _skipSingleReleasePlayLists; } bool getSkipSingleReleasePlayLists() const { return _skipSingleReleasePlayLists; }
bool getAllowMBIDArtistMerge() const { return _allowMBIDArtistMerge; } bool getAllowMBIDArtistMerge() const { return _allowMBIDArtistMerge; }
bool getArtistImageFallbackToReleaseField() const { return _artistImageFallbackToReleaseField; }
// Setters // Setters
void setUpdateStartTime(Wt::WTime t) { _startTime = t; } void setUpdateStartTime(Wt::WTime t) { _startTime = t; }
@@ -85,6 +86,7 @@ namespace lms::db
void setDefaultTagDelimiters(std::span<const std::string_view> delimiters); void setDefaultTagDelimiters(std::span<const std::string_view> delimiters);
void setSkipSingleReleasePlayLists(bool value); void setSkipSingleReleasePlayLists(bool value);
void setAllowMBIDArtistMerge(bool value); void setAllowMBIDArtistMerge(bool value);
void setArtistImageFallbackToReleaseField(bool value);
template<class Action> template<class Action>
void persist(Action& a) void persist(Action& a)
@@ -101,6 +103,7 @@ namespace lms::db
Wt::Dbo::field(a, _defaultTagDelimiters, "default_tag_delimiters"); Wt::Dbo::field(a, _defaultTagDelimiters, "default_tag_delimiters");
Wt::Dbo::field(a, _skipSingleReleasePlayLists, "skip_single_release_playlists"); Wt::Dbo::field(a, _skipSingleReleasePlayLists, "skip_single_release_playlists");
Wt::Dbo::field(a, _allowMBIDArtistMerge, "allow_mbid_artist_merge"); Wt::Dbo::field(a, _allowMBIDArtistMerge, "allow_mbid_artist_merge");
Wt::Dbo::field(a, _artistImageFallbackToReleaseField, "artist_image_fallback_to_release");
} }
private: private:
@@ -123,5 +126,6 @@ namespace lms::db
std::string _defaultTagDelimiters; std::string _defaultTagDelimiters;
bool _skipSingleReleasePlayLists{}; bool _skipSingleReleasePlayLists{};
bool _allowMBIDArtistMerge{}; bool _allowMBIDArtistMerge{};
bool _artistImageFallbackToReleaseField{};
}; };
} // namespace lms::db } // namespace lms::db
@@ -119,6 +119,7 @@ namespace lms::scanner
settings->skipSingleReleasePlayLists = scanSettings->getSkipSingleReleasePlayLists(); settings->skipSingleReleasePlayLists = scanSettings->getSkipSingleReleasePlayLists();
settings->allowArtistMBIDFallback = scanSettings->getAllowMBIDArtistMerge(); settings->allowArtistMBIDFallback = scanSettings->getAllowMBIDArtistMerge();
settings->artistImageFallbackToRelease = scanSettings->getArtistImageFallbackToReleaseField();
// TODO, store this in DB + expose in UI // TODO, store this in DB + expose in UI
settings->skipDuplicateTrackMBID = core::Service<core::IConfig>::get()->getBool("scanner-skip-duplicate-mbid", false); settings->skipDuplicateTrackMBID = core::Service<core::IConfig>::get()->getBool("scanner-skip-duplicate-mbid", false);
@@ -45,7 +45,8 @@ namespace lms::scanner
std::vector<std::string> artistsToNotSplit; std::vector<std::string> artistsToNotSplit;
std::vector<std::string> defaultTagDelimiters; std::vector<std::string> defaultTagDelimiters;
bool skipSingleReleasePlayLists{}; bool skipSingleReleasePlayLists{};
bool allowArtistMBIDFallback{ true }; // TODO false? bool allowArtistMBIDFallback{ true };
bool artistImageFallbackToRelease{};
std::vector<MediaLibraryInfo> mediaLibraries; std::vector<MediaLibraryInfo> mediaLibraries;
@@ -33,20 +33,23 @@
#include "database/Artist.hpp" #include "database/Artist.hpp"
#include "database/ArtistInfo.hpp" #include "database/ArtistInfo.hpp"
#include "database/Artwork.hpp" #include "database/Artwork.hpp"
#include "database/ArtworkId.hpp"
#include "database/Db.hpp" #include "database/Db.hpp"
#include "database/Directory.hpp" #include "database/Directory.hpp"
#include "database/Image.hpp" #include "database/Image.hpp"
#include "database/Release.hpp"
#include "database/Session.hpp" #include "database/Session.hpp"
#include "database/Track.hpp" #include "database/Track.hpp"
#include "ArtworkUtils.hpp" #include "ArtworkUtils.hpp"
#include "ScanContext.hpp" #include "ScanContext.hpp"
#include "ScannerSettings.hpp"
namespace lms::scanner namespace lms::scanner
{ {
namespace namespace
{ {
using ArtistArtwork = std::variant<std::monostate, db::ImageId>; // TODO handle embedded images in tracks? using ArtistArtwork = std::variant<std::monostate, db::ImageId, db::ArtworkId>; // TODO handle embedded images in tracks?
bool isSameArtwork(ArtistArtwork preferredArtwork, const db::ObjectPtr<db::Artwork>& artwork) bool isSameArtwork(ArtistArtwork preferredArtwork, const db::ObjectPtr<db::Artwork>& artwork)
{ {
if (std::holds_alternative<std::monostate>(preferredArtwork)) if (std::holds_alternative<std::monostate>(preferredArtwork))
@@ -55,6 +58,9 @@ namespace lms::scanner
if (const db::ImageId* imageId = std::get_if<db::ImageId>(&preferredArtwork)) if (const db::ImageId* imageId = std::get_if<db::ImageId>(&preferredArtwork))
return artwork && *imageId == artwork->getImageId(); return artwork && *imageId == artwork->getImageId();
if (const db::ArtworkId* artworkId = std::get_if<db::ArtworkId>(&preferredArtwork))
return artwork && *artworkId == artwork->getId();
return false; return false;
} }
@@ -71,6 +77,7 @@ namespace lms::scanner
db::ArtistId lastRetrievedArtistId; db::ArtistId lastRetrievedArtistId;
std::size_t processedArtistCount{}; std::size_t processedArtistCount{};
std::span<const std::string> artistFileNames; std::span<const std::string> artistFileNames;
const ScannerSettings& settings;
}; };
db::Image::pointer findImageInDirectory(SearchArtistImageContext& searchContext, const std::filesystem::path& directoryPath, std::span<const std::string> fileStemsToSearch) db::Image::pointer findImageInDirectory(SearchArtistImageContext& searchContext, const std::filesystem::path& directoryPath, std::span<const std::string> fileStemsToSearch)
@@ -183,20 +190,51 @@ namespace lms::scanner
return image ? image->getId() : db::ImageId{}; return image ? image->getId() : db::ImageId{};
} }
db::ArtworkId getFirstReleaseArtwork(db::Session& session, const db::Artist::pointer& artist)
{
db::ArtworkId artworkId;
db::Release::FindParameters params;
params.setArtist(artist->getId(), { db::TrackArtistLinkType::ReleaseArtist });
params.setSortMethod(db::ReleaseSortMethod::OriginalDate);
db::Release::find(session, params, [&](const db::Release::pointer& release) {
if (artworkId.isValid())
return;
artworkId = release->getPreferredArtworkId();
});
return artworkId;
}
ArtistArtwork computePreferredArtwork(SearchArtistImageContext& searchContext, const db::Artist::pointer& artist) ArtistArtwork computePreferredArtwork(SearchArtistImageContext& searchContext, const db::Artist::pointer& artist)
{ {
db::ImageId imageId; db::ImageId imageId;
if (const auto mbid{ artist->getMBID() }) if (const auto mbid{ artist->getMBID() })
{
imageId = getImageFromMbid(searchContext, *mbid); imageId = getImageFromMbid(searchContext, *mbid);
if (imageId.isValid())
return ArtistArtwork{ imageId };
}
if (!imageId.isValid())
imageId = searchImageInArtistInfoDirectory(searchContext, artist->getId()); imageId = searchImageInArtistInfoDirectory(searchContext, artist->getId());
if (imageId.isValid())
return ArtistArtwork{ imageId };
if (!imageId.isValid())
imageId = searchImageInDirectories(searchContext, artist->getId()); imageId = searchImageInDirectories(searchContext, artist->getId());
if (imageId.isValid())
return ArtistArtwork{ imageId };
return imageId.isValid() ? ArtistArtwork{ imageId } : ArtistArtwork{}; if (searchContext.settings.artistImageFallbackToRelease)
{
db::ArtworkId artworkId{ getFirstReleaseArtwork(searchContext.session, artist) };
if (artworkId.isValid())
return ArtistArtwork{ artworkId };
}
return ArtistArtwork{};
} }
bool fetchNextArtistArtworksToUpdate(SearchArtistImageContext& searchContext, ArtistArtworkAssociationContainer& ArtistArtworkAssociations) bool fetchNextArtistArtworksToUpdate(SearchArtistImageContext& searchContext, ArtistArtworkAssociationContainer& ArtistArtworkAssociations)
@@ -228,6 +266,8 @@ namespace lms::scanner
db::Artwork::pointer artwork; db::Artwork::pointer artwork;
if (const db::ImageId * imageId{ std::get_if<db::ImageId>(&ArtistArtworkAssociation.preferredArtwork) }) if (const db::ImageId * imageId{ std::get_if<db::ImageId>(&ArtistArtworkAssociation.preferredArtwork) })
artwork = utils::getOrCreateArtworkFromImage(session, *imageId); artwork = utils::getOrCreateArtworkFromImage(session, *imageId);
else if (const db::ArtworkId * artworkId{ std::get_if<db::ArtworkId>(&ArtistArtworkAssociation.preferredArtwork) })
artwork = db::Artwork::find(session, *artworkId);
artist.modify()->setPreferredArtwork(artwork); artist.modify()->setPreferredArtwork(artwork);
if (artwork) if (artwork)
@@ -275,7 +315,13 @@ namespace lms::scanner
bool ScanStepAssociateArtistImages::needProcess(const ScanContext& context) const bool ScanStepAssociateArtistImages::needProcess(const ScanContext& context) const
{ {
return context.stats.nbChanges() > 0; if (context.stats.nbChanges() > 0)
return true;
if (getLastScanSettings() && getLastScanSettings()->artistImageFallbackToRelease != _settings.artistImageFallbackToRelease)
return true;
return false;
} }
void ScanStepAssociateArtistImages::process(ScanContext& context) void ScanStepAssociateArtistImages::process(ScanContext& context)
@@ -291,6 +337,7 @@ namespace lms::scanner
.session = session, .session = session,
.lastRetrievedArtistId = {}, .lastRetrievedArtistId = {},
.artistFileNames = _artistFileNames, .artistFileNames = _artistFileNames,
.settings = _settings,
}; };
ArtistArtworkAssociationContainer ArtistArtworkAssociations; ArtistArtworkAssociationContainer ArtistArtworkAssociations;
+12
View File
@@ -72,6 +72,7 @@ namespace lms::ui
static inline constexpr Field SimilarityEngineTypeField{ "similarity-engine-type" }; static inline constexpr Field SimilarityEngineTypeField{ "similarity-engine-type" };
static inline constexpr Field SkipSingleReleasePlayListsField{ "skip-single-release-playlists" }; static inline constexpr Field SkipSingleReleasePlayListsField{ "skip-single-release-playlists" };
static inline constexpr Field AllowMBIDArtistMergeField{ "allow-mbid-artist-merge" }; static inline constexpr Field AllowMBIDArtistMergeField{ "allow-mbid-artist-merge" };
static inline constexpr Field ArtistImageFallbackToReleaseField{ "artist-image-fallback-to-release" };
static inline constexpr Field ArtistsToNotSplitField{ "artists-to-not-split" }; static inline constexpr Field ArtistsToNotSplitField{ "artists-to-not-split" };
using UpdatePeriodModel = ValueStringModel<ScanSettings::UpdatePeriod>; using UpdatePeriodModel = ValueStringModel<ScanSettings::UpdatePeriod>;
@@ -85,6 +86,7 @@ namespace lms::ui
addField(SimilarityEngineTypeField); addField(SimilarityEngineTypeField);
addField(SkipSingleReleasePlayListsField); addField(SkipSingleReleasePlayListsField);
addField(AllowMBIDArtistMergeField); addField(AllowMBIDArtistMergeField);
addField(ArtistImageFallbackToReleaseField);
addField(ArtistsToNotSplitField); addField(ArtistsToNotSplitField);
setValidator(UpdatePeriodField, createMandatoryValidator()); setValidator(UpdatePeriodField, createMandatoryValidator());
@@ -92,6 +94,7 @@ namespace lms::ui
setValidator(SimilarityEngineTypeField, createMandatoryValidator()); setValidator(SimilarityEngineTypeField, createMandatoryValidator());
setValidator(SkipSingleReleasePlayListsField, createMandatoryValidator()); setValidator(SkipSingleReleasePlayListsField, createMandatoryValidator());
setValidator(AllowMBIDArtistMergeField, createMandatoryValidator()); setValidator(AllowMBIDArtistMergeField, createMandatoryValidator());
setValidator(ArtistImageFallbackToReleaseField, createMandatoryValidator());
} }
std::shared_ptr<UpdatePeriodModel> updatePeriodModel() { return _updatePeriodModel; } std::shared_ptr<UpdatePeriodModel> updatePeriodModel() { return _updatePeriodModel; }
@@ -120,6 +123,7 @@ namespace lms::ui
setValue(SkipSingleReleasePlayListsField, scanSettings->getSkipSingleReleasePlayLists()); setValue(SkipSingleReleasePlayListsField, scanSettings->getSkipSingleReleasePlayLists());
setValue(AllowMBIDArtistMergeField, scanSettings->getAllowMBIDArtistMerge()); setValue(AllowMBIDArtistMergeField, scanSettings->getAllowMBIDArtistMerge());
setValue(ArtistImageFallbackToReleaseField, scanSettings->getArtistImageFallbackToReleaseField());
auto similarityEngineTypeRow{ _similarityEngineTypeModel->getRowFromValue(scanSettings->getSimilarityEngineType()) }; auto similarityEngineTypeRow{ _similarityEngineTypeModel->getRowFromValue(scanSettings->getSimilarityEngineType()) };
if (similarityEngineTypeRow) if (similarityEngineTypeRow)
@@ -167,6 +171,11 @@ namespace lms::ui
scanSettings.modify()->setAllowMBIDArtistMerge(allowMBIDArtistMerge); scanSettings.modify()->setAllowMBIDArtistMerge(allowMBIDArtistMerge);
} }
{
const bool artistImageFallbackToRelease{ Wt::asNumber(value(ArtistImageFallbackToReleaseField)) != 0 };
scanSettings.modify()->setArtistImageFallbackToReleaseField(artistImageFallbackToRelease);
}
{ {
const auto similarityEngineTypeRow{ _similarityEngineTypeModel->getRowFromString(valueText(SimilarityEngineTypeField)) }; const auto similarityEngineTypeRow{ _similarityEngineTypeModel->getRowFromString(valueText(SimilarityEngineTypeField)) };
if (similarityEngineTypeRow) if (similarityEngineTypeRow)
@@ -371,6 +380,9 @@ namespace lms::ui
// Allow to merge artists without MBID with those with one // Allow to merge artists without MBID with those with one
t->setFormWidget(DatabaseSettingsModel::AllowMBIDArtistMergeField, std::make_unique<Wt::WCheckBox>()); t->setFormWidget(DatabaseSettingsModel::AllowMBIDArtistMergeField, std::make_unique<Wt::WCheckBox>());
// Allow to fallback on release image if artist image is not available
t->setFormWidget(DatabaseSettingsModel::ArtistImageFallbackToReleaseField, std::make_unique<Wt::WCheckBox>());
// Similarity engine type // Similarity engine type
auto similarityEngineType{ std::make_unique<Wt::WComboBox>() }; auto similarityEngineType{ std::make_unique<Wt::WComboBox>() };
similarityEngineType->setModel(model->similarityEngineTypeModel()); similarityEngineType->setModel(model->similarityEngineTypeModel());