Improve album and title disc, remastered, etc matching
Don't partial remove things like "(Mono / Remastered)". Fixes #1387
This commit is contained in:
parent
b365131363
commit
7f4c61b15a
@ -1681,7 +1681,7 @@ QString CollectionModel::PrettyYearAlbum(const int year, const QString &album) {
|
||||
|
||||
QString CollectionModel::PrettyAlbumDisc(const QString &album, const int disc) {
|
||||
|
||||
if (disc <= 0 || album.contains(Song::kAlbumRemoveDisc)) return TextOrUnknown(album);
|
||||
if (disc <= 0 || Song::AlbumContainsDisc(album)) return TextOrUnknown(album);
|
||||
else return TextOrUnknown(album) + " - (Disc " + QString::number(disc) + ")";
|
||||
|
||||
}
|
||||
@ -1693,7 +1693,7 @@ QString CollectionModel::PrettyYearAlbumDisc(const int year, const QString &albu
|
||||
if (year <= 0) str = TextOrUnknown(album);
|
||||
else str = QString::number(year) + " - " + TextOrUnknown(album);
|
||||
|
||||
if (!album.contains(Song::kAlbumRemoveDisc) && disc > 0) str += " - (Disc " + QString::number(disc) + ")";
|
||||
if (!Song::AlbumContainsDisc(album) && disc > 0) str += " - (Disc " + QString::number(disc) + ")";
|
||||
|
||||
return str;
|
||||
|
||||
|
@ -167,9 +167,20 @@ const QString Song::kFtsColumnSpec = Song::kFtsColumns.join(", ");
|
||||
const QString Song::kFtsBindSpec = Utilities::Prepend(":", Song::kFtsColumns).join(", ");
|
||||
const QString Song::kFtsUpdateSpec = Utilities::Updateify(Song::kFtsColumns).join(", ");
|
||||
|
||||
const QRegularExpression Song::kAlbumRemoveDisc(" ?-? ((\\(|\\[)?)(Disc|CD) ?([0-9]{1,2})((\\)|\\])?)$", QRegularExpression::CaseInsensitiveOption);
|
||||
const QRegularExpression Song::kAlbumRemoveMisc(" ?-? ((\\(|\\[)?)(Remastered|([0-9]{1,4}) *Remaster|Explicit) ?((\\)|\\])?)$", QRegularExpression::CaseInsensitiveOption);
|
||||
const QRegularExpression Song::kTitleRemoveMisc(" ?-? ((\\(|\\[)?)(Remastered|Remastered Version|([0-9]{1,4}) *Remaster) ?((\\)|\\])?)$", QRegularExpression::CaseInsensitiveOption);
|
||||
const Song::RegularExpressionList Song::kAlbumDisc = Song::RegularExpressionList()
|
||||
<< QRegularExpression("\\s+-*\\s*(Disc|CD)\\s*([0-9]{1,2})$", QRegularExpression::CaseInsensitiveOption)
|
||||
<< QRegularExpression("\\s+-*\\s*\\(\\s*(Disc|CD)\\s*([0-9]{1,2})\\)$", QRegularExpression::CaseInsensitiveOption)
|
||||
<< QRegularExpression("\\s+-*\\s*\\[\\s*(Disc|CD)\\s*([0-9]{1,2})\\]$", QRegularExpression::CaseInsensitiveOption);
|
||||
|
||||
const Song::RegularExpressionList Song::kAlbumMisc = Song::RegularExpressionList()
|
||||
<< QRegularExpression("\\s+-*\\s*(Remastered|([0-9]{1,4})\\s*Remaster|Explicit)\\s*$", QRegularExpression::CaseInsensitiveOption)
|
||||
<< QRegularExpression("\\s+-*\\s*\\(\\s*(Remastered|([0-9]{1,4})\\s*Remaster|Explicit)\\s*\\)\\s*$", QRegularExpression::CaseInsensitiveOption)
|
||||
<< QRegularExpression("\\s+-*\\s*\\[\\s*(Remastered|([0-9]{1,4})\\s*Remaster|Explicit)\\s*\\]\\s*$", QRegularExpression::CaseInsensitiveOption);
|
||||
|
||||
const Song::RegularExpressionList Song::kTitleMisc = Song::RegularExpressionList()
|
||||
<< QRegularExpression("\\s+-*\\s*(Remastered|Remastered Version|([0-9]{1,4})\\s*Remaster)\\s*$", QRegularExpression::CaseInsensitiveOption)
|
||||
<< QRegularExpression("\\s+-*\\s*\\(\\s*(Remastered|Remastered Version|([0-9]{1,4})\\s*Remaster)\\s*\\)\\s*$", QRegularExpression::CaseInsensitiveOption)
|
||||
<< QRegularExpression("\\s+-*\\s*\\[\\s*(Remastered|Remastered Version|([0-9]{1,4})\\s*Remaster)\\s*\\]\\s*$", QRegularExpression::CaseInsensitiveOption);
|
||||
|
||||
const QStringList Song::kArticles = QStringList() << "the " << "a " << "an ";
|
||||
|
||||
@ -1843,3 +1854,53 @@ size_t HashSimilar(const Song &song) {
|
||||
// Should compare the same fields as function IsSimilar
|
||||
return qHash(song.title().toLower()) ^ qHash(song.artist().toLower()) ^ qHash(song.album().toLower());
|
||||
}
|
||||
|
||||
bool Song::ContainsRegexList(const QString &str, const RegularExpressionList ®ex_list) {
|
||||
|
||||
for (const QRegularExpression ®ex : regex_list) {
|
||||
if (str.contains(regex)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
QString Song::StripRegexList(QString str, const RegularExpressionList ®ex_list) {
|
||||
|
||||
for (const QRegularExpression ®ex : regex_list) {
|
||||
str = str.remove(regex);
|
||||
}
|
||||
|
||||
return str;
|
||||
|
||||
}
|
||||
|
||||
bool Song::AlbumContainsDisc(const QString &album) {
|
||||
|
||||
return ContainsRegexList(album, kAlbumDisc);
|
||||
|
||||
}
|
||||
|
||||
QString Song::AlbumRemoveDisc(const QString &album) {
|
||||
|
||||
return StripRegexList(album, kAlbumDisc);
|
||||
|
||||
}
|
||||
|
||||
QString Song::AlbumRemoveMisc(const QString &album) {
|
||||
|
||||
return StripRegexList(album, kAlbumMisc);
|
||||
|
||||
}
|
||||
|
||||
QString Song::AlbumRemoveDiscMisc(const QString &album) {
|
||||
|
||||
return StripRegexList(album, RegularExpressionList() << kAlbumDisc << kAlbumMisc);
|
||||
|
||||
}
|
||||
|
||||
QString Song::TitleRemoveMisc(const QString &title) {
|
||||
|
||||
return StripRegexList(title, kTitleMisc);
|
||||
|
||||
}
|
||||
|
@ -123,9 +123,10 @@ class Song {
|
||||
static const QString kFtsBindSpec;
|
||||
static const QString kFtsUpdateSpec;
|
||||
|
||||
static const QRegularExpression kAlbumRemoveDisc;
|
||||
static const QRegularExpression kAlbumRemoveMisc;
|
||||
static const QRegularExpression kTitleRemoveMisc;
|
||||
using RegularExpressionList = QList<QRegularExpression>;
|
||||
static const RegularExpressionList kAlbumDisc;
|
||||
static const RegularExpressionList kAlbumMisc;
|
||||
static const RegularExpressionList kTitleMisc;
|
||||
|
||||
static const QStringList kArticles;
|
||||
|
||||
@ -443,6 +444,14 @@ class Song {
|
||||
// It is more efficient to use IsOnSameAlbum, but this function can be used when you need to hash the key to do fast lookups.
|
||||
QString AlbumKey() const;
|
||||
|
||||
static bool ContainsRegexList(const QString &str, const RegularExpressionList ®ex_list);
|
||||
static QString StripRegexList(QString str, const RegularExpressionList ®ex_list);
|
||||
static bool AlbumContainsDisc(const QString &album);
|
||||
static QString AlbumRemoveDisc(const QString &album);
|
||||
static QString AlbumRemoveMisc(const QString &album);
|
||||
static QString AlbumRemoveDiscMisc(const QString &album);
|
||||
static QString TitleRemoveMisc(const QString &title);
|
||||
|
||||
private:
|
||||
struct Private;
|
||||
|
||||
|
@ -333,7 +333,7 @@ AlbumCoverImageResult AlbumCoverChoiceController::SearchForImage(Song *song) {
|
||||
if (!song->url().isValid() || !song->url().isLocalFile() || song->effective_albumartist().isEmpty() || song->album().isEmpty()) return AlbumCoverImageResult();
|
||||
|
||||
QString album = song->effective_album();
|
||||
album = album.remove(Song::kAlbumRemoveDisc).remove(Song::kAlbumRemoveMisc);
|
||||
album = Song::AlbumRemoveDiscMisc(album);
|
||||
|
||||
// Get something sensible to stick in the search box
|
||||
return cover_searcher_->Exec(song->effective_albumartist(), album);
|
||||
|
@ -66,9 +66,7 @@ quint64 AlbumCoverFetcher::FetchAlbumCover(const QString &artist, const QString
|
||||
CoverSearchRequest request;
|
||||
request.id = ++next_id_;
|
||||
request.artist = artist;
|
||||
request.album = album;
|
||||
request.album = request.album.remove(Song::kAlbumRemoveDisc);
|
||||
request.album = request.album.remove(Song::kAlbumRemoveMisc);
|
||||
request.album = Song::AlbumRemoveDiscMisc(album);
|
||||
request.title = title;
|
||||
request.search = false;
|
||||
request.batch = batch;
|
||||
@ -83,9 +81,7 @@ quint64 AlbumCoverFetcher::SearchForCovers(const QString &artist, const QString
|
||||
CoverSearchRequest request;
|
||||
request.id = ++next_id_;
|
||||
request.artist = artist;
|
||||
request.album = album;
|
||||
request.album = request.album.remove(Song::kAlbumRemoveDisc);
|
||||
request.album = request.album.remove(Song::kAlbumRemoveMisc);
|
||||
request.album = Song::AlbumRemoveDiscMisc(album);
|
||||
request.title = title;
|
||||
request.search = true;
|
||||
request.batch = false;
|
||||
|
@ -265,12 +265,9 @@ void DeezerCoverProvider::HandleSearchReply(QNetworkReply *reply, const int id)
|
||||
}
|
||||
QString album = obj_album["title"].toString();
|
||||
|
||||
album = album.remove(Song::kAlbumRemoveDisc);
|
||||
album = album.remove(Song::kAlbumRemoveMisc);
|
||||
|
||||
CoverProviderSearchResult cover_result;
|
||||
cover_result.artist = artist;
|
||||
cover_result.album = album;
|
||||
cover_result.album = Song::AlbumRemoveDiscMisc(album);
|
||||
|
||||
bool have_cover = false;
|
||||
QList<QPair<QString, QSize>> cover_sizes = QList<QPair<QString, QSize>>() << qMakePair(QString("cover_xl"), QSize(1000, 1000))
|
||||
|
@ -262,12 +262,9 @@ void QobuzCoverProvider::HandleSearchReply(QNetworkReply *reply, const int id) {
|
||||
}
|
||||
QUrl cover_url(obj_image["large"].toString());
|
||||
|
||||
album = album.remove(Song::kAlbumRemoveDisc);
|
||||
album = album.remove(Song::kAlbumRemoveMisc);
|
||||
|
||||
CoverProviderSearchResult cover_result;
|
||||
cover_result.artist = artist;
|
||||
cover_result.album = album;
|
||||
cover_result.album = Song::AlbumRemoveDiscMisc(album);
|
||||
cover_result.image_url = cover_url;
|
||||
cover_result.image_size = QSize(600, 600);
|
||||
results << cover_result;
|
||||
|
@ -241,15 +241,11 @@ void TidalCoverProvider::HandleSearchReply(QNetworkReply *reply, const int id) {
|
||||
continue;
|
||||
}
|
||||
QString album = obj_album["title"].toString();
|
||||
QString cover = obj_album["cover"].toString();
|
||||
|
||||
album = album.remove(Song::kAlbumRemoveDisc);
|
||||
album = album.remove(Song::kAlbumRemoveMisc);
|
||||
cover = cover.replace("-", "/");
|
||||
QString cover = obj_album["cover"].toString().replace("-", "/");
|
||||
|
||||
CoverProviderSearchResult cover_result;
|
||||
cover_result.artist = artist;
|
||||
cover_result.album = album;
|
||||
cover_result.album = Song::AlbumRemoveDiscMisc(album);
|
||||
cover_result.number = ++i;
|
||||
|
||||
QList<QPair<QString, QSize>> cover_sizes = QList<QPair<QString, QSize>>() << qMakePair(QString("1280x1280"), QSize(1280, 1280))
|
||||
|
@ -53,10 +53,8 @@ quint64 LyricsFetcher::Search(const QString &effective_albumartist, const QStrin
|
||||
LyricsSearchRequest search_request;
|
||||
search_request.albumartist = effective_albumartist;
|
||||
search_request.artist = artist;
|
||||
search_request.album = album;
|
||||
search_request.album.remove(Song::kAlbumRemoveMisc);
|
||||
search_request.title = title;
|
||||
search_request.title.remove(Song::kTitleRemoveMisc);
|
||||
search_request.album = Song::AlbumRemoveDiscMisc(album);
|
||||
search_request.title = Song::TitleRemoveMisc(title);
|
||||
|
||||
Request request;
|
||||
request.id = ++next_id_;
|
||||
|
@ -1189,7 +1189,7 @@ void QobuzRequest::ParseSong(Song &song, const QJsonObject &json_obj, const Arti
|
||||
url.setScheme(url_handler_->scheme());
|
||||
url.setPath(song_id);
|
||||
|
||||
title.remove(Song::kTitleRemoveMisc);
|
||||
title = Song::TitleRemoveMisc(title);
|
||||
|
||||
//qLog(Debug) << "id" << song_id << "track" << track << "title" << title << "album" << album << "album artist" << album_artist << cover_url << streamable << url;
|
||||
|
||||
|
@ -50,14 +50,14 @@ bool ScrobblerService::ExtractJsonObj(const QByteArray &data, QJsonObject &json_
|
||||
|
||||
}
|
||||
|
||||
QString ScrobblerService::StripAlbum(QString album) const {
|
||||
QString ScrobblerService::StripAlbum(const QString &album) const {
|
||||
|
||||
return album.remove(Song::kAlbumRemoveDisc).remove(Song::kAlbumRemoveMisc);
|
||||
return Song::AlbumRemoveDisc(album);
|
||||
|
||||
}
|
||||
|
||||
QString ScrobblerService::StripTitle(QString title) const {
|
||||
QString ScrobblerService::StripTitle(const QString &title) const {
|
||||
|
||||
return title.remove(Song::kTitleRemoveMisc);
|
||||
return Song::TitleRemoveMisc(title);
|
||||
|
||||
}
|
||||
|
@ -61,8 +61,8 @@ class ScrobblerService : public QObject {
|
||||
|
||||
bool ExtractJsonObj(const QByteArray &data, QJsonObject &json_obj, QString &error_description);
|
||||
|
||||
QString StripAlbum(QString album) const;
|
||||
QString StripTitle(QString title) const;
|
||||
QString StripAlbum(const QString &album) const;
|
||||
QString StripTitle(const QString &title) const;
|
||||
|
||||
public slots:
|
||||
virtual void Submit() = 0;
|
||||
|
@ -1129,7 +1129,7 @@ void TidalRequest::ParseSong(Song &song, const QJsonObject &json_obj, const Arti
|
||||
}
|
||||
}
|
||||
|
||||
title.remove(Song::kTitleRemoveMisc);
|
||||
title = Song::TitleRemoveMisc(title);
|
||||
|
||||
//qLog(Debug) << "id" << song_id << "track" << track << "disc" << disc << "title" << title << "album" << album << "album artist" << album_artist << "artist" << artist << cover << allow_streaming << url;
|
||||
|
||||
|
@ -152,7 +152,7 @@ QString CoverUtils::CoverFilenameFromSource(const Song::Source source, const QUr
|
||||
|
||||
QString CoverUtils::CoverFilenameFromVariable(const CoverOptions &options, const QString &artist, QString album, const QString &extension) {
|
||||
|
||||
album = album.remove(Song::kAlbumRemoveDisc);
|
||||
album = Song::AlbumRemoveDisc(album);
|
||||
|
||||
QString filename(options.cover_pattern);
|
||||
filename.replace("%albumartist", artist);
|
||||
|
Loading…
x
Reference in New Issue
Block a user