fix: lyrics backend ns -> class

Also add toString method
This commit is contained in:
2 * r + 2 * t 2026-05-05 18:38:01 +10:00
parent 8eb9f100d4
commit bbec29ed7b
4 changed files with 126 additions and 103 deletions

View file

@ -1,11 +1,24 @@
#include "lyriccandidate.hpp" #include "lyriccandidate.hpp"
#include <utility>
namespace caelestia::services { namespace caelestia::services {
QString LyricsBackend::toString(Backend b) {
switch (b) {
case LyricsBackend::Auto:
return QStringLiteral("Auto");
case LyricsBackend::Local:
return QStringLiteral("Local");
case LyricsBackend::LRCLIB:
return QStringLiteral("LRCLIB");
case LyricsBackend::NetEase:
return QStringLiteral("NetEase");
default:
return QStringLiteral("Unknown");
}
}
LyricCandidate::LyricCandidate( LyricCandidate::LyricCandidate(
LyricsBackend backend, QString id, QString title, QString artist, QString album, qreal duration) LyricsBackend::Backend backend, QString id, QString title, QString artist, QString album, qreal duration)
: m_backend(backend) : m_backend(backend)
, m_id(std::move(id)) , m_id(std::move(id))
, m_title(std::move(title)) , m_title(std::move(title))
@ -13,7 +26,7 @@ LyricCandidate::LyricCandidate(
, m_album(std::move(album)) , m_album(std::move(album))
, m_duration(duration) {} , m_duration(duration) {}
LyricsBackend LyricCandidate::backend() const { LyricsBackend::Backend LyricCandidate::backend() const {
return m_backend; return m_backend;
} }

View file

@ -4,21 +4,28 @@
namespace caelestia::services { namespace caelestia::services {
Q_NAMESPACE class LyricsBackend : public QObject {
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
enum LyricsBackend { public:
Auto = 0, enum Backend {
Local = 1, Auto = 0,
LRCLIB = 2, Local,
NetEase = 3, LRCLIB,
NetEase
};
Q_ENUM(Backend)
Q_INVOKABLE QString toString(caelestia::services::LyricsBackend::Backend b);
}; };
Q_ENUM_NS(LyricsBackend)
class LyricCandidate { class LyricCandidate {
Q_GADGET Q_GADGET
QML_VALUE_TYPE(lyricCandidate) QML_VALUE_TYPE(lyricCandidate)
Q_PROPERTY(LyricsBackend backend READ backend) Q_PROPERTY(caelestia::services::LyricsBackend::Backend backend READ backend)
Q_PROPERTY(QString id READ id) Q_PROPERTY(QString id READ id)
Q_PROPERTY(QString title READ title) Q_PROPERTY(QString title READ title)
Q_PROPERTY(QString artist READ artist) Q_PROPERTY(QString artist READ artist)
@ -27,10 +34,10 @@ class LyricCandidate {
public: public:
LyricCandidate() = default; LyricCandidate() = default;
LyricCandidate( LyricCandidate(LyricsBackend::Backend backend, QString id, QString title, QString artist, QString album = {},
LyricsBackend backend, QString id, QString title, QString artist, QString album = {}, qreal duration = 0.0); qreal duration = 0.0);
[[nodiscard]] LyricsBackend backend() const; [[nodiscard]] LyricsBackend::Backend backend() const;
[[nodiscard]] QString id() const; [[nodiscard]] QString id() const;
[[nodiscard]] QString title() const; [[nodiscard]] QString title() const;
[[nodiscard]] QString artist() const; [[nodiscard]] QString artist() const;
@ -42,7 +49,7 @@ public:
bool operator!=(const LyricCandidate& o) const noexcept; bool operator!=(const LyricCandidate& o) const noexcept;
private: private:
LyricsBackend m_backend = Auto; LyricsBackend::Backend m_backend = LyricsBackend::Auto;
QString m_id; QString m_id;
QString m_title; QString m_title;
QString m_artist; QString m_artist;

View file

@ -86,15 +86,15 @@ QStringList Lyrics::lyrics() const {
return m_lyrics; return m_lyrics;
} }
LyricsBackend Lyrics::backend() const { LyricsBackend::Backend Lyrics::backend() const {
return m_backend; return m_backend;
} }
LyricsBackend Lyrics::preferredBackend() const { LyricsBackend::Backend Lyrics::preferredBackend() const {
return m_preferredBackend; return m_preferredBackend;
} }
void Lyrics::setPreferredBackend(LyricsBackend value) { void Lyrics::setPreferredBackend(LyricsBackend::Backend value) {
if (m_preferredBackend == value) { if (m_preferredBackend == value) {
return; return;
} }
@ -136,7 +136,7 @@ void Lyrics::setSelectedCandidate(const LyricCandidate& value) {
cancelInFlight(); cancelInFlight();
const int reqId = newRequestId(); const int reqId = newRequestId();
if (b == LRCLIB || b == NetEase) { if (b == LyricsBackend::LRCLIB || b == LyricsBackend::NetEase) {
const QString cached = readCachedLrc(b, value.id()); const QString cached = readCachedLrc(b, value.id());
if (!cached.isEmpty()) { if (!cached.isEmpty()) {
const auto lines = parseLrc(cached); const auto lines = parseLrc(cached);
@ -151,16 +151,16 @@ void Lyrics::setSelectedCandidate(const LyricCandidate& value) {
} }
} }
if (b == LRCLIB) { if (b == LyricsBackend::LRCLIB) {
fetchLrclibById(value.id(), reqId); fetchLrclibById(value.id(), reqId);
} else if (b == NetEase) { } else if (b == LyricsBackend::NetEase) {
fetchNetEaseLyricsById(value.id(), reqId); fetchNetEaseLyricsById(value.id(), reqId);
} else if (b == Local) { } else if (b == LyricsBackend::Local) {
// For local, the id is the file path. Read directly. // For local, the id is the file path. Read directly.
QFile f(value.id()); QFile f(value.id());
if (f.open(QIODevice::ReadOnly)) { if (f.open(QIODevice::ReadOnly)) {
const QString text = QString::fromUtf8(f.readAll()); const QString text = QString::fromUtf8(f.readAll());
setLines(parseLrc(text), Local); setLines(parseLrc(text), LyricsBackend::Local);
setLoading(false); setLoading(false);
} else { } else {
qCWarning(lcLyrics) << "selectedCandidate: cannot open local file" << value.id(); qCWarning(lcLyrics) << "selectedCandidate: cannot open local file" << value.id();
@ -257,7 +257,7 @@ void Lyrics::refresh() {
scheduleLoad(); scheduleLoad();
} }
void Lyrics::setBackend(LyricsBackend value) { void Lyrics::setBackend(LyricsBackend::Backend value) {
if (m_backend == value) { if (m_backend == value) {
return; return;
} }
@ -273,7 +273,7 @@ void Lyrics::setLoading(bool value) {
emit loadingChanged(); emit loadingChanged();
} }
void Lyrics::setLines(QVector<LyricLine> lines, LyricsBackend source) { void Lyrics::setLines(QVector<LyricLine> lines, LyricsBackend::Backend source) {
std::sort(lines.begin(), lines.end(), [](const LyricLine& a, const LyricLine& b) { std::sort(lines.begin(), lines.end(), [](const LyricLine& a, const LyricLine& b) {
return a.time < b.time; return a.time < b.time;
}); });
@ -394,36 +394,36 @@ void Lyrics::doLoad() {
// Primary attempt by preferred backend // Primary attempt by preferred backend
switch (m_preferredBackend) { switch (m_preferredBackend) {
case Local: case LyricsBackend::Local:
tryLocal(reqId); tryLocal(reqId);
break; break;
case LRCLIB: case LyricsBackend::LRCLIB:
tryLrclib(reqId); tryLrclib(reqId);
break; break;
case NetEase: case LyricsBackend::NetEase:
tryNetEase(reqId); tryNetEase(reqId);
break; break;
case Auto: case LyricsBackend::Auto:
default: default:
tryLocal(reqId); tryLocal(reqId);
break; break;
} }
} }
void Lyrics::chainNext(LyricsBackend just_failed, int reqId) { void Lyrics::chainNext(LyricsBackend::Backend just_failed, int reqId) {
if (m_preferredBackend != Auto) { if (m_preferredBackend != LyricsBackend::Auto) {
// Non-auto modes don't chain // Non-auto modes don't chain
setLoading(false); setLoading(false);
return; return;
} }
switch (just_failed) { switch (just_failed) {
case Local: case LyricsBackend::Local:
tryLrclib(reqId); tryLrclib(reqId);
return; return;
case LRCLIB: case LyricsBackend::LRCLIB:
tryNetEase(reqId); tryNetEase(reqId);
return; return;
case NetEase: case LyricsBackend::NetEase:
default: default:
setLoading(false); setLoading(false);
return; return;
@ -435,11 +435,11 @@ void Lyrics::tryLocal(int reqId) {
return; return;
} }
setBackend(Local); setBackend(LyricsBackend::Local);
const QString dir = lyricsDir(); const QString dir = lyricsDir();
if (dir.isEmpty()) { if (dir.isEmpty()) {
chainNext(Local, reqId); chainNext(LyricsBackend::Local, reqId);
return; return;
} }
@ -450,9 +450,10 @@ void Lyrics::tryLocal(int reqId) {
const QString text = QString::fromUtf8(f.readAll()); const QString text = QString::fromUtf8(f.readAll());
const auto lines = parseLrc(text); const auto lines = parseLrc(text);
if (!lines.isEmpty()) { if (!lines.isEmpty()) {
setLines(lines, Local); setLines(lines, LyricsBackend::Local);
appendCandidates({ LyricCandidate(Local, direct, m_title, m_artist, m_album, m_duration) }); appendCandidates(
m_selected = LyricCandidate(Local, direct, m_title, m_artist, m_album, m_duration); { LyricCandidate(LyricsBackend::Local, direct, m_title, m_artist, m_album, m_duration) });
m_selected = LyricCandidate(LyricsBackend::Local, direct, m_title, m_artist, m_album, m_duration);
emit selectedCandidateChanged(); emit selectedCandidateChanged();
if (!m_settingFromPrefs) { if (!m_settingFromPrefs) {
persistTrackPrefs(); persistTrackPrefs();
@ -470,9 +471,10 @@ void Lyrics::tryLocal(int reqId) {
const QString text = QString::fromUtf8(f.readAll()); const QString text = QString::fromUtf8(f.readAll());
const auto lines = parseLrc(text); const auto lines = parseLrc(text);
if (!lines.isEmpty()) { if (!lines.isEmpty()) {
setLines(lines, Local); setLines(lines, LyricsBackend::Local);
appendCandidates({ LyricCandidate(Local, recursive, m_title, m_artist, m_album, m_duration) }); appendCandidates(
m_selected = LyricCandidate(Local, recursive, m_title, m_artist, m_album, m_duration); { LyricCandidate(LyricsBackend::Local, recursive, m_title, m_artist, m_album, m_duration) });
m_selected = LyricCandidate(LyricsBackend::Local, recursive, m_title, m_artist, m_album, m_duration);
emit selectedCandidateChanged(); emit selectedCandidateChanged();
if (!m_settingFromPrefs) { if (!m_settingFromPrefs) {
persistTrackPrefs(); persistTrackPrefs();
@ -484,7 +486,7 @@ void Lyrics::tryLocal(int reqId) {
} }
qCDebug(lcLyrics) << "no local lrc for" << m_artist << "-" << m_title; qCDebug(lcLyrics) << "no local lrc for" << m_artist << "-" << m_title;
chainNext(Local, reqId); chainNext(LyricsBackend::Local, reqId);
} }
void Lyrics::tryLrclib(int reqId) { void Lyrics::tryLrclib(int reqId) {
@ -492,7 +494,7 @@ void Lyrics::tryLrclib(int reqId) {
return; return;
} }
setBackend(LRCLIB); setBackend(LyricsBackend::LRCLIB);
QUrl url(u"https://lrclib.net/api/get"_s); QUrl url(u"https://lrclib.net/api/get"_s);
QUrlQuery q; QUrlQuery q;
@ -516,7 +518,7 @@ void Lyrics::tryLrclib(int reqId) {
} }
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
qCDebug(lcLyrics) << "lrclib /get error:" << reply->errorString(); qCDebug(lcLyrics) << "lrclib /get error:" << reply->errorString();
chainNext(LRCLIB, reqId); chainNext(LyricsBackend::LRCLIB, reqId);
return; return;
} }
const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll()); const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
@ -526,19 +528,19 @@ void Lyrics::tryLrclib(int reqId) {
if (synced.isEmpty()) { if (synced.isEmpty()) {
qCDebug(lcLyrics) << "lrclib: no syncedLyrics for" << m_artist << "-" << m_title; qCDebug(lcLyrics) << "lrclib: no syncedLyrics for" << m_artist << "-" << m_title;
chainNext(LRCLIB, reqId); chainNext(LyricsBackend::LRCLIB, reqId);
return; return;
} }
const auto lines = parseLrc(synced); const auto lines = parseLrc(synced);
if (lines.isEmpty()) { if (lines.isEmpty()) {
chainNext(LRCLIB, reqId); chainNext(LyricsBackend::LRCLIB, reqId);
return; return;
} }
writeCachedLrc(LRCLIB, QString::number(id), synced); writeCachedLrc(LyricsBackend::LRCLIB, QString::number(id), synced);
setLines(lines, LRCLIB); setLines(lines, LyricsBackend::LRCLIB);
const LyricCandidate cand(LRCLIB, QString::number(id), obj.value(u"trackName"_s).toString(), const LyricCandidate cand(LyricsBackend::LRCLIB, QString::number(id), obj.value(u"trackName"_s).toString(),
obj.value(u"artistName"_s).toString(), obj.value(u"albumName"_s).toString(), obj.value(u"artistName"_s).toString(), obj.value(u"albumName"_s).toString(),
obj.value(u"duration"_s).toDouble()); obj.value(u"duration"_s).toDouble());
appendCandidates({ cand }); appendCandidates({ cand });
@ -556,9 +558,9 @@ void Lyrics::tryNetEase(int reqId) {
return; return;
} }
setBackend(NetEase); setBackend(LyricsBackend::NetEase);
// Reset cookies (NetEase rejects requests with stale cookies sometimes) // Reset cookies (LyricsBackend::NetEase rejects requests with stale cookies sometimes)
m_nam->setCookieJar(new QNetworkCookieJar(m_nam)); m_nam->setCookieJar(new QNetworkCookieJar(m_nam));
QUrl url(u"https://music.163.com/api/search/get"_s); QUrl url(u"https://music.163.com/api/search/get"_s);
@ -578,7 +580,7 @@ void Lyrics::tryNetEase(int reqId) {
} }
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
qCDebug(lcLyrics) << "netease /search error:" << reply->errorString(); qCDebug(lcLyrics) << "netease /search error:" << reply->errorString();
chainNext(NetEase, reqId); chainNext(LyricsBackend::NetEase, reqId);
return; return;
} }
@ -602,7 +604,7 @@ void Lyrics::tryNetEase(int reqId) {
if (bestId < 0) { if (bestId < 0) {
qCDebug(lcLyrics) << "netease: no artist match for" << m_artist << "-" << m_title; qCDebug(lcLyrics) << "netease: no artist match for" << m_artist << "-" << m_title;
chainNext(NetEase, reqId); chainNext(LyricsBackend::NetEase, reqId);
return; return;
} }
@ -639,9 +641,10 @@ void Lyrics::searchLrclibCandidates(int reqId) {
if (o.value(u"syncedLyrics"_s).isNull() && o.value(u"plainLyrics"_s).isNull()) { if (o.value(u"syncedLyrics"_s).isNull() && o.value(u"plainLyrics"_s).isNull()) {
continue; continue;
} }
add.append(LyricCandidate(LRCLIB, QString::number(static_cast<qint64>(o.value(u"id"_s).toDouble())), add.append(
o.value(u"trackName"_s).toString(), o.value(u"artistName"_s).toString(), LyricCandidate(LyricsBackend::LRCLIB, QString::number(static_cast<qint64>(o.value(u"id"_s).toDouble())),
o.value(u"albumName"_s).toString(), o.value(u"duration"_s).toDouble())); o.value(u"trackName"_s).toString(), o.value(u"artistName"_s).toString(),
o.value(u"albumName"_s).toString(), o.value(u"duration"_s).toDouble()));
} }
appendCandidates(add); appendCandidates(add);
}); });
@ -682,8 +685,9 @@ void Lyrics::searchNetEaseCandidates(int reqId) {
for (const auto& a : artists) { for (const auto& a : artists) {
artistNames.append(a.toObject().value(u"name"_s).toString()); artistNames.append(a.toObject().value(u"name"_s).toString());
} }
add.append(LyricCandidate(NetEase, QString::number(static_cast<qint64>(s.value(u"id"_s).toDouble())), add.append(LyricCandidate(LyricsBackend::NetEase,
s.value(u"name"_s).toString(), artistNames.join(u", "_s))); QString::number(static_cast<qint64>(s.value(u"id"_s).toDouble())), s.value(u"name"_s).toString(),
artistNames.join(u", "_s)));
} }
appendCandidates(add); appendCandidates(add);
}); });
@ -711,8 +715,8 @@ void Lyrics::fetchLrclibById(const QString& id, int reqId) {
setLoading(false); setLoading(false);
return; return;
} }
writeCachedLrc(LRCLIB, id, synced); writeCachedLrc(LyricsBackend::LRCLIB, id, synced);
setLines(parseLrc(synced), LRCLIB); setLines(parseLrc(synced), LyricsBackend::LRCLIB);
setLoading(false); setLoading(false);
}); });
} }
@ -746,8 +750,8 @@ void Lyrics::fetchNetEaseLyricsById(const QString& id, int reqId) {
setLoading(false); setLoading(false);
return; return;
} }
writeCachedLrc(NetEase, id, lrc); writeCachedLrc(LyricsBackend::NetEase, id, lrc);
setLines(parseLrc(lrc), NetEase); setLines(parseLrc(lrc), LyricsBackend::NetEase);
setLoading(false); setLoading(false);
}); });
} }
@ -767,7 +771,7 @@ QNetworkReply* Lyrics::getJson(const QUrl& url, const QHash<QByteArray, QByteArr
void Lyrics::onPreferredBackendConfigChanged() { void Lyrics::onPreferredBackendConfigChanged() {
auto* svcCfg = config::GlobalConfig::instance()->services(); auto* svcCfg = config::GlobalConfig::instance()->services();
const LyricsBackend desired = backendFromKey(svcCfg->lyricsBackend()); const LyricsBackend::Backend desired = backendFromKey(svcCfg->lyricsBackend());
if (desired == m_preferredBackend) { if (desired == m_preferredBackend) {
return; return;
} }
@ -862,31 +866,31 @@ QString Lyrics::trackKey() const {
return u"%1 - %2"_s.arg(joinArtists(m_artist), m_title); return u"%1 - %2"_s.arg(joinArtists(m_artist), m_title);
} }
QString Lyrics::backendKey(LyricsBackend value) { QString Lyrics::backendKey(LyricsBackend::Backend value) {
switch (value) { switch (value) {
case Local: case LyricsBackend::Local:
return u"Local"_s; return u"LyricsBackend::Local"_s;
case LRCLIB: case LyricsBackend::LRCLIB:
return u"LRCLIB"_s; return u"LyricsBackend::LRCLIB"_s;
case NetEase: case LyricsBackend::NetEase:
return u"NetEase"_s; return u"LyricsBackend::NetEase"_s;
case Auto: case LyricsBackend::Auto:
default: default:
return u"Auto"_s; return u"LyricsBackend::Auto"_s;
} }
} }
LyricsBackend Lyrics::backendFromKey(const QString& key) { LyricsBackend::Backend Lyrics::backendFromKey(const QString& key) {
if (key.compare(u"Local"_s, Qt::CaseInsensitive) == 0) { if (key.compare(u"LyricsBackend::Local"_s, Qt::CaseInsensitive) == 0) {
return Local; return LyricsBackend::Local;
} }
if (key.compare(u"LRCLIB"_s, Qt::CaseInsensitive) == 0) { if (key.compare(u"LyricsBackend::LRCLIB"_s, Qt::CaseInsensitive) == 0) {
return LRCLIB; return LyricsBackend::LRCLIB;
} }
if (key.compare(u"NetEase"_s, Qt::CaseInsensitive) == 0) { if (key.compare(u"LyricsBackend::NetEase"_s, Qt::CaseInsensitive) == 0) {
return NetEase; return LyricsBackend::NetEase;
} }
return Auto; return LyricsBackend::Auto;
} }
const QString& Lyrics::cacheDir() { const QString& Lyrics::cacheDir() {
@ -900,14 +904,14 @@ const QString& Lyrics::cacheDir() {
return s_dir; return s_dir;
} }
QString Lyrics::cachePathFor(LyricsBackend backend, const QString& id) { QString Lyrics::cachePathFor(LyricsBackend::Backend backend, const QString& id) {
if (id.isEmpty() || backend == Auto || backend == Local) { if (id.isEmpty() || backend == LyricsBackend::Auto || backend == LyricsBackend::Local) {
return {}; return {};
} }
return u"%1/%2/%3.lrc"_s.arg(cacheDir(), backendKey(backend), sanitizeFilenamePart(id)); return u"%1/%2/%3.lrc"_s.arg(cacheDir(), backendKey(backend), sanitizeFilenamePart(id));
} }
QString Lyrics::readCachedLrc(LyricsBackend backend, const QString& id) { QString Lyrics::readCachedLrc(LyricsBackend::Backend backend, const QString& id) {
const QString path = cachePathFor(backend, id); const QString path = cachePathFor(backend, id);
if (path.isEmpty()) { if (path.isEmpty()) {
return {}; return {};
@ -919,7 +923,7 @@ QString Lyrics::readCachedLrc(LyricsBackend backend, const QString& id) {
return QString::fromUtf8(f.readAll()); return QString::fromUtf8(f.readAll());
} }
void Lyrics::writeCachedLrc(LyricsBackend backend, const QString& id, const QString& text) { void Lyrics::writeCachedLrc(LyricsBackend::Backend backend, const QString& id, const QString& text) {
if (text.isEmpty()) { if (text.isEmpty()) {
return; return;
} }

View file

@ -18,12 +18,11 @@ class Lyrics : public QObject {
Q_OBJECT Q_OBJECT
QML_ELEMENT QML_ELEMENT
QML_SINGLETON QML_SINGLETON
QML_EXTENDED_NAMESPACE(caelestia::services)
Q_PROPERTY(QStringList lyrics READ lyrics NOTIFY lyricsChanged) Q_PROPERTY(QStringList lyrics READ lyrics NOTIFY lyricsChanged)
Q_PROPERTY(LyricsBackend backend READ backend NOTIFY backendChanged) Q_PROPERTY(caelestia::services::LyricsBackend::Backend backend READ backend NOTIFY backendChanged)
Q_PROPERTY( Q_PROPERTY(caelestia::services::LyricsBackend::Backend preferredBackend READ preferredBackend WRITE
LyricsBackend preferredBackend READ preferredBackend WRITE setPreferredBackend NOTIFY preferredBackendChanged) setPreferredBackend NOTIFY preferredBackendChanged)
Q_PROPERTY( Q_PROPERTY(
QList<caelestia::services::LyricCandidate> lyricCandidates READ lyricCandidates NOTIFY lyricCandidatesChanged) QList<caelestia::services::LyricCandidate> lyricCandidates READ lyricCandidates NOTIFY lyricCandidatesChanged)
Q_PROPERTY(caelestia::services::LyricCandidate selectedCandidate READ selectedCandidate WRITE setSelectedCandidate Q_PROPERTY(caelestia::services::LyricCandidate selectedCandidate READ selectedCandidate WRITE setSelectedCandidate
@ -38,9 +37,9 @@ public:
explicit Lyrics(QObject* parent = nullptr); explicit Lyrics(QObject* parent = nullptr);
[[nodiscard]] QStringList lyrics() const; [[nodiscard]] QStringList lyrics() const;
[[nodiscard]] LyricsBackend backend() const; [[nodiscard]] LyricsBackend::Backend backend() const;
[[nodiscard]] LyricsBackend preferredBackend() const; [[nodiscard]] LyricsBackend::Backend preferredBackend() const;
void setPreferredBackend(LyricsBackend value); void setPreferredBackend(LyricsBackend::Backend value);
[[nodiscard]] QList<LyricCandidate> lyricCandidates() const; [[nodiscard]] QList<LyricCandidate> lyricCandidates() const;
[[nodiscard]] LyricCandidate selectedCandidate() const; [[nodiscard]] LyricCandidate selectedCandidate() const;
void setSelectedCandidate(const LyricCandidate& value); void setSelectedCandidate(const LyricCandidate& value);
@ -69,9 +68,9 @@ signals:
void trackChanged(); void trackChanged();
private: private:
void setBackend(LyricsBackend value); void setBackend(LyricsBackend::Backend value);
void setLoading(bool value); void setLoading(bool value);
void setLines(QVector<LyricLine> lines, LyricsBackend source); void setLines(QVector<LyricLine> lines, LyricsBackend::Backend source);
void clearLines(); void clearLines();
void appendCandidates(const QList<LyricCandidate>& add); void appendCandidates(const QList<LyricCandidate>& add);
void clearCandidates(); void clearCandidates();
@ -84,7 +83,7 @@ private:
void tryLocal(int reqId); void tryLocal(int reqId);
void tryLrclib(int reqId); void tryLrclib(int reqId);
void tryNetEase(int reqId); void tryNetEase(int reqId);
void chainNext(LyricsBackend just_failed, int reqId); void chainNext(LyricsBackend::Backend just_failed, int reqId);
void searchLrclibCandidates(int reqId); void searchLrclibCandidates(int reqId);
void searchNetEaseCandidates(int reqId); void searchNetEaseCandidates(int reqId);
@ -104,13 +103,13 @@ private:
[[nodiscard]] QString lyricsDir() const; [[nodiscard]] QString lyricsDir() const;
[[nodiscard]] QString lyricsMapPath() const; [[nodiscard]] QString lyricsMapPath() const;
[[nodiscard]] QString trackKey() const; [[nodiscard]] QString trackKey() const;
[[nodiscard]] static QString backendKey(LyricsBackend value); [[nodiscard]] static QString backendKey(LyricsBackend::Backend value);
[[nodiscard]] static LyricsBackend backendFromKey(const QString& key); [[nodiscard]] static LyricsBackend::Backend backendFromKey(const QString& key);
[[nodiscard]] static const QString& cacheDir(); [[nodiscard]] static const QString& cacheDir();
[[nodiscard]] static QString cachePathFor(LyricsBackend backend, const QString& id); [[nodiscard]] static QString cachePathFor(LyricsBackend::Backend backend, const QString& id);
[[nodiscard]] static QString readCachedLrc(LyricsBackend backend, const QString& id); [[nodiscard]] static QString readCachedLrc(LyricsBackend::Backend backend, const QString& id);
static void writeCachedLrc(LyricsBackend backend, const QString& id, const QString& text); static void writeCachedLrc(LyricsBackend::Backend backend, const QString& id, const QString& text);
[[nodiscard]] static QVector<LyricLine> parseLrc(const QString& text); [[nodiscard]] static QVector<LyricLine> parseLrc(const QString& text);
[[nodiscard]] static QString tryReadLocalLrc(const QString& dir, const QString& artist, const QString& title); [[nodiscard]] static QString tryReadLocalLrc(const QString& dir, const QString& artist, const QString& title);
@ -121,8 +120,8 @@ private:
QVector<LyricLine> m_lines; QVector<LyricLine> m_lines;
QStringList m_lyrics; QStringList m_lyrics;
LyricsBackend m_backend = Auto; LyricsBackend::Backend m_backend = LyricsBackend::Auto;
LyricsBackend m_preferredBackend = Auto; LyricsBackend::Backend m_preferredBackend = LyricsBackend::Auto;
QList<LyricCandidate> m_candidates; QList<LyricCandidate> m_candidates;
LyricCandidate m_selected; LyricCandidate m_selected;
bool m_loading = false; bool m_loading = false;