1 /*
2 * Cantata
3 *
4 * Copyright (c) 2011-2020 Craig Drummond <craig.p.drummond@gmail.com>
5 *
6 * ----
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24 #include "soundcloudservice.h"
25 #include "gui/apikeys.h"
26 #include "network/networkaccessmanager.h"
27 #include "mpd-interface/mpdconnection.h"
28 #include "support/utils.h"
29 #include "support/monoicon.h"
30 #include <QUrl>
31 #include <QUrlQuery>
32 #include <QJsonDocument>
33
34 static const QLatin1String constName("soundcloud");
35 static const QLatin1String constUrl("https://api.soundcloud.com/tracks");
36
SoundCloudService(QObject * p)37 SoundCloudService::SoundCloudService(QObject *p)
38 : OnlineSearchService(p)
39 {
40 icn=MonoIcon::icon(FontAwesome::soundcloud, Utils::monoIconColor());
41 }
42
name() const43 QString SoundCloudService::name() const
44 {
45 return constName;
46 }
47
title() const48 QString SoundCloudService::title() const
49 {
50 return QLatin1String("SoundCloud");
51 }
52
descr() const53 QString SoundCloudService::descr() const
54 {
55 return tr("Search for tracks from soundcloud.com");
56 }
57
search(const QString & key,const QString & value)58 void SoundCloudService::search(const QString &key, const QString &value)
59 {
60 Q_UNUSED(key);
61
62 if (value==currentValue) {
63 return;
64 }
65
66 clear();
67 cancel();
68
69 currentValue=value;
70
71 if (currentValue.isEmpty()) {
72 return;
73 }
74
75 QUrl searchUrl(constUrl);
76 QUrlQuery query;
77 ApiKeys::self()->addKey(query, ApiKeys::SoundCloud);
78 query.addQueryItem("q", currentValue);
79 query.addQueryItem("limit", QString::number(200));
80 searchUrl.setQuery(query);
81
82 QNetworkRequest req(searchUrl);
83 req.setRawHeader("Accept", "application/json");
84 job=NetworkAccessManager::self()->get(req);
85 connect(job, SIGNAL(finished()), this, SLOT(jobFinished()));
86 emit searching();
87 emit dataChanged(QModelIndex(), QModelIndex());
88 }
89
jobFinished()90 void SoundCloudService::jobFinished()
91 {
92 NetworkJob *j=dynamic_cast<NetworkJob *>(sender());
93 if (!j || j!=job) {
94 return;
95 }
96
97 j->deleteLater();
98 QList<Song> songs;
99
100 if (j->ok()) {
101 QVariant result=QJsonDocument::fromJson(j->readAll()).toVariant();
102 if (result.isValid()) {
103 QVariantList list = result.toList();
104 for (const QVariant &item: list) {
105 QVariantMap details=item.toMap();
106 if (details["title"].toString().isEmpty()) {
107 continue;
108 }
109 Song song;
110 QUrl url = details["stream_url"].toUrl();
111 QUrlQuery query;
112 ApiKeys::self()->addKey(query, ApiKeys::SoundCloud);
113 url.setQuery(query);
114 // MPD does not seem to support https :-(
115 if (QLatin1String("https")==url.scheme() && !MPDConnection::self()->urlHandlers().contains(QLatin1String("https"))) {
116 url.setScheme(QLatin1String("http"));
117 }
118 song.file=url.toString();
119 // We don't have a real artist name, but username is the most similar thing we have
120 song.artist=details["user"].toMap()["username"].toString();
121 song.title=details["title"].toString();
122 song.genres[0]=details["genre"].toString();
123 song.year=details["release_year"].toInt();
124 song.time=details["duration"].toUInt()/1000;
125 song.fillEmptyFields();
126 songs.append(song);
127 }
128 }
129 } else {
130 ApiKeys::self()->isLimitReached(j->actualJob(), ApiKeys::SoundCloud);
131 }
132 results(songs);
133 job=nullptr;
134 emit dataChanged(QModelIndex(), QModelIndex());
135 }
136
137 #include "moc_soundcloudservice.cpp"
138