diff --git a/Changelog b/Changelog index dc8e408a..e100113c 100644 --- a/Changelog +++ b/Changelog @@ -120,7 +120,6 @@ Version 0.6.1: * Replaced FTS3 and custom tokenizer with FTS5 with unicode61. * Fixed certain cases where track slider popup was stuck. * Fixed certain cases where the playing widget gets stuck when switching fast between context and other widgets. - * Removed ChartLyrics provider (service have been down for a long time). Version 0.5.5: diff --git a/README.md b/README.md index 29fa0150..710ec510 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Strawberry is a music player and music collection organizer. It is a fork of Cle * Edit tags on music files * Fetch tags from MusicBrainz * Album cover art from Last.fm, Musicbrainz, Discogs, Deezer and Tidal - * Song lyrics from AudD, lyrics.ovh and lololyrics.com + * Song lyrics from AudD, ChartLyrics, lyrics.ovh and lololyrics.com * Support for multiple backends * Audio analyzer * Audio equalizer diff --git a/debian/control b/debian/control index 542ad698..8856d200 100644 --- a/debian/control +++ b/debian/control @@ -58,7 +58,7 @@ Description: Audio player and music collection organizer - Edit tags on music files - Fetch tags from MusicBrainz - Album cover art from Lastfm, Musicbrainz, Discogs, Deezer and Tidal - - Song lyrics from AudD, lyrics.ovh and lololyrics.com + - Song lyrics from AudD, ChartLyrics, lyrics.ovh and lololyrics.com - Support for multiple backends - Audio analyzer - Audio equalizer diff --git a/dist/man/strawberry.1 b/dist/man/strawberry.1 index 340995e2..ff2d99b6 100644 --- a/dist/man/strawberry.1 +++ b/dist/man/strawberry.1 @@ -27,7 +27,7 @@ Features: .br - Album cover art from Lastfm, Musicbrainz, Discogs, Deezer and Tidal .br -- Song lyrics from AudD, lyrics.ovh and lololyrics.com +- Song lyrics from AudD, ChartLyrics, lyrics.ovh and lololyrics.com .br - Support for multiple backends .br diff --git a/dist/rpm/strawberry.spec.in b/dist/rpm/strawberry.spec.in index 60f24899..7caa188c 100644 --- a/dist/rpm/strawberry.spec.in +++ b/dist/rpm/strawberry.spec.in @@ -103,7 +103,7 @@ Features: - Edit tags on music files - Fetch tags from MusicBrainz - Album cover art from Last.fm, Musicbrainz, Discogs, Deezer and Tidal - - Song lyrics from AudD, lyrics.ovh and lololyrics.com + - Song lyrics from AudD, ChartLyrics, lyrics.ovh and lololyrics.com - Support for multiple backends - Audio analyzer - Audio equalizer diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 00ced7ef..52dc502d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -235,6 +235,7 @@ set(SOURCES lyrics/auddlyricsprovider.cpp lyrics/ovhlyricsprovider.cpp lyrics/lololyricsprovider.cpp + lyrics/chartlyricsprovider.cpp settings/settingsdialog.cpp settings/settingspage.cpp @@ -419,6 +420,7 @@ set(HEADERS lyrics/auddlyricsprovider.h lyrics/ovhlyricsprovider.h lyrics/lololyricsprovider.h + lyrics/chartlyricsprovider.h settings/settingsdialog.h settings/settingspage.h diff --git a/src/core/application.cpp b/src/core/application.cpp index e83787b2..aa679fc5 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -61,6 +61,7 @@ #include "lyrics/auddlyricsprovider.h" #include "lyrics/ovhlyricsprovider.h" #include "lyrics/lololyricsprovider.h" +#include "lyrics/chartlyricsprovider.h" #include "scrobbler/audioscrobbler.h" @@ -139,6 +140,7 @@ class ApplicationImpl { lyrics_providers->AddProvider(new AuddLyricsProvider(app)); lyrics_providers->AddProvider(new OVHLyricsProvider(app)); lyrics_providers->AddProvider(new LoloLyricsProvider(app)); + lyrics_providers->AddProvider(new ChartLyricsProvider(app)); return lyrics_providers; }), internet_services_([=]() { diff --git a/src/lyrics/chartlyricsprovider.cpp b/src/lyrics/chartlyricsprovider.cpp new file mode 100644 index 00000000..684b2246 --- /dev/null +++ b/src/lyrics/chartlyricsprovider.cpp @@ -0,0 +1,135 @@ +/* + * Strawberry Music Player + * Copyright 2018, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/closure.h" +#include "core/logging.h" +#include "core/network.h" +#include "core/utilities.h" +#include "lyricsprovider.h" +#include "lyricsfetcher.h" +#include "chartlyricsprovider.h" + +const char *ChartLyricsProvider::kUrlSearch = "http://api.chartlyrics.com/apiv1.asmx/SearchLyricDirect"; +const int ChartLyricsProvider::kMaxLength = 6000; + +ChartLyricsProvider::ChartLyricsProvider(QObject *parent) : LyricsProvider("ChartLyrics", parent), network_(new NetworkAccessManager(this)) {} + +bool ChartLyricsProvider::StartSearch(const QString &artist, const QString &album, const QString &title, const quint64 id) { + + const ParamList params = ParamList() << Param("artist", artist) + << Param("song", title); + + QUrlQuery url_query; + for (const Param ¶m : params) { + url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second)); + } + + QUrl url(kUrlSearch); + url.setQuery(url_query); + QNetworkReply *reply = network_->get(QNetworkRequest(url)); + NewClosure(reply, SIGNAL(finished()), this, SLOT(HandleSearchReply(QNetworkReply*, const quint64, const QString&, const QString&)), reply, id, artist, title); + + //qLog(Debug) << "ChartLyrics: Sending request for" << url; + + return true; + +} + +void ChartLyricsProvider::CancelSearch(const quint64 id) { +} + +void ChartLyricsProvider::HandleSearchReply(QNetworkReply *reply, const quint64 id, const QString &artist, const QString &title) { + + reply->deleteLater(); + + if (reply->error() != QNetworkReply::NoError) { + QString failure_reason = QString("%1 (%2)").arg(reply->errorString()).arg(reply->error()); + Error(id, failure_reason); + return; + } + + if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) { + QString failure_reason = QString("Received HTTP code %1").arg(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt()); + Error(id, failure_reason); + return; + } + + QXmlStreamReader reader(reply); + LyricsSearchResults results; + LyricsSearchResult result; + + while (!reader.atEnd()) { + QXmlStreamReader::TokenType type = reader.readNext(); + QStringRef name = reader.name(); + if (type == QXmlStreamReader::StartElement) { + if (name == "GetLyricResult") { + result = LyricsSearchResult(); + } + if (name == "LyricArtist") { + result.artist = reader.readElementText(); + } + else if (name == "LyricSong") { + result.title = reader.readElementText(); + } + else if (name == "Lyric") { + result.lyrics = reader.readElementText(); + } + } + else if (type == QXmlStreamReader::EndElement) { + if (name == "GetLyricResult") { + if (!result.artist.isEmpty() && !result.title.isEmpty() && !result.lyrics.isEmpty()) { + result.score = 0.0; + if (result.artist.toLower() == artist.toLower()) result.score += 1.0; + if (result.title.toLower() == title.toLower()) result.score += 1.0; + if (result.artist.toLower() == artist.toLower() || result.title.toLower() == title.toLower()) { + results << result; + } + } + result = LyricsSearchResult(); + } + } + } + + if (results.isEmpty()) qLog(Debug) << "ChartLyrics: No lyrics for" << artist << title; + else qLog(Debug) << "ChartLyrics: Got lyrics for" << artist << title; + + emit SearchFinished(id, results); + +} + +void ChartLyricsProvider::Error(const quint64 id, const QString &error, QVariant debug) { + qLog(Error) << "ChartLyrics:" << error; + if (debug.isValid()) qLog(Debug) << debug; + emit SearchFinished(id, LyricsSearchResults()); +} diff --git a/src/lyrics/chartlyricsprovider.h b/src/lyrics/chartlyricsprovider.h new file mode 100644 index 00000000..65a4c043 --- /dev/null +++ b/src/lyrics/chartlyricsprovider.h @@ -0,0 +1,56 @@ +/* + * Strawberry Music Player + * Copyright 2018, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef CHARTLYRICSPROVIDER_H +#define CHARTLYRICSPROVIDER_H + +#include "config.h" + +#include + +#include +#include +#include +#include +#include + +#include "lyricsprovider.h" +#include "lyricsfetcher.h" + +class ChartLyricsProvider : public LyricsProvider { + Q_OBJECT + + public: + explicit ChartLyricsProvider(QObject *parent = nullptr); + + bool StartSearch(const QString &artist, const QString &album, const QString &title, const quint64 id); + void CancelSearch(quint64 id); + + private slots: + void HandleSearchReply(QNetworkReply *reply, const quint64 id, const QString &artist, const QString &title); + + private: + static const char *kUrlSearch; + static const int kMaxLength; + QNetworkAccessManager *network_; + void Error(const quint64 id, const QString &error, QVariant debug = QVariant()); + +}; + +#endif // CHARTLYRICSPROVIDER_H