mirror of
https://github.com/clementine-player/Clementine
synced 2025-02-02 20:36:44 +01:00
Filter out songkick concerts that are too far away.
This commit is contained in:
parent
86cced782e
commit
0d5d1dbad1
@ -1,5 +1,6 @@
|
||||
#include "geolocator.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include <qjson/parser.h>
|
||||
@ -7,8 +8,9 @@
|
||||
#include <QStringList>
|
||||
|
||||
#include "core/closure.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
const char* Geolocator::kUrl = "https://data.clementine-player.org/geolocate";
|
||||
const char* Geolocator::kUrl = "http://data.clementine-player.org/geolocate";
|
||||
|
||||
using std::numeric_limits;
|
||||
|
||||
@ -22,6 +24,43 @@ Geolocator::LatLng::LatLng(int lat_e6, int lng_e6)
|
||||
lng_e6_(lng_e6) {
|
||||
}
|
||||
|
||||
Geolocator::LatLng::LatLng(const QString& latlng)
|
||||
: lat_e6_(numeric_limits<int>::min()),
|
||||
lng_e6_(numeric_limits<int>::min()) {
|
||||
QStringList split = latlng.split(",");
|
||||
if (split.length() != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const double lat = split[0].toDouble();
|
||||
const double lng = split[1].toDouble();
|
||||
lat_e6_ = static_cast<int>(lat * 1e6);
|
||||
lng_e6_ = static_cast<int>(lng * 1e6);
|
||||
}
|
||||
|
||||
Geolocator::LatLng::LatLng(const QString& lat, const QString& lng) {
|
||||
lat_e6_ = static_cast<int>(lat.toDouble() * 1e6);
|
||||
lng_e6_ = static_cast<int>(lng.toDouble() * 1e6);
|
||||
}
|
||||
|
||||
int Geolocator::LatLng::Distance(const Geolocator::LatLng& other) const {
|
||||
static const int kEarthRadiusMetres = 6372800;
|
||||
|
||||
double lat_a = lat_e6() / 1000000.0 * (M_PI / 180.0);
|
||||
double lng_a = lng_e6() / 1000000.0 * (M_PI / 180.0);
|
||||
|
||||
double lat_b = other.lat_e6() / 1000000.0 * (M_PI / 180.0);
|
||||
double lng_b = other.lng_e6() / 1000000.0 * (M_PI / 180.0);
|
||||
|
||||
double delta_longitude = lng_b - lng_a;
|
||||
|
||||
double sines = sin(lat_a) * sin(lat_b);
|
||||
double cosines = cos(lat_a) * cos(lat_b) * cos(delta_longitude);
|
||||
double central_angle = acos(sines + cosines);
|
||||
double distance_metres = kEarthRadiusMetres * central_angle;
|
||||
return static_cast<int>(distance_metres);
|
||||
}
|
||||
|
||||
bool Geolocator::LatLng::IsValid() const {
|
||||
return lat_e6_ != numeric_limits<int>::min() &&
|
||||
lng_e6_ != numeric_limits<int>::min();
|
||||
@ -34,7 +73,7 @@ Geolocator::Geolocator(QObject* parent)
|
||||
void Geolocator::Geolocate() {
|
||||
QNetworkRequest req = QNetworkRequest(QUrl(kUrl));
|
||||
QNetworkReply* reply = network_.get(req);
|
||||
NewClosure(reply, SIGNAL(finished()), this, SLOT(RequestFinished()));
|
||||
NewClosure(reply, SIGNAL(finished()), this, SLOT(RequestFinished(QNetworkReply*)), reply);
|
||||
}
|
||||
|
||||
void Geolocator::RequestFinished(QNetworkReply* reply) {
|
||||
@ -54,16 +93,13 @@ void Geolocator::RequestFinished(QNetworkReply* reply) {
|
||||
|
||||
QVariantMap map = result.toMap();
|
||||
QString latlng = map["latlng"].toString();
|
||||
QStringList split = latlng.split(",");
|
||||
if (split.length() != 2) {
|
||||
emit Finished(LatLng());
|
||||
return;
|
||||
}
|
||||
|
||||
double lat = split[0].toDouble();
|
||||
double lng = split[1].toDouble();
|
||||
|
||||
emit Finished(
|
||||
LatLng(static_cast<int>(lat * 1e6),
|
||||
static_cast<int>(lng * 1e6)));
|
||||
LatLng ll(latlng);
|
||||
qLog(Debug) << "Gelocated to:" << ll;
|
||||
emit Finished(ll);
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug dbg, const Geolocator::LatLng& ll) {
|
||||
dbg.nospace() << "(" << ll.lat_e6() << "," << ll.lng_e6() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
@ -16,19 +16,22 @@ class Geolocator : public QObject {
|
||||
public:
|
||||
LatLng();
|
||||
LatLng(int lat_e6, int lng_e6);
|
||||
explicit LatLng(const QString& latlng);
|
||||
LatLng(const QString& lat, const QString& lng);
|
||||
|
||||
int lat_e6() const { return lat_e6_; }
|
||||
int lng_e6() const { return lng_e6_; }
|
||||
|
||||
bool IsValid() const;
|
||||
int Distance(const LatLng& other) const;
|
||||
|
||||
private:
|
||||
const int lat_e6_;
|
||||
const int lng_e6_;
|
||||
int lat_e6_;
|
||||
int lng_e6_;
|
||||
};
|
||||
|
||||
signals:
|
||||
void Finished(LatLng latlng);
|
||||
void Finished(Geolocator::LatLng latlng);
|
||||
|
||||
private slots:
|
||||
void RequestFinished(QNetworkReply* reply);
|
||||
@ -39,4 +42,7 @@ class Geolocator : public QObject {
|
||||
static const char* kUrl;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug dbg, const Geolocator::LatLng& ll);
|
||||
Q_DECLARE_METATYPE(Geolocator::LatLng);
|
||||
|
||||
#endif // GEOLOCATOR_H
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "engines/enginebase.h"
|
||||
#include "globalsearch/searchprovider.h"
|
||||
#include "internet/digitallyimportedclient.h"
|
||||
#include "internet/geolocator.h"
|
||||
#include "internet/somafmservice.h"
|
||||
#include "library/directory.h"
|
||||
#include "playlist/playlist.h"
|
||||
@ -293,6 +294,7 @@ int main(int argc, char *argv[]) {
|
||||
qRegisterMetaType<QList<PodcastEpisode> >("QList<PodcastEpisode>");
|
||||
qRegisterMetaType<PodcastList>("PodcastList");
|
||||
qRegisterMetaType<PodcastEpisodeList>("PodcastEpisodeList");
|
||||
qRegisterMetaType<Geolocator::LatLng>("Geolocator::LatLng");
|
||||
|
||||
qRegisterMetaType<GstBuffer*>("GstBuffer*");
|
||||
qRegisterMetaType<GstElement*>("GstElement*");
|
||||
|
@ -34,7 +34,10 @@ const char* SongkickConcerts::kSongkickArtistCalendarUrl =
|
||||
"apikey=8rgKfy1WU6IlJFfN";
|
||||
|
||||
SongkickConcerts::SongkickConcerts() {
|
||||
|
||||
Geolocator* geolocator = new Geolocator;
|
||||
geolocator->Geolocate();
|
||||
connect(geolocator, SIGNAL(Finished(Geolocator::LatLng)), SLOT(GeolocateFinished(Geolocator::LatLng)));
|
||||
NewClosure(geolocator, SIGNAL(Finished(Geolocator::LatLng)), geolocator, SLOT(deleteLater()));
|
||||
}
|
||||
|
||||
void SongkickConcerts::FetchInfo(int id, const Song& metadata) {
|
||||
@ -120,15 +123,35 @@ void SongkickConcerts::CalendarRequestFinished(QNetworkReply* reply, int id) {
|
||||
foreach (const QVariant& v, events) {
|
||||
QVariantMap event = v.toMap();
|
||||
{
|
||||
QString display_name = event["displayName"].toString();
|
||||
QVariantMap venue = event["venue"].toMap();
|
||||
const bool valid_latlng =
|
||||
venue["lng"].isValid() && venue["lat"].isValid();
|
||||
|
||||
if (valid_latlng && latlng_.IsValid()) {
|
||||
static const int kFilterDistanceMetres = 250 * 1e3; // 250km
|
||||
Geolocator::LatLng latlng(
|
||||
venue["lat"].toString(), venue["lng"].toString());
|
||||
if (latlng_.IsValid() && latlng.IsValid()) {
|
||||
int distance_metres = latlng_.Distance(latlng);
|
||||
if (distance_metres > kFilterDistanceMetres) {
|
||||
qLog(Debug) << "Filtered concert:"
|
||||
<< display_name
|
||||
<< "as too far away:"
|
||||
<< distance_metres;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writer.writeStartElement("div");
|
||||
{
|
||||
writer.writeStartElement("a");
|
||||
writer.writeAttribute("href", event["uri"].toString());
|
||||
writer.writeCharacters(event["displayName"].toString());
|
||||
writer.writeCharacters(display_name);
|
||||
writer.writeEndElement();
|
||||
}
|
||||
QVariantMap venue = event["venue"].toMap();
|
||||
if (venue["lng"].isValid() && venue["lat"].isValid()) {
|
||||
if (valid_latlng) {
|
||||
writer.writeStartElement("img");
|
||||
QString maps_url = QString(kStaticMapUrl).arg(
|
||||
venue["lat"].toString(),
|
||||
@ -171,3 +194,7 @@ void SongkickConcerts::InjectImage(
|
||||
reply->request().url(),
|
||||
QVariant(image));
|
||||
}
|
||||
|
||||
void SongkickConcerts::GeolocateFinished(Geolocator::LatLng latlng) {
|
||||
latlng_ = latlng;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "songinfoprovider.h"
|
||||
|
||||
#include "core/network.h"
|
||||
#include "internet/geolocator.h"
|
||||
|
||||
class QNetworkReply;
|
||||
class SongInfoTextView;
|
||||
@ -36,11 +37,13 @@ class SongkickConcerts : public SongInfoProvider {
|
||||
void ArtistSearchFinished(QNetworkReply* reply, int id);
|
||||
void CalendarRequestFinished(QNetworkReply* reply, int id);
|
||||
void InjectImage(QNetworkReply* reply, SongInfoTextView* text_view);
|
||||
void GeolocateFinished(Geolocator::LatLng latlng);
|
||||
|
||||
private:
|
||||
void FetchSongkickCalendar(const QString& artist_id, int id);
|
||||
|
||||
NetworkAccessManager network_;
|
||||
Geolocator::LatLng latlng_;
|
||||
|
||||
static const char* kSongkickArtistBucket;
|
||||
static const char* kSongkickArtistCalendarUrl;
|
||||
|
Loading…
x
Reference in New Issue
Block a user