Line
Link Here
|
0 |
-- Clementine-1.3.1/CMakeLists.txt |
0 |
++ Clementine-1.3.1/CMakeLists.txt |
Lines 365-373
Link Here
|
365 |
endif (NOT APPLE) |
365 |
endif (NOT APPLE) |
366 |
endif (USE_SYSTEM_QXT) |
366 |
endif (USE_SYSTEM_QXT) |
367 |
|
367 |
|
368 |
find_path(ECHONEST_INCLUDE_DIRS echonest/echonest_export.h) |
|
|
369 |
find_library(ECHONEST_LIBRARIES echonest) |
370 |
|
371 |
# Use system gmock if it's available |
368 |
# Use system gmock if it's available |
372 |
# We need to look for both gmock and gtest |
369 |
# We need to look for both gmock and gtest |
373 |
find_path(GMOCK_INCLUDE_DIRS gmock/gmock.h) |
370 |
find_path(GMOCK_INCLUDE_DIRS gmock/gmock.h) |
374 |
-- Clementine-1.3.1/src/CMakeLists.txt |
371 |
++ Clementine-1.3.1/src/CMakeLists.txt |
Lines 35-41
Link Here
|
35 |
include_directories(${QTSINGLEAPPLICATION_INCLUDE_DIRS}) |
35 |
include_directories(${QTSINGLEAPPLICATION_INCLUDE_DIRS}) |
36 |
include_directories(${QTIOCOMPRESSOR_INCLUDE_DIRS}) |
36 |
include_directories(${QTIOCOMPRESSOR_INCLUDE_DIRS}) |
37 |
include_directories(${QXT_INCLUDE_DIRS}) |
37 |
include_directories(${QXT_INCLUDE_DIRS}) |
38 |
include_directories(${ECHONEST_INCLUDE_DIRS}) |
|
|
39 |
include_directories(${SHA2_INCLUDE_DIRS}) |
38 |
include_directories(${SHA2_INCLUDE_DIRS}) |
40 |
include_directories(${CHROMAPRINT_INCLUDE_DIRS}) |
39 |
include_directories(${CHROMAPRINT_INCLUDE_DIRS}) |
41 |
include_directories(${MYGPOQT_INCLUDE_DIRS}) |
40 |
include_directories(${MYGPOQT_INCLUDE_DIRS}) |
Lines 297-304
Link Here
|
297 |
songinfo/artistinfoview.cpp |
296 |
songinfo/artistinfoview.cpp |
298 |
songinfo/collapsibleinfoheader.cpp |
297 |
songinfo/collapsibleinfoheader.cpp |
299 |
songinfo/collapsibleinfopane.cpp |
298 |
songinfo/collapsibleinfopane.cpp |
300 |
songinfo/echonestbiographies.cpp |
|
|
301 |
songinfo/echonestimages.cpp |
302 |
songinfo/songinfobase.cpp |
299 |
songinfo/songinfobase.cpp |
303 |
songinfo/songinfofetcher.cpp |
300 |
songinfo/songinfofetcher.cpp |
304 |
songinfo/songinfoprovider.cpp |
301 |
songinfo/songinfoprovider.cpp |
Lines 586-593
Link Here
|
586 |
songinfo/artistinfoview.h |
583 |
songinfo/artistinfoview.h |
587 |
songinfo/collapsibleinfoheader.h |
584 |
songinfo/collapsibleinfoheader.h |
588 |
songinfo/collapsibleinfopane.h |
585 |
songinfo/collapsibleinfopane.h |
589 |
songinfo/echonestbiographies.h |
|
|
590 |
songinfo/echonestimages.h |
591 |
songinfo/songinfobase.h |
586 |
songinfo/songinfobase.h |
592 |
songinfo/songinfofetcher.h |
587 |
songinfo/songinfofetcher.h |
593 |
songinfo/songinfoprovider.h |
588 |
songinfo/songinfoprovider.h |
Lines 822-837
Link Here
|
822 |
internet/lastfm/lastfmcompat.cpp |
817 |
internet/lastfm/lastfmcompat.cpp |
823 |
internet/lastfm/lastfmservice.cpp |
818 |
internet/lastfm/lastfmservice.cpp |
824 |
internet/lastfm/lastfmsettingspage.cpp |
819 |
internet/lastfm/lastfmsettingspage.cpp |
825 |
songinfo/echonestsimilarartists.cpp |
|
|
826 |
songinfo/echonesttags.cpp |
827 |
songinfo/lastfmtrackinfoprovider.cpp |
820 |
songinfo/lastfmtrackinfoprovider.cpp |
828 |
songinfo/tagwidget.cpp |
821 |
songinfo/tagwidget.cpp |
829 |
HEADERS |
822 |
HEADERS |
830 |
covers/lastfmcoverprovider.h |
823 |
covers/lastfmcoverprovider.h |
831 |
internet/lastfm/lastfmservice.h |
824 |
internet/lastfm/lastfmservice.h |
832 |
internet/lastfm/lastfmsettingspage.h |
825 |
internet/lastfm/lastfmsettingspage.h |
833 |
songinfo/echonestsimilarartists.h |
|
|
834 |
songinfo/echonesttags.h |
835 |
songinfo/lastfmtrackinfoprovider.h |
826 |
songinfo/lastfmtrackinfoprovider.h |
836 |
songinfo/tagwidget.h |
827 |
songinfo/tagwidget.h |
837 |
UI |
828 |
UI |
Lines 1241-1247
Link Here
|
1241 |
${TAGLIB_LIBRARIES} |
1232 |
${TAGLIB_LIBRARIES} |
1242 |
${MYGPOQT_LIBRARIES} |
1233 |
${MYGPOQT_LIBRARIES} |
1243 |
${CHROMAPRINT_LIBRARIES} |
1234 |
${CHROMAPRINT_LIBRARIES} |
1244 |
${ECHONEST_LIBRARIES} |
|
|
1245 |
${GOBJECT_LIBRARIES} |
1235 |
${GOBJECT_LIBRARIES} |
1246 |
${GLIB_LIBRARIES} |
1236 |
${GLIB_LIBRARIES} |
1247 |
${GIO_LIBRARIES} |
1237 |
${GIO_LIBRARIES} |
1248 |
-- Clementine-1.3.1/src/main.cpp |
1238 |
++ Clementine-1.3.1/src/main.cpp |
Lines 76-83
Link Here
|
76 |
#include <glib.h> |
76 |
#include <glib.h> |
77 |
#include <gst/gst.h> |
77 |
#include <gst/gst.h> |
78 |
|
78 |
|
79 |
#include <echonest/Config.h> |
|
|
80 |
|
81 |
#ifdef Q_OS_DARWIN |
79 |
#ifdef Q_OS_DARWIN |
82 |
#include <sys/resource.h> |
80 |
#include <sys/resource.h> |
83 |
#include <sys/sysctl.h> |
81 |
#include <sys/sysctl.h> |
Lines 401-408
Link Here
|
401 |
// Add root CA cert for SoundCloud, whose certificate is missing on OS X. |
399 |
// Add root CA cert for SoundCloud, whose certificate is missing on OS X. |
402 |
QSslSocket::addDefaultCaCertificates( |
400 |
QSslSocket::addDefaultCaCertificates( |
403 |
QSslCertificate::fromPath(":/soundcloud-ca.pem", QSsl::Pem)); |
401 |
QSslCertificate::fromPath(":/soundcloud-ca.pem", QSsl::Pem)); |
404 |
QSslSocket::addDefaultCaCertificates( |
402 |
QSslSocket::addDefaultCaCertificates(QSslCertificate::fromPath( |
405 |
QSslCertificate::fromPath(":/Equifax_Secure_Certificate_Authority.pem", QSsl::Pem)); |
403 |
":/Equifax_Secure_Certificate_Authority.pem", QSsl::Pem)); |
406 |
|
404 |
|
407 |
// Has the user forced a different language? |
405 |
// Has the user forced a different language? |
408 |
QString override_language = options.language(); |
406 |
QString override_language = options.language(); |
Lines 440-449
Link Here
|
440 |
Application app; |
438 |
Application app; |
441 |
app.set_language_name(language); |
439 |
app.set_language_name(language); |
442 |
|
440 |
|
443 |
Echonest::Config::instance()->setAPIKey("DFLFLJBUF4EGTXHIG"); |
|
|
444 |
Echonest::Config::instance()->setNetworkAccessManager( |
445 |
new NetworkAccessManager); |
446 |
|
447 |
// Network proxy |
441 |
// Network proxy |
448 |
QNetworkProxyFactory::setApplicationProxyFactory( |
442 |
QNetworkProxyFactory::setApplicationProxyFactory( |
449 |
NetworkProxyFactory::Instance()); |
443 |
NetworkProxyFactory::Instance()); |
450 |
-- Clementine-1.3.1/src/songinfo/artistinfoview.cpp |
444 |
++ Clementine-1.3.1/src/songinfo/artistinfoview.cpp |
Lines 16-40
Link Here
|
16 |
*/ |
16 |
*/ |
17 |
|
17 |
|
18 |
#include "artistinfoview.h" |
18 |
#include "artistinfoview.h" |
19 |
#include "echonestbiographies.h" |
|
|
20 |
#include "echonestimages.h" |
21 |
#include "songinfofetcher.h" |
19 |
#include "songinfofetcher.h" |
22 |
#include "songkickconcerts.h" |
20 |
#include "songkickconcerts.h" |
23 |
#include "widgets/prettyimageview.h" |
21 |
#include "widgets/prettyimageview.h" |
24 |
|
22 |
|
25 |
#ifdef HAVE_LIBLASTFM |
|
|
26 |
#include "echonestsimilarartists.h" |
27 |
#include "echonesttags.h" |
28 |
#endif |
29 |
|
30 |
ArtistInfoView::ArtistInfoView(QWidget* parent) : SongInfoBase(parent) { |
23 |
ArtistInfoView::ArtistInfoView(QWidget* parent) : SongInfoBase(parent) { |
31 |
fetcher_->AddProvider(new EchoNestBiographies); |
|
|
32 |
fetcher_->AddProvider(new EchoNestImages); |
33 |
fetcher_->AddProvider(new SongkickConcerts); |
24 |
fetcher_->AddProvider(new SongkickConcerts); |
34 |
#ifdef HAVE_LIBLASTFM |
|
|
35 |
fetcher_->AddProvider(new EchoNestSimilarArtists); |
36 |
fetcher_->AddProvider(new EchoNestTags); |
37 |
#endif |
38 |
} |
25 |
} |
39 |
|
26 |
|
40 |
ArtistInfoView::~ArtistInfoView() {} |
27 |
ArtistInfoView::~ArtistInfoView() {} |
41 |
-- Clementine-1.3.1/src/songinfo/echonestbiographies.cpp |
28 |
++ Clementine-1.3.1/src/songinfo/echonestbiographies.cpp |
Lines 1-123
Link Here
|
1 |
/* This file is part of Clementine. |
0 |
++ Clementine-1.3.1/src/songinfo/echonestbiographies.h |
2 |
Copyright 2010, David Sansome <me@davidsansome.com> |
|
|
3 |
|
4 |
Clementine is free software: you can redistribute it and/or modify |
5 |
it under the terms of the GNU General Public License as published by |
6 |
the Free Software Foundation, either version 3 of the License, or |
7 |
(at your option) any later version. |
8 |
|
9 |
Clementine is distributed in the hope that it will be useful, |
10 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
GNU General Public License for more details. |
13 |
|
14 |
You should have received a copy of the GNU General Public License |
15 |
along with Clementine. If not, see <http://www.gnu.org/licenses/>. |
16 |
*/ |
17 |
|
18 |
#include "echonestbiographies.h" |
19 |
|
20 |
#include <memory> |
21 |
|
22 |
#include <echonest/Artist.h> |
23 |
|
24 |
#include "songinfotextview.h" |
25 |
#include "core/logging.h" |
26 |
#include "ui/iconloader.h" |
27 |
|
28 |
struct EchoNestBiographies::Request { |
29 |
Request(int id) : id_(id), artist_(new Echonest::Artist) {} |
30 |
|
31 |
int id_; |
32 |
std::unique_ptr<Echonest::Artist> artist_; |
33 |
}; |
34 |
|
35 |
EchoNestBiographies::EchoNestBiographies() { |
36 |
site_relevance_["wikipedia"] = 100; |
37 |
site_relevance_["lastfm"] = 60; |
38 |
site_relevance_["amazon"] = 30; |
39 |
|
40 |
site_icons_["amazon"] = IconLoader::Load("amazon", IconLoader::Provider); |
41 |
site_icons_["aol"] = IconLoader::Load("aol", IconLoader::Provider); |
42 |
site_icons_["cdbaby"] = IconLoader::Load("cdbaby", IconLoader::Provider); |
43 |
site_icons_["lastfm"] = IconLoader::Load("as", IconLoader::Lastfm); |
44 |
site_icons_["mog"] = IconLoader::Load("mog", IconLoader::Provider); |
45 |
site_icons_["mtvmusic"] = IconLoader::Load("mtvmusic", IconLoader::Provider); |
46 |
site_icons_["myspace"] = IconLoader::Load("myspace", IconLoader::Provider); |
47 |
site_icons_["wikipedia"] = IconLoader::Load("wikipedia", IconLoader::Provider); |
48 |
} |
49 |
|
50 |
void EchoNestBiographies::FetchInfo(int id, const Song& metadata) { |
51 |
std::shared_ptr<Request> request(new Request(id)); |
52 |
request->artist_->setName(metadata.artist()); |
53 |
|
54 |
QNetworkReply* reply = request->artist_->fetchBiographies(); |
55 |
connect(reply, SIGNAL(finished()), SLOT(RequestFinished())); |
56 |
requests_[reply] = request; |
57 |
} |
58 |
|
59 |
void EchoNestBiographies::RequestFinished() { |
60 |
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender()); |
61 |
if (!reply || !requests_.contains(reply)) return; |
62 |
reply->deleteLater(); |
63 |
|
64 |
RequestPtr request = requests_.take(reply); |
65 |
|
66 |
try { |
67 |
request->artist_->parseProfile(reply); |
68 |
} |
69 |
catch (Echonest::ParseError e) { |
70 |
qLog(Warning) << "Error parsing echonest reply:" << e.errorType() |
71 |
<< e.what(); |
72 |
} |
73 |
|
74 |
QSet<QString> already_seen; |
75 |
|
76 |
for (const Echonest::Biography& bio : request->artist_->biographies()) { |
77 |
QString canonical_site = bio.site().toLower(); |
78 |
canonical_site.replace(QRegExp("[^a-z]"), ""); |
79 |
|
80 |
if (already_seen.contains(canonical_site)) continue; |
81 |
already_seen.insert(canonical_site); |
82 |
|
83 |
CollapsibleInfoPane::Data data; |
84 |
data.id_ = "echonest/bio/" + bio.site(); |
85 |
data.title_ = tr("Biography from %1").arg(bio.site()); |
86 |
data.type_ = CollapsibleInfoPane::Data::Type_Biography; |
87 |
|
88 |
if (site_relevance_.contains(canonical_site)) |
89 |
data.relevance_ = site_relevance_[canonical_site]; |
90 |
if (site_icons_.contains(canonical_site)) |
91 |
data.icon_ = site_icons_[canonical_site]; |
92 |
|
93 |
SongInfoTextView* editor = new SongInfoTextView; |
94 |
QString text; |
95 |
// Add a link to the bio webpage at the top if we have one |
96 |
if (!bio.url().isEmpty()) { |
97 |
QString bio_url = bio.url().toEncoded(); |
98 |
if (bio.site() == "facebook") { |
99 |
bio_url.replace("graph.facebook.com", "www.facebook.com"); |
100 |
} |
101 |
text += "<p><a href=\"" + bio_url + "\">" + |
102 |
tr("Open in your browser") + "</a></p>"; |
103 |
} |
104 |
|
105 |
text += bio.text(); |
106 |
if (bio.site() == "last.fm") { |
107 |
// Echonest lost formatting and it seems there is currently no plans on |
108 |
// Echonest side for changing this. |
109 |
// But with last.fm, we can guess newlines: " " corresponds to a newline |
110 |
// (this seems to be because on last.fm' website, extra blank is inserted |
111 |
// before <br /> tag, and this blank is kept). |
112 |
// This is tricky, but this make the display nicer for last.fm |
113 |
// biographies. |
114 |
text.replace(" ", "<p>"); |
115 |
} |
116 |
editor->SetHtml(text); |
117 |
data.contents_ = editor; |
118 |
|
119 |
emit InfoReady(request->id_, data); |
120 |
} |
121 |
|
122 |
emit Finished(request->id_); |
123 |
} |
124 |
-- Clementine-1.3.1/src/songinfo/echonestbiographies.h |
Lines 1-48
Link Here
|
1 |
/* This file is part of Clementine. |
0 |
++ Clementine-1.3.1/src/songinfo/echonestsimilarartists.cpp |
2 |
Copyright 2010, David Sansome <me@davidsansome.com> |
|
|
3 |
|
4 |
Clementine is free software: you can redistribute it and/or modify |
5 |
it under the terms of the GNU General Public License as published by |
6 |
the Free Software Foundation, either version 3 of the License, or |
7 |
(at your option) any later version. |
8 |
|
9 |
Clementine is distributed in the hope that it will be useful, |
10 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
GNU General Public License for more details. |
13 |
|
14 |
You should have received a copy of the GNU General Public License |
15 |
along with Clementine. If not, see <http://www.gnu.org/licenses/>. |
16 |
*/ |
17 |
|
18 |
#ifndef ECHONESTBIOGRAPHIES_H |
19 |
#define ECHONESTBIOGRAPHIES_H |
20 |
|
21 |
#include <memory> |
22 |
|
23 |
#include "songinfoprovider.h" |
24 |
|
25 |
class QNetworkReply; |
26 |
|
27 |
class EchoNestBiographies : public SongInfoProvider { |
28 |
Q_OBJECT |
29 |
|
30 |
public: |
31 |
EchoNestBiographies(); |
32 |
|
33 |
void FetchInfo(int id, const Song& metadata); |
34 |
|
35 |
private slots: |
36 |
void RequestFinished(); |
37 |
|
38 |
private: |
39 |
QMap<QString, int> site_relevance_; |
40 |
QMap<QString, QIcon> site_icons_; |
41 |
|
42 |
struct Request; |
43 |
typedef std::shared_ptr<Request> RequestPtr; |
44 |
|
45 |
QMap<QNetworkReply*, RequestPtr> requests_; |
46 |
}; |
47 |
|
48 |
#endif // ECHONESTBIOGRAPHIES_H |
49 |
-- Clementine-1.3.1/src/songinfo/echonestsimilarartists.cpp |
Lines 1-76
Link Here
|
1 |
/* This file is part of Clementine. |
0 |
++ Clementine-1.3.1/src/songinfo/echonestsimilarartists.h |
2 |
Copyright 2010, David Sansome <me@davidsansome.com> |
|
|
3 |
|
4 |
Clementine is free software: you can redistribute it and/or modify |
5 |
it under the terms of the GNU General Public License as published by |
6 |
the Free Software Foundation, either version 3 of the License, or |
7 |
(at your option) any later version. |
8 |
|
9 |
Clementine is distributed in the hope that it will be useful, |
10 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
GNU General Public License for more details. |
13 |
|
14 |
You should have received a copy of the GNU General Public License |
15 |
along with Clementine. If not, see <http://www.gnu.org/licenses/>. |
16 |
*/ |
17 |
|
18 |
#include "echonestsimilarartists.h" |
19 |
#include "tagwidget.h" |
20 |
#include "core/logging.h" |
21 |
#include "ui/iconloader.h" |
22 |
|
23 |
#include <echonest/Artist.h> |
24 |
|
25 |
Q_DECLARE_METATYPE(QVector<QString>); |
26 |
|
27 |
void EchoNestSimilarArtists::FetchInfo(int id, const Song& metadata) { |
28 |
using Echonest::Artist; |
29 |
|
30 |
Artist::SearchParams params; |
31 |
params << Artist::SearchParamEntry(Artist::Name, metadata.artist()); |
32 |
params << Artist::SearchParamEntry(Artist::MinHotttnesss, 0.5); |
33 |
|
34 |
QNetworkReply* reply = Echonest::Artist::fetchSimilar(params); |
35 |
connect(reply, SIGNAL(finished()), SLOT(RequestFinished())); |
36 |
requests_[reply] = id; |
37 |
} |
38 |
|
39 |
void EchoNestSimilarArtists::RequestFinished() { |
40 |
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender()); |
41 |
if (!reply || !requests_.contains(reply)) return; |
42 |
reply->deleteLater(); |
43 |
|
44 |
int id = requests_.take(reply); |
45 |
|
46 |
Echonest::Artists artists; |
47 |
try { |
48 |
artists = Echonest::Artist::parseSimilar(reply); |
49 |
} |
50 |
catch (Echonest::ParseError e) { |
51 |
qLog(Warning) << "Error parsing echonest reply:" << e.errorType() |
52 |
<< e.what(); |
53 |
} |
54 |
|
55 |
if (!artists.isEmpty()) { |
56 |
CollapsibleInfoPane::Data data; |
57 |
data.id_ = "echonest/similarartists"; |
58 |
data.title_ = tr("Similar artists"); |
59 |
data.type_ = CollapsibleInfoPane::Data::Type_Similar; |
60 |
data.icon_ = IconLoader::Load("echonest", IconLoader::Provider); |
61 |
|
62 |
TagWidget* widget = new TagWidget(TagWidget::Type_Artists); |
63 |
data.contents_ = widget; |
64 |
|
65 |
widget->SetIcon(IconLoader::Load("x-clementine-artist", IconLoader::Base)); |
66 |
|
67 |
for (const Echonest::Artist& artist : artists) { |
68 |
widget->AddTag(artist.name()); |
69 |
if (widget->count() >= 10) break; |
70 |
} |
71 |
|
72 |
emit InfoReady(id, data); |
73 |
} |
74 |
|
75 |
emit Finished(id); |
76 |
} |
77 |
-- Clementine-1.3.1/src/songinfo/echonestsimilarartists.h |
Lines 1-38
Link Here
|
1 |
/* This file is part of Clementine. |
0 |
++ Clementine-1.3.1/src/songinfo/echonesttags.cpp |
2 |
Copyright 2010, David Sansome <me@davidsansome.com> |
|
|
3 |
|
4 |
Clementine is free software: you can redistribute it and/or modify |
5 |
it under the terms of the GNU General Public License as published by |
6 |
the Free Software Foundation, either version 3 of the License, or |
7 |
(at your option) any later version. |
8 |
|
9 |
Clementine is distributed in the hope that it will be useful, |
10 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
GNU General Public License for more details. |
13 |
|
14 |
You should have received a copy of the GNU General Public License |
15 |
along with Clementine. If not, see <http://www.gnu.org/licenses/>. |
16 |
*/ |
17 |
|
18 |
#ifndef ECHONESTSIMILARARTISTS_H |
19 |
#define ECHONESTSIMILARARTISTS_H |
20 |
|
21 |
#include "songinfoprovider.h" |
22 |
|
23 |
class QNetworkReply; |
24 |
|
25 |
class EchoNestSimilarArtists : public SongInfoProvider { |
26 |
Q_OBJECT |
27 |
|
28 |
public: |
29 |
void FetchInfo(int id, const Song& metadata); |
30 |
|
31 |
private slots: |
32 |
void RequestFinished(); |
33 |
|
34 |
private: |
35 |
QMap<QNetworkReply*, int> requests_; |
36 |
}; |
37 |
|
38 |
#endif // ECHONESTSIMILARARTISTS_H |
39 |
-- Clementine-1.3.1/src/songinfo/echonesttags.cpp |
Lines 1-80
Link Here
|
1 |
/* This file is part of Clementine. |
0 |
++ Clementine-1.3.1/src/songinfo/echonesttags.h |
2 |
Copyright 2010, David Sansome <me@davidsansome.com> |
|
|
3 |
|
4 |
Clementine is free software: you can redistribute it and/or modify |
5 |
it under the terms of the GNU General Public License as published by |
6 |
the Free Software Foundation, either version 3 of the License, or |
7 |
(at your option) any later version. |
8 |
|
9 |
Clementine is distributed in the hope that it will be useful, |
10 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
GNU General Public License for more details. |
13 |
|
14 |
You should have received a copy of the GNU General Public License |
15 |
along with Clementine. If not, see <http://www.gnu.org/licenses/>. |
16 |
*/ |
17 |
|
18 |
#include "echonesttags.h" |
19 |
|
20 |
#include <memory> |
21 |
|
22 |
#include <echonest/Artist.h> |
23 |
|
24 |
#include "tagwidget.h" |
25 |
#include "core/logging.h" |
26 |
#include "ui/iconloader.h" |
27 |
|
28 |
struct EchoNestTags::Request { |
29 |
Request(int id) : id_(id), artist_(new Echonest::Artist) {} |
30 |
|
31 |
int id_; |
32 |
std::unique_ptr<Echonest::Artist> artist_; |
33 |
}; |
34 |
|
35 |
void EchoNestTags::FetchInfo(int id, const Song& metadata) { |
36 |
std::shared_ptr<Request> request(new Request(id)); |
37 |
request->artist_->setName(metadata.artist()); |
38 |
|
39 |
QNetworkReply* reply = request->artist_->fetchTerms(); |
40 |
connect(reply, SIGNAL(finished()), SLOT(RequestFinished())); |
41 |
requests_[reply] = request; |
42 |
} |
43 |
|
44 |
void EchoNestTags::RequestFinished() { |
45 |
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender()); |
46 |
if (!reply || !requests_.contains(reply)) return; |
47 |
reply->deleteLater(); |
48 |
|
49 |
RequestPtr request = requests_.take(reply); |
50 |
|
51 |
try { |
52 |
request->artist_->parseProfile(reply); |
53 |
} |
54 |
catch (Echonest::ParseError e) { |
55 |
qLog(Warning) << "Error parsing echonest reply:" << e.errorType() |
56 |
<< e.what(); |
57 |
} |
58 |
|
59 |
if (!request->artist_->terms().isEmpty()) { |
60 |
CollapsibleInfoPane::Data data; |
61 |
data.id_ = "echonest/artisttags"; |
62 |
data.title_ = tr("Artist tags"); |
63 |
data.type_ = CollapsibleInfoPane::Data::Type_Tags; |
64 |
data.icon_ = IconLoader::Load("icon_tag", IconLoader::Lastfm); |
65 |
|
66 |
TagWidget* widget = new TagWidget(TagWidget::Type_Tags); |
67 |
data.contents_ = widget; |
68 |
|
69 |
widget->SetIcon(data.icon_); |
70 |
|
71 |
for (const Echonest::Term& term : request->artist_->terms()) { |
72 |
widget->AddTag(term.name()); |
73 |
if (widget->count() >= 10) break; |
74 |
} |
75 |
|
76 |
emit InfoReady(request->id_, data); |
77 |
} |
78 |
|
79 |
emit Finished(request->id_); |
80 |
} |
81 |
-- Clementine-1.3.1/src/songinfo/echonesttags.h |
Lines 1-43
Link Here
|
1 |
/* This file is part of Clementine. |
0 |
++ Clementine-1.3.1/src/songinfo/songkickconcerts.cpp |
2 |
Copyright 2010, David Sansome <me@davidsansome.com> |
|
|
3 |
|
4 |
Clementine is free software: you can redistribute it and/or modify |
5 |
it under the terms of the GNU General Public License as published by |
6 |
the Free Software Foundation, either version 3 of the License, or |
7 |
(at your option) any later version. |
8 |
|
9 |
Clementine is distributed in the hope that it will be useful, |
10 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
GNU General Public License for more details. |
13 |
|
14 |
You should have received a copy of the GNU General Public License |
15 |
along with Clementine. If not, see <http://www.gnu.org/licenses/>. |
16 |
*/ |
17 |
|
18 |
#ifndef ECHONESTTAGS_H |
19 |
#define ECHONESTTAGS_H |
20 |
|
21 |
#include <memory> |
22 |
|
23 |
#include "songinfoprovider.h" |
24 |
|
25 |
class QNetworkReply; |
26 |
|
27 |
class EchoNestTags : public SongInfoProvider { |
28 |
Q_OBJECT |
29 |
|
30 |
public: |
31 |
void FetchInfo(int id, const Song& metadata); |
32 |
|
33 |
private slots: |
34 |
void RequestFinished(); |
35 |
|
36 |
private: |
37 |
struct Request; |
38 |
typedef std::shared_ptr<Request> RequestPtr; |
39 |
|
40 |
QMap<QNetworkReply*, RequestPtr> requests_; |
41 |
}; |
42 |
|
43 |
#endif // ECHONESTTAGS_H |
44 |
-- Clementine-1.3.1/src/songinfo/songkickconcerts.cpp |
Lines 21-29
Link Here
|
21 |
#include <QVBoxLayout> |
21 |
#include <QVBoxLayout> |
22 |
#include <QXmlStreamWriter> |
22 |
#include <QXmlStreamWriter> |
23 |
|
23 |
|
24 |
#include <echonest/Artist.h> |
|
|
25 |
#include <echonest/TypeInformation.h> |
26 |
|
27 |
#include <qjson/parser.h> |
24 |
#include <qjson/parser.h> |
28 |
|
25 |
|
29 |
#include "core/closure.h" |
26 |
#include "core/closure.h" |
Lines 31-107
Link Here
|
31 |
#include "songkickconcertwidget.h" |
28 |
#include "songkickconcertwidget.h" |
32 |
#include "ui/iconloader.h" |
29 |
#include "ui/iconloader.h" |
33 |
|
30 |
|
34 |
const char* SongkickConcerts::kSongkickArtistBucket = "songkick"; |
31 |
namespace { |
35 |
const char* SongkickConcerts::kSongkickArtistCalendarUrl = |
32 |
const char* kSongkickArtistCalendarUrl = |
36 |
"https://api.songkick.com/api/3.0/artists/%1/calendar.json?" |
33 |
"https://api.songkick.com/api/3.0/artists/%1/calendar.json"; |
37 |
"per_page=5&" |
34 |
const char* kSongkickArtistSearchUrl = |
38 |
"apikey=8rgKfy1WU6IlJFfN"; |
35 |
"https://api.songkick.com/api/3.0/search/artists.json"; |
|
|
36 |
const char* kSongkickApiKey = "8rgKfy1WU6IlJFfN"; |
37 |
} // namespace |
39 |
|
38 |
|
40 |
SongkickConcerts::SongkickConcerts() { |
39 |
SongkickConcerts::SongkickConcerts() { |
41 |
Geolocator* geolocator = new Geolocator; |
40 |
Geolocator* geolocator = new Geolocator; |
42 |
geolocator->Geolocate(); |
41 |
geolocator->Geolocate(); |
43 |
connect(geolocator, SIGNAL(Finished(Geolocator::LatLng)), |
42 |
connect(geolocator, SIGNAL(Finished(Geolocator::LatLng)), |
44 |
SLOT(GeolocateFinished(Geolocator::LatLng))); |
43 |
SLOT(GeolocateFinished(Geolocator::LatLng))); |
45 |
NewClosure(geolocator, SIGNAL(Finished(Geolocator::LatLng)), geolocator, |
44 |
connect(geolocator, SIGNAL(Finished(Geolocator::LatLng)), geolocator, |
46 |
SLOT(deleteLater())); |
45 |
SLOT(deleteLater())); |
47 |
} |
46 |
} |
48 |
|
47 |
|
49 |
void SongkickConcerts::FetchInfo(int id, const Song& metadata) { |
48 |
void SongkickConcerts::FetchInfo(int id, const Song& metadata) { |
50 |
Echonest::Artist::SearchParams params; |
49 |
if (metadata.artist().isEmpty()) { |
51 |
params.push_back( |
50 |
emit Finished(id); |
52 |
qMakePair(Echonest::Artist::Name, QVariant(metadata.artist()))); |
51 |
return; |
53 |
qLog(Debug) << "Params:" << params; |
52 |
} |
54 |
QNetworkReply* reply = Echonest::Artist::search( |
53 |
|
55 |
params, |
54 |
QUrl url(kSongkickArtistSearchUrl); |
56 |
Echonest::ArtistInformation(Echonest::ArtistInformation::NoInformation, |
55 |
url.addQueryItem("apikey", kSongkickApiKey); |
57 |
QStringList() << kSongkickArtistBucket)); |
56 |
url.addQueryItem("query", metadata.artist()); |
58 |
qLog(Debug) << reply->request().url(); |
57 |
|
|
|
58 |
QNetworkRequest request(url); |
59 |
QNetworkReply* reply = network_.get(request); |
59 |
NewClosure(reply, SIGNAL(finished()), this, |
60 |
NewClosure(reply, SIGNAL(finished()), this, |
60 |
SLOT(ArtistSearchFinished(QNetworkReply*, int)), reply, id); |
61 |
SLOT(ArtistSearchFinished(QNetworkReply*, int)), reply, id); |
61 |
} |
62 |
} |
62 |
|
63 |
|
63 |
void SongkickConcerts::ArtistSearchFinished(QNetworkReply* reply, int id) { |
64 |
void SongkickConcerts::ArtistSearchFinished(QNetworkReply* reply, int id) { |
64 |
reply->deleteLater(); |
65 |
reply->deleteLater(); |
65 |
try { |
66 |
|
66 |
Echonest::Artists artists = Echonest::Artist::parseSearch(reply); |
67 |
QJson::Parser parser; |
67 |
if (artists.isEmpty()) { |
68 |
QVariantMap json = parser.parse(reply).toMap(); |
68 |
qLog(Debug) << "Failed to find artist in echonest"; |
69 |
|
69 |
emit Finished(id); |
70 |
QVariantMap results_page = json["resultsPage"].toMap(); |
70 |
return; |
71 |
QVariantMap results = results_page["results"].toMap(); |
71 |
} |
72 |
QVariantList artists = results["artist"].toList(); |
72 |
|
73 |
|
73 |
const Echonest::Artist& artist = artists[0]; |
74 |
if (artists.isEmpty()) { |
74 |
const Echonest::ForeignIds& foreign_ids = artist.foreignIds(); |
|
|
75 |
QString songkick_id; |
76 |
for (const Echonest::ForeignId& id : foreign_ids) { |
77 |
if (id.catalog == "songkick") { |
78 |
songkick_id = id.foreign_id; |
79 |
break; |
80 |
} |
81 |
} |
82 |
|
83 |
if (songkick_id.isEmpty()) { |
84 |
qLog(Debug) << "Failed to fetch songkick foreign id for artist"; |
85 |
emit Finished(id); |
86 |
return; |
87 |
} |
88 |
|
89 |
QStringList split = songkick_id.split(':'); |
90 |
if (split.count() != 3) { |
91 |
qLog(Error) << "Weird songkick id"; |
92 |
emit Finished(id); |
93 |
return; |
94 |
} |
95 |
|
96 |
FetchSongkickCalendar(split[2], id); |
97 |
} catch (Echonest::ParseError& e) { |
98 |
qLog(Error) << "Error parsing echonest reply:" << e.errorType() << e.what(); |
99 |
emit Finished(id); |
75 |
emit Finished(id); |
|
|
76 |
return; |
100 |
} |
77 |
} |
|
|
78 |
|
79 |
QVariantMap artist = artists.first().toMap(); |
80 |
QString artist_id = artist["id"].toString(); |
81 |
|
82 |
FetchSongkickCalendar(artist_id, id); |
101 |
} |
83 |
} |
102 |
|
84 |
|
103 |
void SongkickConcerts::FetchSongkickCalendar(const QString& artist_id, int id) { |
85 |
void SongkickConcerts::FetchSongkickCalendar(const QString& artist_id, int id) { |
104 |
QUrl url(QString(kSongkickArtistCalendarUrl).arg(artist_id)); |
86 |
QUrl url(QString(kSongkickArtistCalendarUrl).arg(artist_id)); |
|
|
87 |
url.addQueryItem("per_page", "5"); |
88 |
url.addQueryItem("apikey", kSongkickApiKey); |
105 |
qLog(Debug) << url; |
89 |
qLog(Debug) << url; |
106 |
QNetworkReply* reply = network_.get(QNetworkRequest(url)); |
90 |
QNetworkReply* reply = network_.get(QNetworkRequest(url)); |
107 |
NewClosure(reply, SIGNAL(finished()), this, |
91 |
NewClosure(reply, SIGNAL(finished()), this, |
108 |
-- Clementine-1.3.1/src/songinfo/songkickconcerts.h |
92 |
++ Clementine-1.3.1/src/songinfo/songkickconcerts.h |
Lines 44-52
Link Here
|
44 |
|
44 |
|
45 |
NetworkAccessManager network_; |
45 |
NetworkAccessManager network_; |
46 |
Geolocator::LatLng latlng_; |
46 |
Geolocator::LatLng latlng_; |
47 |
|
|
|
48 |
static const char* kSongkickArtistBucket; |
49 |
static const char* kSongkickArtistCalendarUrl; |
50 |
}; |
47 |
}; |
51 |
|
48 |
|
52 |
#endif |
49 |
#endif |