122 lines
3.3 KiB
C++
122 lines
3.3 KiB
C++
// SPDX-FileCopyrightText: 2024 Kavinu Nethsara <[email protected]>
|
|
//
|
|
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
|
|
|
#include "lyricsmodel.h"
|
|
|
|
#include <QObject>
|
|
#include <QNetworkRequest>
|
|
#include <QNetworkReply>
|
|
#include <QRegularExpression>
|
|
#include <QAbstractListModel>
|
|
|
|
#include "library.h"
|
|
|
|
using namespace Qt::Literals::StringLiterals;
|
|
|
|
LyricsModel::LyricsModel(QObject *parent) : QAbstractListModel(parent) {}
|
|
|
|
int LyricsModel::rowCount(const QModelIndex &parent) const
|
|
{
|
|
return parent.isValid() ? 0 : m_lyrics.count();
|
|
}
|
|
|
|
QVariant LyricsModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
switch (role) {
|
|
case Line:
|
|
return m_lyrics[index.row()].text;
|
|
case Start:
|
|
return m_lyrics[index.row()].start;
|
|
case End:
|
|
return m_lyrics[index.row()].end;
|
|
}
|
|
|
|
Q_UNREACHABLE();
|
|
|
|
return {};
|
|
}
|
|
|
|
QHash<int, QByteArray> LyricsModel::roleNames() const
|
|
{
|
|
return {
|
|
{Line, "line"},
|
|
{Start, "start"},
|
|
{End, "end"}
|
|
};
|
|
}
|
|
|
|
void LyricsModel::fetchLyrics() {
|
|
QUrl url(u"https://lrclib.net/"_s);
|
|
url.setPath(u"/api/get"_s);
|
|
|
|
QUrlQuery query;
|
|
query.addQueryItem(u"track_name"_s, m_song);
|
|
query.addQueryItem(u"artist_name"_s, m_artist);
|
|
query.addQueryItem(u"album_name"_s, m_album);
|
|
query.addQueryItem(u"duration"_s, QString::number(m_duration));
|
|
|
|
url.setQuery(query);
|
|
|
|
QNetworkReply *reply = Library::instance().nam().get(QNetworkRequest(url));
|
|
connect(reply, &QNetworkReply::finished, this, [=, this] {
|
|
setLyrics(reply);
|
|
});
|
|
connect(reply, &QNetworkReply::errorOccurred, this, [=, this] {
|
|
setLyrics(reply);
|
|
});
|
|
}
|
|
|
|
void LyricsModel::setLyrics(QNetworkReply *reply) {
|
|
beginResetModel();
|
|
auto content = QJsonDocument::fromJson(reply->readAll()).object();
|
|
QList<SyncLine> syncLyrics{};
|
|
if (content.contains(u"syncedLyrics"_s)) {
|
|
syncLyrics = parseSyncedLyrics(content[u"syncedLyrics"_s].toString());
|
|
}
|
|
m_lyrics = syncLyrics;
|
|
Q_EMIT endResetModel();
|
|
Q_EMIT countChanged();
|
|
}
|
|
|
|
QList<SyncLine> LyricsModel::parseSyncedLyrics(const QString &synclrc) {
|
|
QRegularExpression regex{uR"(\[(\d{2}):(\d{2})\.(\d{2})\]\s*(.*))"_s};
|
|
QList<SyncLine> lyrics;
|
|
QStringList lines = synclrc.split(u'\n', Qt::KeepEmptyParts);
|
|
for (int i = 0; i < lines.count(); i++) {
|
|
auto match = regex.match(lines[i]);
|
|
|
|
double time = 0;
|
|
double finishTime = m_duration;
|
|
QString line;
|
|
|
|
if (match.hasMatch()) {
|
|
int minutes = match.captured(1).toInt();
|
|
int seconds = match.captured(2).toInt();
|
|
int centiseconds = match.captured(3).toInt();
|
|
time = minutes * 60 + seconds + centiseconds * 0.01;
|
|
line = match.captured(4);
|
|
}
|
|
|
|
if (i < lines.count() - 1){
|
|
auto futurematch = regex.match(lines[i + 1]);
|
|
|
|
int minutes = futurematch.captured(1).toInt();
|
|
int seconds = futurematch.captured(2).toInt();
|
|
int centiseconds = futurematch.captured(3).toInt();
|
|
finishTime = minutes * 60 + seconds + centiseconds * 0.01;
|
|
}
|
|
|
|
lyrics.push_back(SyncLine {
|
|
time,
|
|
finishTime,
|
|
line
|
|
});
|
|
}
|
|
return lyrics;
|
|
}
|
|
|
|
int LyricsModel::count() const {
|
|
return m_lyrics.count();
|
|
}
|