Files
audiotube/src/lyricsmodel.cpp
T

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();
}