Use one instance of NetworkAccessManager
This commit is contained in:
parent
bee6b7f946
commit
7fc5aef553
@ -268,7 +268,6 @@ set(SOURCES
|
||||
radios/radioparadiseservice.cpp
|
||||
|
||||
scrobbler/audioscrobbler.cpp
|
||||
scrobbler/scrobblerservices.cpp
|
||||
scrobbler/scrobblerservice.cpp
|
||||
scrobbler/scrobblercache.cpp
|
||||
scrobbler/scrobblercacheitem.cpp
|
||||
@ -503,7 +502,6 @@ set(HEADERS
|
||||
radios/radioparadiseservice.h
|
||||
|
||||
scrobbler/audioscrobbler.h
|
||||
scrobbler/scrobblerservices.h
|
||||
scrobbler/scrobblerservice.h
|
||||
scrobbler/scrobblercache.h
|
||||
scrobbler/scrobblingapi20.h
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "database.h"
|
||||
#include "taskmanager.h"
|
||||
#include "player.h"
|
||||
#include "networkaccessmanager.h"
|
||||
|
||||
#include "engine/devicefinders.h"
|
||||
#ifndef Q_OS_WIN
|
||||
@ -66,7 +67,13 @@
|
||||
#include "lyrics/lyricscomlyricsprovider.h"
|
||||
|
||||
#include "scrobbler/audioscrobbler.h"
|
||||
#include "scrobbler/lastfmscrobbler.h"
|
||||
#include "scrobbler/librefmscrobbler.h"
|
||||
#include "scrobbler/listenbrainzscrobbler.h"
|
||||
#include "scrobbler/lastfmimport.h"
|
||||
#ifdef HAVE_SUBSONIC
|
||||
# include "scrobbler/subsonicscrobbler.h"
|
||||
#endif
|
||||
|
||||
#include "internet/internetservices.h"
|
||||
|
||||
@ -111,6 +118,7 @@ class ApplicationImpl {
|
||||
}),
|
||||
task_manager_([app]() { return new TaskManager(app); }),
|
||||
player_([app]() { return new Player(app, app); }),
|
||||
network_([app]() { return new NetworkAccessManager(app); }),
|
||||
device_finders_([app]() { return new DeviceFinders(app); }),
|
||||
#ifndef Q_OS_WIN
|
||||
device_manager_([app]() { return new DeviceManager(app, app); }),
|
||||
@ -125,23 +133,23 @@ class ApplicationImpl {
|
||||
cover_providers_([app]() {
|
||||
CoverProviders *cover_providers = new CoverProviders(app);
|
||||
// Initialize the repository of cover providers.
|
||||
cover_providers->AddProvider(new LastFmCoverProvider(app, cover_providers->network(), app));
|
||||
cover_providers->AddProvider(new MusicbrainzCoverProvider(app, cover_providers->network(), app));
|
||||
cover_providers->AddProvider(new DiscogsCoverProvider(app, cover_providers->network(), app));
|
||||
cover_providers->AddProvider(new DeezerCoverProvider(app, cover_providers->network(), app));
|
||||
cover_providers->AddProvider(new MusixmatchCoverProvider(app, cover_providers->network(), app));
|
||||
cover_providers->AddProvider(new SpotifyCoverProvider(app, cover_providers->network(), app));
|
||||
cover_providers->AddProvider(new LastFmCoverProvider(app, app->network(), app));
|
||||
cover_providers->AddProvider(new MusicbrainzCoverProvider(app, app->network(), app));
|
||||
cover_providers->AddProvider(new DiscogsCoverProvider(app, app->network(), app));
|
||||
cover_providers->AddProvider(new DeezerCoverProvider(app, app->network(), app));
|
||||
cover_providers->AddProvider(new MusixmatchCoverProvider(app, app->network(), app));
|
||||
cover_providers->AddProvider(new SpotifyCoverProvider(app, app->network(), app));
|
||||
#ifdef HAVE_TIDAL
|
||||
cover_providers->AddProvider(new TidalCoverProvider(app, cover_providers->network(), app));
|
||||
cover_providers->AddProvider(new TidalCoverProvider(app, app->network(), app));
|
||||
#endif
|
||||
#ifdef HAVE_QOBUZ
|
||||
cover_providers->AddProvider(new QobuzCoverProvider(app, cover_providers->network(), app));
|
||||
cover_providers->AddProvider(new QobuzCoverProvider(app, app->network(), app));
|
||||
#endif
|
||||
cover_providers->ReloadSettings();
|
||||
return cover_providers;
|
||||
}),
|
||||
album_cover_loader_([app]() {
|
||||
AlbumCoverLoader *loader = new AlbumCoverLoader(app);
|
||||
AlbumCoverLoader *loader = new AlbumCoverLoader(app->network(), app);
|
||||
app->MoveToNewThread(loader);
|
||||
return loader;
|
||||
}),
|
||||
@ -149,13 +157,13 @@ class ApplicationImpl {
|
||||
lyrics_providers_([app]() {
|
||||
LyricsProviders *lyrics_providers = new LyricsProviders(app);
|
||||
// Initialize the repository of lyrics providers.
|
||||
lyrics_providers->AddProvider(new AuddLyricsProvider(lyrics_providers->network(), app));
|
||||
lyrics_providers->AddProvider(new GeniusLyricsProvider(lyrics_providers->network(), app));
|
||||
lyrics_providers->AddProvider(new OVHLyricsProvider(lyrics_providers->network(), app));
|
||||
lyrics_providers->AddProvider(new LoloLyricsProvider(lyrics_providers->network(), app));
|
||||
lyrics_providers->AddProvider(new MusixmatchLyricsProvider(lyrics_providers->network(), app));
|
||||
lyrics_providers->AddProvider(new ChartLyricsProvider(lyrics_providers->network(), app));
|
||||
lyrics_providers->AddProvider(new LyricsComLyricsProvider(lyrics_providers->network(), app));
|
||||
lyrics_providers->AddProvider(new AuddLyricsProvider(app->network(), app));
|
||||
lyrics_providers->AddProvider(new GeniusLyricsProvider(app->network(), app));
|
||||
lyrics_providers->AddProvider(new OVHLyricsProvider(app->network(), app));
|
||||
lyrics_providers->AddProvider(new LoloLyricsProvider(app->network(), app));
|
||||
lyrics_providers->AddProvider(new MusixmatchLyricsProvider(app->network(), app));
|
||||
lyrics_providers->AddProvider(new ChartLyricsProvider(app->network(), app));
|
||||
lyrics_providers->AddProvider(new LyricsComLyricsProvider(app->network(), app));
|
||||
lyrics_providers->ReloadSettings();
|
||||
return lyrics_providers;
|
||||
}),
|
||||
@ -173,18 +181,25 @@ class ApplicationImpl {
|
||||
return internet_services;
|
||||
}),
|
||||
radio_services_([app]() { return new RadioServices(app, app); }),
|
||||
scrobbler_([app]() { return new AudioScrobbler(app, app); }),
|
||||
scrobbler_([app]() {
|
||||
AudioScrobbler *scrobbler = new AudioScrobbler(app);
|
||||
scrobbler->AddService(new LastFMScrobbler(scrobbler, app->network(), app));
|
||||
scrobbler->AddService(new LibreFMScrobbler(scrobbler, app->network(), app));
|
||||
scrobbler->AddService(new ListenBrainzScrobbler(scrobbler, app->network(), app));
|
||||
return scrobbler;
|
||||
}),
|
||||
#ifdef HAVE_MOODBAR
|
||||
moodbar_loader_([app]() { return new MoodbarLoader(app, app); }),
|
||||
moodbar_controller_([app]() { return new MoodbarController(app, app); }),
|
||||
#endif
|
||||
lastfm_import_([app]() { return new LastFMImport(app); })
|
||||
lastfm_import_([app]() { return new LastFMImport(app->network(), app); })
|
||||
{}
|
||||
|
||||
Lazy<TagReaderClient> tag_reader_client_;
|
||||
Lazy<Database> database_;
|
||||
Lazy<TaskManager> task_manager_;
|
||||
Lazy<Player> player_;
|
||||
Lazy<NetworkAccessManager> network_;
|
||||
Lazy<DeviceFinders> device_finders_;
|
||||
#ifndef Q_OS_WIN
|
||||
Lazy<DeviceManager> device_manager_;
|
||||
@ -317,6 +332,7 @@ TagReaderClient *Application::tag_reader_client() const { return p_->tag_reader_
|
||||
Database *Application::database() const { return p_->database_.get(); }
|
||||
TaskManager *Application::task_manager() const { return p_->task_manager_.get(); }
|
||||
Player *Application::player() const { return p_->player_.get(); }
|
||||
NetworkAccessManager *Application::network() const { return p_->network_.get(); }
|
||||
DeviceFinders *Application::device_finders() const { return p_->device_finders_.get(); }
|
||||
#ifndef Q_OS_WIN
|
||||
DeviceManager *Application::device_manager() const { return p_->device_manager_.get(); }
|
||||
|
@ -41,6 +41,7 @@ class TagReaderClient;
|
||||
class Database;
|
||||
class DeviceFinders;
|
||||
class Player;
|
||||
class NetworkAccessManager;
|
||||
class SCollection;
|
||||
class CollectionBackend;
|
||||
class CollectionModel;
|
||||
@ -74,6 +75,7 @@ class Application : public QObject {
|
||||
Database *database() const;
|
||||
TaskManager *task_manager() const;
|
||||
Player *player() const;
|
||||
NetworkAccessManager *network() const;
|
||||
DeviceFinders *device_finders() const;
|
||||
#ifndef Q_OS_WIN
|
||||
DeviceManager *device_manager() const;
|
||||
|
@ -1024,7 +1024,7 @@ MainWindow::MainWindow(Application *app, std::shared_ptr<SystemTrayIcon> tray_ic
|
||||
if (!sparkle_url.isEmpty()) {
|
||||
qLog(Debug) << "Creating Qt Sparkle updater";
|
||||
qtsparkle::Updater *updater = new qtsparkle::Updater(sparkle_url, this);
|
||||
updater->SetNetworkAccessManager(new NetworkAccessManager(this));
|
||||
updater->SetNetworkAccessManager(app->network());
|
||||
updater->SetVersion(STRAWBERRY_VERSION_PACKAGE);
|
||||
QObject::connect(check_updates, &QAction::triggered, updater, &qtsparkle::Updater::CheckNow);
|
||||
}
|
||||
@ -2933,7 +2933,7 @@ void MainWindow::AutoCompleteTags() {
|
||||
|
||||
// Create the tag fetching stuff if it hasn't been already
|
||||
if (!tag_fetcher_) {
|
||||
tag_fetcher_ = std::make_unique<TagFetcher>();
|
||||
tag_fetcher_ = std::make_unique<TagFetcher>(app_->network());
|
||||
track_selection_dialog_ = std::make_unique<TrackSelectionDialog>();
|
||||
track_selection_dialog_->set_save_on_close(true);
|
||||
|
||||
|
@ -46,6 +46,7 @@
|
||||
|
||||
#include "signalchecker.h"
|
||||
#include "player.h"
|
||||
#include "networkaccessmanager.h"
|
||||
#include "song.h"
|
||||
#include "songloader.h"
|
||||
#include "tagreaderclient.h"
|
||||
@ -66,9 +67,10 @@
|
||||
QSet<QString> SongLoader::sRawUriSchemes;
|
||||
const int SongLoader::kDefaultTimeout = 5000;
|
||||
|
||||
SongLoader::SongLoader(CollectionBackendInterface *collection, const Player *player, QObject *parent)
|
||||
SongLoader::SongLoader(CollectionBackendInterface *collection, const Player *player, NetworkAccessManager *network, QObject *parent)
|
||||
: QObject(parent),
|
||||
player_(player),
|
||||
network_(network),
|
||||
collection_(collection),
|
||||
timeout_timer_(new QTimer(this)),
|
||||
playlist_parser_(new PlaylistParser(collection, this)),
|
||||
@ -191,7 +193,7 @@ SongLoader::Result SongLoader::LoadAudioCD() {
|
||||
|
||||
#if defined(HAVE_AUDIOCD) && defined(HAVE_GSTREAMER)
|
||||
if (player_->engine()->type() == Engine::EngineType::GStreamer) {
|
||||
CddaSongLoader *cdda_song_loader = new CddaSongLoader(QUrl(), this);
|
||||
CddaSongLoader *cdda_song_loader = new CddaSongLoader(QUrl(), network_, this);
|
||||
QObject::connect(cdda_song_loader, &CddaSongLoader::SongsDurationLoaded, this, &SongLoader::AudioCDTracksLoadFinishedSlot);
|
||||
QObject::connect(cdda_song_loader, &CddaSongLoader::SongsMetadataLoaded, this, &SongLoader::AudioCDTracksTagsLoaded);
|
||||
cdda_song_loader->LoadSongs();
|
||||
|
@ -45,6 +45,7 @@
|
||||
|
||||
class QTimer;
|
||||
class Player;
|
||||
class NetworkAccessManager;
|
||||
class CollectionBackendInterface;
|
||||
class PlaylistParser;
|
||||
class ParserBase;
|
||||
@ -58,7 +59,7 @@ class SongLoader : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SongLoader(CollectionBackendInterface *collection, const Player *player, QObject *parent = nullptr);
|
||||
explicit SongLoader(CollectionBackendInterface *collection, const Player *player, NetworkAccessManager *network, QObject *parent = nullptr);
|
||||
~SongLoader() override;
|
||||
|
||||
enum class Result {
|
||||
@ -144,6 +145,7 @@ class SongLoader : public QObject {
|
||||
SongList songs_;
|
||||
|
||||
const Player *player_;
|
||||
NetworkAccessManager *network_;
|
||||
CollectionBackendInterface *collection_;
|
||||
QTimer *timeout_timer_;
|
||||
PlaylistParser *playlist_parser_;
|
||||
|
@ -132,7 +132,7 @@ void AlbumCoverChoiceController::Init(Application *app) {
|
||||
|
||||
app_ = app;
|
||||
|
||||
cover_fetcher_ = new AlbumCoverFetcher(app_->cover_providers(), this);
|
||||
cover_fetcher_ = new AlbumCoverFetcher(app_->cover_providers(), app->network(), this);
|
||||
cover_searcher_ = new AlbumCoverSearcher(QIcon(":/pictures/cdcase.png"), app, this);
|
||||
cover_searcher_->Init(cover_fetcher_);
|
||||
|
||||
@ -322,7 +322,7 @@ QUrl AlbumCoverChoiceController::LoadCoverFromURL(Song *song) {
|
||||
|
||||
AlbumCoverImageResultPtr AlbumCoverChoiceController::LoadImageFromURL() {
|
||||
|
||||
if (!cover_from_url_dialog_) { cover_from_url_dialog_ = new CoverFromURLDialog(this); }
|
||||
if (!cover_from_url_dialog_) { cover_from_url_dialog_ = new CoverFromURLDialog(app_->network(), this); }
|
||||
|
||||
return cover_from_url_dialog_->Exec();
|
||||
|
||||
|
@ -37,10 +37,10 @@ using namespace std::chrono_literals;
|
||||
|
||||
const int AlbumCoverFetcher::kMaxConcurrentRequests = 5;
|
||||
|
||||
AlbumCoverFetcher::AlbumCoverFetcher(CoverProviders *cover_providers, QObject *parent, NetworkAccessManager *network)
|
||||
AlbumCoverFetcher::AlbumCoverFetcher(CoverProviders *cover_providers, NetworkAccessManager *network, QObject *parent)
|
||||
: QObject(parent),
|
||||
cover_providers_(cover_providers),
|
||||
network_(network ? network : new NetworkAccessManager(this)),
|
||||
network_(network),
|
||||
next_id_(0),
|
||||
request_starter_(new QTimer(this)) {
|
||||
|
||||
|
@ -107,7 +107,7 @@ class AlbumCoverFetcher : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AlbumCoverFetcher(CoverProviders *cover_providers, QObject *parent = nullptr, NetworkAccessManager *network = nullptr);
|
||||
explicit AlbumCoverFetcher(CoverProviders *cover_providers, NetworkAccessManager *network, QObject *parent = nullptr);
|
||||
~AlbumCoverFetcher() override;
|
||||
|
||||
static const int kMaxConcurrentRequests;
|
||||
|
@ -53,12 +53,12 @@
|
||||
#include "albumcoverloaderresult.h"
|
||||
#include "albumcoverimageresult.h"
|
||||
|
||||
AlbumCoverLoader::AlbumCoverLoader(QObject *parent)
|
||||
AlbumCoverLoader::AlbumCoverLoader(NetworkAccessManager *network, QObject *parent)
|
||||
: QObject(parent),
|
||||
network_(network),
|
||||
stop_requested_(false),
|
||||
load_image_async_id_(1),
|
||||
save_image_async_id_(1),
|
||||
network_(new NetworkAccessManager(this)),
|
||||
original_thread_(nullptr) {
|
||||
|
||||
original_thread_ = thread();
|
||||
|
@ -51,7 +51,7 @@ class AlbumCoverLoader : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AlbumCoverLoader(QObject *parent = nullptr);
|
||||
explicit AlbumCoverLoader(NetworkAccessManager *network, QObject *parent = nullptr);
|
||||
|
||||
enum class State {
|
||||
None,
|
||||
@ -135,6 +135,8 @@ class AlbumCoverLoader : public QObject {
|
||||
void NextState(TaskPtr task);
|
||||
TryLoadResult TryLoadImage(TaskPtr task);
|
||||
|
||||
NetworkAccessManager *network_;
|
||||
|
||||
bool stop_requested_;
|
||||
|
||||
QMutex mutex_load_image_async_;
|
||||
@ -144,8 +146,6 @@ class AlbumCoverLoader : public QObject {
|
||||
quint64 load_image_async_id_;
|
||||
quint64 save_image_async_id_;
|
||||
|
||||
NetworkAccessManager *network_;
|
||||
|
||||
static const int kMaxRedirects = 3;
|
||||
|
||||
QThread *original_thread_;
|
||||
|
@ -106,7 +106,7 @@ AlbumCoverManager::AlbumCoverManager(Application *app, CollectionBackend *collec
|
||||
filter_all_(nullptr),
|
||||
filter_with_covers_(nullptr),
|
||||
filter_without_covers_(nullptr),
|
||||
cover_fetcher_(new AlbumCoverFetcher(app_->cover_providers(), this)),
|
||||
cover_fetcher_(new AlbumCoverFetcher(app_->cover_providers(), app_->network(), this)),
|
||||
cover_searcher_(nullptr),
|
||||
cover_export_(nullptr),
|
||||
cover_exporter_(new AlbumCoverExporter(this)),
|
||||
|
@ -40,7 +40,10 @@
|
||||
#include "coverfromurldialog.h"
|
||||
#include "ui_coverfromurldialog.h"
|
||||
|
||||
CoverFromURLDialog::CoverFromURLDialog(QWidget *parent) : QDialog(parent), ui_(new Ui_CoverFromURLDialog), network_(new NetworkAccessManager(this)) {
|
||||
CoverFromURLDialog::CoverFromURLDialog(NetworkAccessManager *network, QWidget *parent)
|
||||
: QDialog(parent),
|
||||
network_(network),
|
||||
ui_(new Ui_CoverFromURLDialog) {
|
||||
|
||||
ui_->setupUi(this);
|
||||
ui_->busy->hide();
|
||||
|
@ -40,7 +40,7 @@ class CoverFromURLDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CoverFromURLDialog(QWidget *parent = nullptr);
|
||||
explicit CoverFromURLDialog(NetworkAccessManager *network, QWidget *parent = nullptr);
|
||||
~CoverFromURLDialog() override;
|
||||
|
||||
// Opens the dialog. This returns an image found at the URL chosen by user or null image if the dialog got rejected.
|
||||
@ -51,9 +51,8 @@ class CoverFromURLDialog : public QDialog {
|
||||
void LoadCoverFromURLFinished();
|
||||
|
||||
private:
|
||||
Ui_CoverFromURLDialog *ui_;
|
||||
|
||||
NetworkAccessManager *network_;
|
||||
Ui_CoverFromURLDialog *ui_;
|
||||
AlbumCoverImageResultPtr last_album_cover_;
|
||||
};
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include <QSettings>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "core/networkaccessmanager.h"
|
||||
#include "coverprovider.h"
|
||||
#include "coverproviders.h"
|
||||
|
||||
@ -38,7 +37,7 @@
|
||||
|
||||
int CoverProviders::NextOrderId = 0;
|
||||
|
||||
CoverProviders::CoverProviders(QObject *parent) : QObject(parent), network_(new NetworkAccessManager(this)) {}
|
||||
CoverProviders::CoverProviders(QObject *parent) : QObject(parent) {}
|
||||
|
||||
CoverProviders::~CoverProviders() {
|
||||
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include <QString>
|
||||
#include <QAtomicInt>
|
||||
|
||||
class NetworkAccessManager;
|
||||
class CoverProvider;
|
||||
|
||||
// This is a repository for cover providers.
|
||||
@ -60,8 +59,6 @@ class CoverProviders : public QObject {
|
||||
|
||||
int NextId();
|
||||
|
||||
NetworkAccessManager *network() const { return network_; }
|
||||
|
||||
private slots:
|
||||
void ProviderDestroyed();
|
||||
|
||||
@ -70,8 +67,6 @@ class CoverProviders : public QObject {
|
||||
|
||||
static int NextOrderId;
|
||||
|
||||
NetworkAccessManager *network_;
|
||||
|
||||
QMap<CoverProvider*, QString> cover_providers_;
|
||||
QMutex mutex_;
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
#include "core/application.h"
|
||||
#include "core/networkaccessmanager.h"
|
||||
#include "collection/collectionmodel.h"
|
||||
#include "cddasongloader.h"
|
||||
#include "connecteddevice.h"
|
||||
@ -35,7 +37,7 @@ class DeviceManager;
|
||||
|
||||
CddaDevice::CddaDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, DeviceManager *manager, Application *app, int database_id, bool first_time, QObject *parent)
|
||||
: ConnectedDevice(url, lister, unique_id, manager, app, database_id, first_time, parent),
|
||||
cdda_song_loader_(url) {
|
||||
cdda_song_loader_(url, app->network()) {
|
||||
|
||||
QObject::connect(&cdda_song_loader_, &CddaSongLoader::SongsLoaded, this, &CddaDevice::SongsLoaded);
|
||||
QObject::connect(&cdda_song_loader_, &CddaSongLoader::SongsDurationLoaded, this, &CddaDevice::SongsLoaded);
|
||||
|
@ -39,11 +39,13 @@
|
||||
|
||||
#include "cddasongloader.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/networkaccessmanager.h"
|
||||
#include "utilities/timeconstants.h"
|
||||
|
||||
CddaSongLoader::CddaSongLoader(const QUrl &url, QObject *parent)
|
||||
CddaSongLoader::CddaSongLoader(const QUrl &url, NetworkAccessManager *network, QObject *parent)
|
||||
: QObject(parent),
|
||||
url_(url),
|
||||
network_(network),
|
||||
cdda_(nullptr),
|
||||
cdio_(nullptr) {}
|
||||
|
||||
@ -195,7 +197,7 @@ void CddaSongLoader::LoadSongs() {
|
||||
QString musicbrainz_discid(string_mb);
|
||||
qLog(Info) << "MusicBrainz discid: " << musicbrainz_discid;
|
||||
|
||||
MusicBrainzClient *musicbrainz_client = new MusicBrainzClient;
|
||||
MusicBrainzClient *musicbrainz_client = new MusicBrainzClient(network_);
|
||||
QObject::connect(musicbrainz_client, &MusicBrainzClient::DiscIdFinished, this, &CddaSongLoader::AudioCDTagsLoaded);
|
||||
musicbrainz_client->StartDiscIdRequest(musicbrainz_discid);
|
||||
g_free(string_mb);
|
||||
|
@ -40,12 +40,14 @@
|
||||
# include "musicbrainz/musicbrainzclient.h"
|
||||
#endif
|
||||
|
||||
class NetworkAccessManager;
|
||||
|
||||
// This class provides a (hopefully) nice, high level interface to get CD information and load tracks
|
||||
class CddaSongLoader : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CddaSongLoader(const QUrl &url = QUrl(), QObject *parent = nullptr);
|
||||
explicit CddaSongLoader(const QUrl &url, NetworkAccessManager *network, QObject *parent = nullptr);
|
||||
~CddaSongLoader() override;
|
||||
|
||||
// Load songs. Signals declared below will be emitted anytime new information will be available.
|
||||
@ -68,7 +70,8 @@ class CddaSongLoader : public QObject {
|
||||
#endif
|
||||
|
||||
private:
|
||||
QUrl url_;
|
||||
const QUrl url_;
|
||||
NetworkAccessManager *network_;
|
||||
GstElement *cdda_;
|
||||
CdIo_t *cdio_;
|
||||
QMutex mutex_load_;
|
||||
|
@ -109,7 +109,7 @@ EditTagDialog::EditTagDialog(Application *app, QWidget *parent)
|
||||
app_(app),
|
||||
album_cover_choice_controller_(new AlbumCoverChoiceController(this)),
|
||||
#ifdef HAVE_MUSICBRAINZ
|
||||
tag_fetcher_(new TagFetcher(this)),
|
||||
tag_fetcher_(new TagFetcher(app->network(), this)),
|
||||
results_dialog_(new TrackSelectionDialog(this)),
|
||||
#endif
|
||||
image_no_cover_thumbnail_(ImageUtils::GenerateNoCoverImage(QSize(128, 128))),
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include <QSettings>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "core/networkaccessmanager.h"
|
||||
|
||||
#include "lyricsprovider.h"
|
||||
#include "lyricsproviders.h"
|
||||
@ -37,7 +36,7 @@
|
||||
|
||||
int LyricsProviders::NextOrderId = 0;
|
||||
|
||||
LyricsProviders::LyricsProviders(QObject *parent) : QObject(parent), network_(new NetworkAccessManager(this)) {}
|
||||
LyricsProviders::LyricsProviders(QObject *parent) : QObject(parent) {}
|
||||
|
||||
LyricsProviders::~LyricsProviders() {
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include <QString>
|
||||
#include <QAtomicInt>
|
||||
|
||||
class NetworkAccessManager;
|
||||
class LyricsProvider;
|
||||
|
||||
class LyricsProviders : public QObject {
|
||||
@ -49,8 +48,6 @@ class LyricsProviders : public QObject {
|
||||
bool HasAnyProviders() const { return !lyrics_providers_.isEmpty(); }
|
||||
int NextId();
|
||||
|
||||
NetworkAccessManager *network() const { return network_; }
|
||||
|
||||
private slots:
|
||||
void ProviderDestroyed();
|
||||
|
||||
@ -59,8 +56,6 @@ class LyricsProviders : public QObject {
|
||||
|
||||
static int NextOrderId;
|
||||
|
||||
NetworkAccessManager *network_;
|
||||
|
||||
QMap<LyricsProvider*, QString> lyrics_providers_;
|
||||
QList<LyricsProvider*> ordered_providers_;
|
||||
QMutex mutex_;
|
||||
|
@ -50,9 +50,9 @@ const char *AcoustidClient::kClientId = "0qjUoxbowg";
|
||||
const char *AcoustidClient::kUrl = "https://api.acoustid.org/v2/lookup";
|
||||
const int AcoustidClient::kDefaultTimeout = 5000; // msec
|
||||
|
||||
AcoustidClient::AcoustidClient(QObject *parent)
|
||||
AcoustidClient::AcoustidClient(NetworkAccessManager *network, QObject *parent)
|
||||
: QObject(parent),
|
||||
network_(new NetworkAccessManager(this)),
|
||||
network_(network),
|
||||
timeouts_(new NetworkTimeouts(kDefaultTimeout, this)) {}
|
||||
|
||||
AcoustidClient::~AcoustidClient() {
|
||||
|
@ -43,7 +43,7 @@ class AcoustidClient : public QObject {
|
||||
// IDs are provided by the caller when a request is started and included in the Finished signal - they have no meaning to AcoustidClient.
|
||||
|
||||
public:
|
||||
explicit AcoustidClient(QObject *parent = nullptr);
|
||||
explicit AcoustidClient(NetworkAccessManager *network, QObject *parent = nullptr);
|
||||
~AcoustidClient() override;
|
||||
|
||||
// Network requests will be aborted after this interval.
|
||||
|
@ -55,9 +55,9 @@ const int MusicBrainzClient::kRequestsDelay = 1200;
|
||||
const int MusicBrainzClient::kDefaultTimeout = 8000;
|
||||
const int MusicBrainzClient::kMaxRequestPerTrack = 3;
|
||||
|
||||
MusicBrainzClient::MusicBrainzClient(QObject *parent, QNetworkAccessManager *network)
|
||||
MusicBrainzClient::MusicBrainzClient(QNetworkAccessManager *network, QObject *parent)
|
||||
: QObject(parent),
|
||||
network_(network ? network : new NetworkAccessManager(this)),
|
||||
network_(network),
|
||||
timeouts_(new NetworkTimeouts(kDefaultTimeout, this)),
|
||||
timer_flush_requests_(new QTimer(this)) {
|
||||
|
||||
|
@ -50,7 +50,7 @@ class MusicBrainzClient : public QObject {
|
||||
public:
|
||||
// The second argument allows for specifying a custom network access manager.
|
||||
// It is used in tests. The ownership of network is not transferred.
|
||||
explicit MusicBrainzClient(QObject *parent = nullptr, QNetworkAccessManager *network = nullptr);
|
||||
explicit MusicBrainzClient(QNetworkAccessManager *network, QObject *parent = nullptr);
|
||||
~MusicBrainzClient() override;
|
||||
|
||||
struct Result {
|
||||
|
@ -29,17 +29,18 @@
|
||||
#include <QFutureWatcher>
|
||||
#include <QString>
|
||||
|
||||
#include "core/networkaccessmanager.h"
|
||||
#include "utilities/timeconstants.h"
|
||||
#include "engine/chromaprinter.h"
|
||||
#include "acoustidclient.h"
|
||||
#include "musicbrainzclient.h"
|
||||
#include "tagfetcher.h"
|
||||
|
||||
TagFetcher::TagFetcher(QObject *parent)
|
||||
TagFetcher::TagFetcher(NetworkAccessManager *network, QObject *parent)
|
||||
: QObject(parent),
|
||||
fingerprint_watcher_(nullptr),
|
||||
acoustid_client_(new AcoustidClient(this)),
|
||||
musicbrainz_client_(new MusicBrainzClient(this)) {
|
||||
acoustid_client_(new AcoustidClient(network, this)),
|
||||
musicbrainz_client_(new MusicBrainzClient(network, this)) {
|
||||
|
||||
QObject::connect(acoustid_client_, &AcoustidClient::Finished, this, &TagFetcher::PuidsFound);
|
||||
QObject::connect(musicbrainz_client_, &MusicBrainzClient::Finished, this, &TagFetcher::TagsFetched);
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "core/song.h"
|
||||
#include "musicbrainzclient.h"
|
||||
|
||||
class NetworkAccessManager;
|
||||
class AcoustidClient;
|
||||
|
||||
class TagFetcher : public QObject {
|
||||
@ -40,7 +41,7 @@ class TagFetcher : public QObject {
|
||||
// High level interface to Fingerprinter, AcoustidClient and MusicBrainzClient.
|
||||
|
||||
public:
|
||||
explicit TagFetcher(QObject *parent = nullptr);
|
||||
explicit TagFetcher(NetworkAccessManager *network, QObject *parent = nullptr);
|
||||
|
||||
void StartFetch(const SongList &songs);
|
||||
|
||||
|
@ -845,7 +845,7 @@ bool Playlist::dropMimeData(const QMimeData *data, Qt::DropAction action, int ro
|
||||
}
|
||||
}
|
||||
else if (data->hasFormat(kCddaMimeType)) {
|
||||
SongLoaderInserter *inserter = new SongLoaderInserter(task_manager_, collection_, backend_->app()->player());
|
||||
SongLoaderInserter *inserter = new SongLoaderInserter(task_manager_, collection_, backend_->app()->player(), backend_->app()->network());
|
||||
QObject::connect(inserter, &SongLoaderInserter::Error, this, &Playlist::Error);
|
||||
inserter->LoadAudioCD(this, row, play_now, enqueue_now, enqueue_next_now);
|
||||
}
|
||||
@ -860,7 +860,7 @@ bool Playlist::dropMimeData(const QMimeData *data, Qt::DropAction action, int ro
|
||||
|
||||
void Playlist::InsertUrls(const QList<QUrl> &urls, const int pos, const bool play_now, const bool enqueue, const bool enqueue_next) {
|
||||
|
||||
SongLoaderInserter *inserter = new SongLoaderInserter(task_manager_, collection_, backend_->app()->player());
|
||||
SongLoaderInserter *inserter = new SongLoaderInserter(task_manager_, collection_, backend_->app()->player(), backend_->app()->network());
|
||||
QObject::connect(inserter, &SongLoaderInserter::Error, this, &Playlist::Error);
|
||||
|
||||
inserter->Load(this, pos, play_now, enqueue, enqueue_next, urls);
|
||||
|
@ -29,10 +29,11 @@
|
||||
#include "core/logging.h"
|
||||
#include "core/songloader.h"
|
||||
#include "core/taskmanager.h"
|
||||
#include "core/networkaccessmanager.h"
|
||||
#include "playlist.h"
|
||||
#include "songloaderinserter.h"
|
||||
|
||||
SongLoaderInserter::SongLoaderInserter(TaskManager *task_manager, CollectionBackendInterface *collection, const Player *player, QObject *parent)
|
||||
SongLoaderInserter::SongLoaderInserter(TaskManager *task_manager, CollectionBackendInterface *collection, const Player *player, NetworkAccessManager *network, QObject *parent)
|
||||
: QObject(parent),
|
||||
task_manager_(task_manager),
|
||||
destination_(nullptr),
|
||||
@ -41,7 +42,8 @@ SongLoaderInserter::SongLoaderInserter(TaskManager *task_manager, CollectionBack
|
||||
enqueue_(false),
|
||||
enqueue_next_(false),
|
||||
collection_(collection),
|
||||
player_(player) {}
|
||||
player_(player),
|
||||
network_(network) {}
|
||||
|
||||
SongLoaderInserter::~SongLoaderInserter() { qDeleteAll(pending_); }
|
||||
|
||||
@ -58,7 +60,7 @@ void SongLoaderInserter::Load(Playlist *destination, int row, bool play_now, boo
|
||||
QObject::connect(this, &SongLoaderInserter::EffectiveLoadFinished, destination, &Playlist::UpdateItems);
|
||||
|
||||
for (const QUrl &url : urls) {
|
||||
SongLoader *loader = new SongLoader(collection_, player_, this);
|
||||
SongLoader *loader = new SongLoader(collection_, player_, network_, this);
|
||||
|
||||
SongLoader::Result ret = loader->Load(url);
|
||||
|
||||
@ -103,7 +105,7 @@ void SongLoaderInserter::LoadAudioCD(Playlist *destination, int row, bool play_n
|
||||
enqueue_ = enqueue;
|
||||
enqueue_next_ = enqueue_next;
|
||||
|
||||
SongLoader *loader = new SongLoader(collection_, player_, this);
|
||||
SongLoader *loader = new SongLoader(collection_, player_, network_, this);
|
||||
QObject::connect(loader, &SongLoader::AudioCDTracksLoadFinished, this, [this, loader]() { AudioCDTracksLoadFinished(loader); });
|
||||
QObject::connect(loader, &SongLoader::LoadAudioCDFinished, this, &SongLoaderInserter::AudioCDTagsLoaded);
|
||||
qLog(Info) << "Loading audio CD...";
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "core/song.h"
|
||||
|
||||
class Player;
|
||||
class NetworkAccessManager;
|
||||
class SongLoader;
|
||||
class TaskManager;
|
||||
class CollectionBackendInterface;
|
||||
@ -41,7 +42,7 @@ class SongLoaderInserter : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SongLoaderInserter(TaskManager *task_manager, CollectionBackendInterface *collection, const Player *player, QObject *parent = nullptr);
|
||||
explicit SongLoaderInserter(TaskManager *task_manager, CollectionBackendInterface *collection, const Player *player, NetworkAccessManager *network, QObject *parent = nullptr);
|
||||
~SongLoaderInserter() override;
|
||||
|
||||
void Load(Playlist *destination, int row, bool play_now, bool enqueue, bool enqueue_next, const QList<QUrl> &urls);
|
||||
@ -75,6 +76,7 @@ class SongLoaderInserter : public QObject {
|
||||
QList<SongLoader*> pending_;
|
||||
CollectionBackendInterface *collection_;
|
||||
const Player *player_;
|
||||
NetworkAccessManager *network_;
|
||||
|
||||
};
|
||||
|
||||
|
@ -76,7 +76,7 @@ constexpr char QobuzService::kSongsFtsTable[] = "qobuz_songs_fts";
|
||||
QobuzService::QobuzService(Application *app, QObject *parent)
|
||||
: InternetService(Song::Source::Qobuz, "Qobuz", "qobuz", QobuzSettingsPage::kSettingsGroup, SettingsDialog::Page::Qobuz, app, parent),
|
||||
app_(app),
|
||||
network_(new NetworkAccessManager(this)),
|
||||
network_(app->network()),
|
||||
url_handler_(new QobuzUrlHandler(app, this)),
|
||||
artists_collection_backend_(nullptr),
|
||||
albums_collection_backend_(nullptr),
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
RadioServices::RadioServices(Application *app, QObject *parent)
|
||||
: QObject(parent),
|
||||
network_(new NetworkAccessManager(this)),
|
||||
network_(app->network()),
|
||||
backend_(nullptr),
|
||||
model_(new RadioModel(app, this)),
|
||||
sort_model_(new QSortFilterProxyModel(this)),
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QMutex>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QSettings>
|
||||
|
||||
@ -29,7 +31,6 @@
|
||||
#include "settings/scrobblersettingspage.h"
|
||||
|
||||
#include "audioscrobbler.h"
|
||||
#include "scrobblerservices.h"
|
||||
#include "scrobblerservice.h"
|
||||
#include "lastfmscrobbler.h"
|
||||
#include "librefmscrobbler.h"
|
||||
@ -41,7 +42,6 @@
|
||||
AudioScrobbler::AudioScrobbler(Application *app, QObject *parent)
|
||||
: QObject(parent),
|
||||
app_(app),
|
||||
scrobbler_services_(new ScrobblerServices(this)),
|
||||
enabled_(false),
|
||||
offline_(false),
|
||||
scrobble_button_(false),
|
||||
@ -50,21 +50,69 @@ AudioScrobbler::AudioScrobbler(Application *app, QObject *parent)
|
||||
prefer_albumartist_(false),
|
||||
show_error_dialog_(false) {
|
||||
|
||||
scrobbler_services_->AddService(new LastFMScrobbler(app_, scrobbler_services_));
|
||||
scrobbler_services_->AddService(new LibreFMScrobbler(app_, scrobbler_services_));
|
||||
scrobbler_services_->AddService(new ListenBrainzScrobbler(app_, scrobbler_services_));
|
||||
#ifdef HAVE_SUBSONIC
|
||||
scrobbler_services_->AddService(new SubsonicScrobbler(app_, scrobbler_services_));
|
||||
#endif
|
||||
|
||||
ReloadSettings();
|
||||
|
||||
for (ScrobblerService *service : scrobbler_services_->List()) {
|
||||
QObject::connect(service, &ScrobblerService::ErrorMessage, this, &AudioScrobbler::ErrorReceived);
|
||||
}
|
||||
|
||||
AudioScrobbler::~AudioScrobbler() {
|
||||
|
||||
while (!services_.isEmpty()) {
|
||||
delete services_.take(services_.firstKey());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AudioScrobbler::AddService(ScrobblerService *service) {
|
||||
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
services_.insert(service->name(), service);
|
||||
}
|
||||
|
||||
QObject::connect(service, &ScrobblerService::ErrorMessage, this, &AudioScrobbler::ErrorReceived);
|
||||
|
||||
qLog(Debug) << "Registered scrobbler service" << service->name();
|
||||
|
||||
}
|
||||
|
||||
void AudioScrobbler::RemoveService(ScrobblerService *service) {
|
||||
|
||||
if (!service || !services_.contains(service->name())) return;
|
||||
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
services_.remove(service->name());
|
||||
QObject::disconnect(service, nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
QObject::disconnect(service, &ScrobblerService::ErrorMessage, this, &AudioScrobbler::ErrorReceived);
|
||||
|
||||
qLog(Debug) << "Unregistered scrobbler service" << service->name();
|
||||
|
||||
}
|
||||
|
||||
int AudioScrobbler::NextId() { return next_id_.fetchAndAddRelaxed(1); }
|
||||
|
||||
QList<ScrobblerService*> AudioScrobbler::GetAll() {
|
||||
|
||||
QList<ScrobblerService*> services;
|
||||
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
services = services_.values();
|
||||
}
|
||||
|
||||
return services;
|
||||
|
||||
}
|
||||
|
||||
ScrobblerService *AudioScrobbler::ServiceByName(const QString &name) {
|
||||
|
||||
if (services_.contains(name)) return services_.value(name);
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
||||
void AudioScrobbler::ReloadSettings() {
|
||||
|
||||
QSettings s;
|
||||
@ -104,7 +152,8 @@ void AudioScrobbler::ReloadSettings() {
|
||||
emit ScrobbleButtonVisibilityChanged(scrobble_button_);
|
||||
emit LoveButtonVisibilityChanged(love_button_);
|
||||
|
||||
for (ScrobblerService *service : scrobbler_services_->List()) {
|
||||
QList<ScrobblerService*> services = services_.values();
|
||||
for (ScrobblerService *service : services) {
|
||||
service->ReloadSettings();
|
||||
}
|
||||
|
||||
@ -150,7 +199,8 @@ void AudioScrobbler::UpdateNowPlaying(const Song &song) {
|
||||
|
||||
qLog(Debug) << "Sending now playing for song" << song.artist() << song.album() << song.title();
|
||||
|
||||
for (ScrobblerService *service : scrobbler_services_->List()) {
|
||||
QList<ScrobblerService*> services = GetAll();
|
||||
for (ScrobblerService *service : services) {
|
||||
if (!service->IsEnabled()) continue;
|
||||
service->UpdateNowPlaying(song);
|
||||
}
|
||||
@ -159,7 +209,8 @@ void AudioScrobbler::UpdateNowPlaying(const Song &song) {
|
||||
|
||||
void AudioScrobbler::ClearPlaying() {
|
||||
|
||||
for (ScrobblerService *service : scrobbler_services_->List()) {
|
||||
QList<ScrobblerService*> services = GetAll();
|
||||
for (ScrobblerService *service : services) {
|
||||
if (!service->IsEnabled()) continue;
|
||||
service->ClearPlaying();
|
||||
}
|
||||
@ -172,7 +223,8 @@ void AudioScrobbler::Scrobble(const Song &song, const qint64 scrobble_point) {
|
||||
|
||||
qLog(Debug) << "Scrobbling song" << song.artist() << song.album() << song.title() << "at" << scrobble_point;
|
||||
|
||||
for (ScrobblerService *service : scrobbler_services_->List()) {
|
||||
QList<ScrobblerService*> services = GetAll();
|
||||
for (ScrobblerService *service : services) {
|
||||
if (!service->IsEnabled()) continue;
|
||||
service->Scrobble(song);
|
||||
}
|
||||
@ -181,7 +233,8 @@ void AudioScrobbler::Scrobble(const Song &song, const qint64 scrobble_point) {
|
||||
|
||||
void AudioScrobbler::Love() {
|
||||
|
||||
for (ScrobblerService *service : scrobbler_services_->List()) {
|
||||
QList<ScrobblerService*> services = GetAll();
|
||||
for (ScrobblerService *service : services) {
|
||||
if (!service->IsEnabled() || !service->IsAuthenticated()) continue;
|
||||
service->Love();
|
||||
}
|
||||
@ -190,7 +243,8 @@ void AudioScrobbler::Love() {
|
||||
|
||||
void AudioScrobbler::Submit() {
|
||||
|
||||
for (ScrobblerService *service : scrobbler_services_->List()) {
|
||||
QList<ScrobblerService*> services = GetAll();
|
||||
for (ScrobblerService *service : services) {
|
||||
if (!service->IsEnabled() || !service->IsAuthenticated() || service->IsSubmitted()) continue;
|
||||
service->StartSubmit();
|
||||
}
|
||||
@ -199,7 +253,8 @@ void AudioScrobbler::Submit() {
|
||||
|
||||
void AudioScrobbler::WriteCache() {
|
||||
|
||||
for (ScrobblerService *service : scrobbler_services_->List()) {
|
||||
QList<ScrobblerService*> services = GetAll();
|
||||
for (ScrobblerService *service : services) {
|
||||
if (!service->IsEnabled()) continue;
|
||||
service->WriteCache();
|
||||
}
|
||||
|
@ -22,22 +22,39 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QAtomicInt>
|
||||
|
||||
#include "core/song.h"
|
||||
#include "scrobblerservices.h"
|
||||
|
||||
class Application;
|
||||
class Song;
|
||||
class ScrobblerService;
|
||||
class Song;
|
||||
|
||||
class AudioScrobbler : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AudioScrobbler(Application *app, QObject *parent = nullptr);
|
||||
~AudioScrobbler();
|
||||
|
||||
void AddService(ScrobblerService *service);
|
||||
void RemoveService(ScrobblerService *service);
|
||||
QList<ScrobblerService*> List() const { return services_.values(); }
|
||||
bool HasAnyServices() const { return !services_.isEmpty(); }
|
||||
int NextId();
|
||||
|
||||
QList<ScrobblerService*> GetAll();
|
||||
ScrobblerService *ServiceByName(const QString &name);
|
||||
template<typename T>
|
||||
T *Service() {
|
||||
return qobject_cast<T*>(ServiceByName(T::kName));
|
||||
}
|
||||
|
||||
void ReloadSettings();
|
||||
|
||||
@ -50,25 +67,19 @@ class AudioScrobbler : public QObject {
|
||||
bool ShowErrorDialog() const { return show_error_dialog_; }
|
||||
QList<Song::Source> sources() const { return sources_; }
|
||||
|
||||
void ShowConfig();
|
||||
|
||||
void UpdateNowPlaying(const Song &song);
|
||||
void ClearPlaying();
|
||||
void Scrobble(const Song &song, const qint64 scrobble_point);
|
||||
void ShowConfig();
|
||||
|
||||
ScrobblerService *ServiceByName(const QString &name) const { return scrobbler_services_->ServiceByName(name); }
|
||||
|
||||
template<typename T>
|
||||
T *Service() {
|
||||
return qobject_cast<T*>(ServiceByName(T::kName));
|
||||
}
|
||||
|
||||
public slots:
|
||||
void ToggleScrobbling();
|
||||
void ToggleOffline();
|
||||
void ErrorReceived(const QString &error);
|
||||
void Submit();
|
||||
void Love();
|
||||
void WriteCache();
|
||||
void ErrorReceived(const QString &error);
|
||||
|
||||
signals:
|
||||
void ErrorMessage(const QString &error);
|
||||
@ -79,7 +90,10 @@ class AudioScrobbler : public QObject {
|
||||
|
||||
private:
|
||||
Application *app_;
|
||||
ScrobblerServices *scrobbler_services_;
|
||||
|
||||
QMap<QString, ScrobblerService*> services_;
|
||||
QMutex mutex_;
|
||||
QAtomicInt next_id_;
|
||||
|
||||
bool enabled_;
|
||||
bool offline_;
|
||||
@ -90,6 +104,7 @@ class AudioScrobbler : public QObject {
|
||||
bool show_error_dialog_;
|
||||
QList<Song::Source> sources_;
|
||||
|
||||
Q_DISABLE_COPY(AudioScrobbler)
|
||||
};
|
||||
|
||||
#endif // AUDIOSCROBBLER_H
|
||||
|
@ -48,9 +48,9 @@
|
||||
|
||||
const int LastFMImport::kRequestsDelay = 2000;
|
||||
|
||||
LastFMImport::LastFMImport(QObject *parent)
|
||||
LastFMImport::LastFMImport(NetworkAccessManager *network, QObject *parent)
|
||||
: QObject(parent),
|
||||
network_(new NetworkAccessManager(this)),
|
||||
network_(network),
|
||||
timer_flush_requests_(new QTimer(this)),
|
||||
lastplayed_(false),
|
||||
playcount_(false),
|
||||
|
@ -40,7 +40,7 @@ class LastFMImport : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LastFMImport(QObject *parent = nullptr);
|
||||
explicit LastFMImport(NetworkAccessManager *network, QObject *parent = nullptr);
|
||||
~LastFMImport() override;
|
||||
|
||||
void ReloadSettings();
|
||||
|
@ -21,8 +21,9 @@
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "core/application.h"
|
||||
#include "core/networkaccessmanager.h"
|
||||
|
||||
#include "audioscrobbler.h"
|
||||
#include "lastfmscrobbler.h"
|
||||
|
||||
const char *LastFMScrobbler::kName = "Last.fm";
|
||||
@ -31,5 +32,5 @@ const char *LastFMScrobbler::kAuthUrl = "https://www.last.fm/api/auth/";
|
||||
const char *LastFMScrobbler::kApiUrl = "https://ws.audioscrobbler.com/2.0/";
|
||||
const char *LastFMScrobbler::kCacheFile = "lastfmscrobbler.cache";
|
||||
|
||||
LastFMScrobbler::LastFMScrobbler(Application *app, QObject *parent)
|
||||
: ScrobblingAPI20(kName, kSettingsGroup, kAuthUrl, kApiUrl, true, kCacheFile, app, parent) {}
|
||||
LastFMScrobbler::LastFMScrobbler(AudioScrobbler *scrobbler, NetworkAccessManager *network, QObject *parent)
|
||||
: ScrobblingAPI20(kName, kSettingsGroup, kAuthUrl, kApiUrl, true, kCacheFile, scrobbler, network, parent) {}
|
||||
|
@ -27,13 +27,14 @@
|
||||
|
||||
#include "scrobblingapi20.h"
|
||||
|
||||
class Application;
|
||||
class AudioScrobbler;
|
||||
class NetworkAccessManager;
|
||||
|
||||
class LastFMScrobbler : public ScrobblingAPI20 {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LastFMScrobbler(Application *app, QObject *parent = nullptr);
|
||||
explicit LastFMScrobbler(AudioScrobbler *scrobbler, NetworkAccessManager *network, QObject *parent = nullptr);
|
||||
|
||||
static const char *kName;
|
||||
static const char *kSettingsGroup;
|
||||
|
@ -21,8 +21,9 @@
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "core/application.h"
|
||||
#include "core/networkaccessmanager.h"
|
||||
|
||||
#include "audioscrobbler.h"
|
||||
#include "scrobblingapi20.h"
|
||||
#include "librefmscrobbler.h"
|
||||
|
||||
@ -32,5 +33,5 @@ const char *LibreFMScrobbler::kAuthUrl = "https://www.libre.fm/api/auth/";
|
||||
const char *LibreFMScrobbler::kApiUrl = "https://libre.fm/2.0/";
|
||||
const char *LibreFMScrobbler::kCacheFile = "librefmscrobbler.cache";
|
||||
|
||||
LibreFMScrobbler::LibreFMScrobbler(Application *app, QObject *parent)
|
||||
: ScrobblingAPI20(kName, kSettingsGroup, kAuthUrl, kApiUrl, false, kCacheFile, app, parent) {}
|
||||
LibreFMScrobbler::LibreFMScrobbler(AudioScrobbler *scrobbler, NetworkAccessManager *network, QObject *parent)
|
||||
: ScrobblingAPI20(kName, kSettingsGroup, kAuthUrl, kApiUrl, false, kCacheFile, scrobbler, network, parent) {}
|
||||
|
@ -27,13 +27,14 @@
|
||||
|
||||
#include "scrobblingapi20.h"
|
||||
|
||||
class Application;
|
||||
class AudioScrobbler;
|
||||
class NetworkAccessManager;
|
||||
|
||||
class LibreFMScrobbler : public ScrobblingAPI20 {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LibreFMScrobbler(Application *app, QObject *parent = nullptr);
|
||||
explicit LibreFMScrobbler(AudioScrobbler *scrobbler, NetworkAccessManager *network, QObject *parent = nullptr);
|
||||
|
||||
static const char *kName;
|
||||
static const char *kSettingsGroup;
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include <QJsonArray>
|
||||
#include <QJsonValue>
|
||||
|
||||
#include "core/application.h"
|
||||
#include "core/networkaccessmanager.h"
|
||||
#include "core/song.h"
|
||||
#include "core/logging.h"
|
||||
@ -66,10 +65,10 @@ const char *ListenBrainzScrobbler::kClientSecretB64 = "Uk9GZ2hrZVEzRjNvUHlFaHFpe
|
||||
const char *ListenBrainzScrobbler::kCacheFile = "listenbrainzscrobbler.cache";
|
||||
const int ListenBrainzScrobbler::kScrobblesPerRequest = 10;
|
||||
|
||||
ListenBrainzScrobbler::ListenBrainzScrobbler(Application *app, QObject *parent)
|
||||
: ScrobblerService(kName, app, parent),
|
||||
app_(app),
|
||||
network_(new NetworkAccessManager(this)),
|
||||
ListenBrainzScrobbler::ListenBrainzScrobbler(AudioScrobbler *scrobbler, NetworkAccessManager *network, QObject *parent)
|
||||
: ScrobblerService(kName, parent),
|
||||
scrobbler_(scrobbler),
|
||||
network_(network),
|
||||
cache_(new ScrobblerCache(kCacheFile, this)),
|
||||
server_(nullptr),
|
||||
enabled_(false),
|
||||
@ -87,7 +86,7 @@ ListenBrainzScrobbler::ListenBrainzScrobbler(Application *app, QObject *parent)
|
||||
timer_submit_.setSingleShot(true);
|
||||
QObject::connect(&timer_submit_, &QTimer::timeout, this, &ListenBrainzScrobbler::Submit);
|
||||
|
||||
ListenBrainzScrobbler::ReloadSettings();
|
||||
ReloadSettings();
|
||||
LoadSession();
|
||||
|
||||
}
|
||||
@ -449,7 +448,7 @@ void ListenBrainzScrobbler::UpdateNowPlaying(const Song &song) {
|
||||
scrobbled_ = false;
|
||||
timestamp_ = QDateTime::currentDateTime().toSecsSinceEpoch();
|
||||
|
||||
if (!song.is_metadata_good() || !IsAuthenticated() || app_->scrobbler()->IsOffline()) return;
|
||||
if (!song.is_metadata_good() || !IsAuthenticated() || scrobbler_->IsOffline()) return;
|
||||
|
||||
QJsonObject object_listen;
|
||||
object_listen.insert("track_metadata", JsonTrackMetadata(ScrobbleMetadata(song)));
|
||||
@ -509,7 +508,7 @@ void ListenBrainzScrobbler::Scrobble(const Song &song) {
|
||||
|
||||
cache_->Add(song, timestamp_);
|
||||
|
||||
if (app_->scrobbler()->IsOffline() || !IsAuthenticated()) return;
|
||||
if (scrobbler_->IsOffline() || !IsAuthenticated()) return;
|
||||
|
||||
StartSubmit();
|
||||
|
||||
@ -518,14 +517,14 @@ void ListenBrainzScrobbler::Scrobble(const Song &song) {
|
||||
void ListenBrainzScrobbler::StartSubmit(const bool initial) {
|
||||
|
||||
if (!submitted_ && cache_->Count() > 0) {
|
||||
if (initial && app_->scrobbler()->SubmitDelay() <= 0 && !submit_error_) {
|
||||
if (initial && scrobbler_->SubmitDelay() <= 0 && !submit_error_) {
|
||||
if (timer_submit_.isActive()) {
|
||||
timer_submit_.stop();
|
||||
}
|
||||
Submit();
|
||||
}
|
||||
else if (!timer_submit_.isActive()) {
|
||||
int submit_delay = static_cast<int>(std::max(app_->scrobbler()->SubmitDelay(), submit_error_ ? 30 : 5) * kMsecPerSec);
|
||||
int submit_delay = static_cast<int>(std::max(scrobbler_->SubmitDelay(), submit_error_ ? 30 : 5) * kMsecPerSec);
|
||||
timer_submit_.setInterval(submit_delay);
|
||||
timer_submit_.start();
|
||||
}
|
||||
@ -537,7 +536,7 @@ void ListenBrainzScrobbler::Submit() {
|
||||
|
||||
qLog(Debug) << "ListenBrainz: Submitting scrobbles.";
|
||||
|
||||
if (!IsEnabled() || !IsAuthenticated() || app_->scrobbler()->IsOffline()) return;
|
||||
if (!IsEnabled() || !IsAuthenticated() || scrobbler_->IsOffline()) return;
|
||||
|
||||
QJsonArray array;
|
||||
ScrobblerCacheItemPtrList cache_items_sent;
|
||||
@ -620,7 +619,7 @@ void ListenBrainzScrobbler::Love() {
|
||||
|
||||
if (!song_playing_.is_valid() || !song_playing_.is_metadata_good()) return;
|
||||
|
||||
if (!IsAuthenticated()) app_->scrobbler()->ShowConfig();
|
||||
if (!IsAuthenticated()) scrobbler_->ShowConfig();
|
||||
|
||||
if (song_playing_.musicbrainz_recording_id().isEmpty()) {
|
||||
Error(tr("Missing MusicBrainz recording ID for %1 %2 %3").arg(song_playing_.artist()).arg(song_playing_.album()).arg(song_playing_.title()));
|
||||
@ -671,7 +670,7 @@ void ListenBrainzScrobbler::Error(const QString &error, const QVariant &debug) {
|
||||
qLog(Error) << "ListenBrainz:" << error;
|
||||
if (debug.isValid()) qLog(Debug) << debug;
|
||||
|
||||
if (app_->scrobbler()->ShowErrorDialog()) {
|
||||
if (scrobbler_->ShowErrorDialog()) {
|
||||
emit ErrorMessage(tr("ListenBrainz error: %1").arg(error));
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
class Application;
|
||||
class AudioScrobbler;
|
||||
class NetworkAccessManager;
|
||||
class LocalRedirectServer;
|
||||
|
||||
@ -47,7 +47,7 @@ class ListenBrainzScrobbler : public ScrobblerService {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ListenBrainzScrobbler(Application *app, QObject *parent = nullptr);
|
||||
explicit ListenBrainzScrobbler(AudioScrobbler *scrobbler, NetworkAccessManager *network, QObject *parent = nullptr);
|
||||
~ListenBrainzScrobbler() override;
|
||||
|
||||
static const char *kName;
|
||||
@ -110,7 +110,7 @@ class ListenBrainzScrobbler : public ScrobblerService {
|
||||
static const char *kCacheFile;
|
||||
static const int kScrobblesPerRequest;
|
||||
|
||||
Application *app_;
|
||||
AudioScrobbler *scrobbler_;
|
||||
NetworkAccessManager *network_;
|
||||
ScrobblerCache *cache_;
|
||||
LocalRedirectServer *server_;
|
||||
|
@ -30,11 +30,7 @@
|
||||
|
||||
#include "core/song.h"
|
||||
|
||||
ScrobblerService::ScrobblerService(const QString &name, Application *app, QObject *parent) : QObject(parent), name_(name) {
|
||||
|
||||
Q_UNUSED(app);
|
||||
|
||||
}
|
||||
ScrobblerService::ScrobblerService(const QString &name, QObject *parent) : QObject(parent), name_(name) {}
|
||||
|
||||
bool ScrobblerService::ExtractJsonObj(const QByteArray &data, QJsonObject &json_obj, QString &error_description) {
|
||||
|
||||
|
@ -32,13 +32,11 @@
|
||||
|
||||
#include "core/song.h"
|
||||
|
||||
class Application;
|
||||
|
||||
class ScrobblerService : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ScrobblerService(const QString &name, Application *app, QObject *parent);
|
||||
explicit ScrobblerService(const QString &name, QObject *parent);
|
||||
|
||||
QString name() const { return name_; }
|
||||
|
||||
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QMutexLocker>
|
||||
#include <QString>
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
#include "scrobblerservices.h"
|
||||
#include "scrobblerservice.h"
|
||||
|
||||
ScrobblerServices::ScrobblerServices(QObject *parent) : QObject(parent) {}
|
||||
|
||||
ScrobblerServices::~ScrobblerServices() {
|
||||
|
||||
while (!scrobbler_services_.isEmpty()) {
|
||||
delete scrobbler_services_.take(scrobbler_services_.firstKey());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ScrobblerServices::AddService(ScrobblerService *service) {
|
||||
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
scrobbler_services_.insert(service->name(), service);
|
||||
}
|
||||
|
||||
qLog(Debug) << "Registered scrobbler service" << service->name();
|
||||
|
||||
}
|
||||
|
||||
void ScrobblerServices::RemoveService(ScrobblerService *service) {
|
||||
|
||||
if (!service || !scrobbler_services_.contains(service->name())) return;
|
||||
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
scrobbler_services_.remove(service->name());
|
||||
QObject::disconnect(service, nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
qLog(Debug) << "Unregistered scrobbler service" << service->name();
|
||||
|
||||
}
|
||||
|
||||
int ScrobblerServices::NextId() { return next_id_.fetchAndAddRelaxed(1); }
|
||||
|
||||
ScrobblerService *ScrobblerServices::ServiceByName(const QString &name) {
|
||||
|
||||
if (scrobbler_services_.contains(name)) return scrobbler_services_.value(name);
|
||||
return nullptr;
|
||||
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCROBBLERSERVICES_H
|
||||
#define SCROBBLERSERVICES_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QAtomicInt>
|
||||
|
||||
class ScrobblerService;
|
||||
|
||||
class ScrobblerServices : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ScrobblerServices(QObject *parent = nullptr);
|
||||
~ScrobblerServices() override;
|
||||
|
||||
void AddService(ScrobblerService *service);
|
||||
void RemoveService(ScrobblerService *service);
|
||||
QList<ScrobblerService*> List() const { return scrobbler_services_.values(); }
|
||||
bool HasAnyServices() const { return !scrobbler_services_.isEmpty(); }
|
||||
int NextId();
|
||||
|
||||
ScrobblerService *ServiceByName(const QString &name);
|
||||
template<typename T>
|
||||
T *Service() {
|
||||
return qobject_cast<T*>(ServiceByName(T::kName));
|
||||
}
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(ScrobblerServices)
|
||||
|
||||
QMap<QString, ScrobblerService *> scrobbler_services_;
|
||||
QMutex mutex_;
|
||||
|
||||
QAtomicInt next_id_;
|
||||
|
||||
};
|
||||
|
||||
#endif // SCROBBLERSERVICES_H
|
@ -44,7 +44,6 @@
|
||||
#include <QJsonValue>
|
||||
#include <QFlags>
|
||||
|
||||
#include "core/application.h"
|
||||
#include "core/networkaccessmanager.h"
|
||||
#include "core/song.h"
|
||||
#include "core/logging.h"
|
||||
@ -63,15 +62,15 @@ const char *ScrobblingAPI20::kApiKey = "211990b4c96782c05d1536e7219eb56e";
|
||||
const char *ScrobblingAPI20::kSecret = "80fd738f49596e9709b1bf9319c444a8";
|
||||
const int ScrobblingAPI20::kScrobblesPerRequest = 50;
|
||||
|
||||
ScrobblingAPI20::ScrobblingAPI20(const QString &name, const QString &settings_group, const QString &auth_url, const QString &api_url, const bool batch, const QString &cache_file, Application *app, QObject *parent)
|
||||
: ScrobblerService(name, app, parent),
|
||||
ScrobblingAPI20::ScrobblingAPI20(const QString &name, const QString &settings_group, const QString &auth_url, const QString &api_url, const bool batch, const QString &cache_file, AudioScrobbler *scrobbler, NetworkAccessManager *network, QObject *parent)
|
||||
: ScrobblerService(name, parent),
|
||||
name_(name),
|
||||
settings_group_(settings_group),
|
||||
auth_url_(auth_url),
|
||||
api_url_(api_url),
|
||||
batch_(batch),
|
||||
app_(app),
|
||||
network_(new NetworkAccessManager(this)),
|
||||
scrobbler_(scrobbler),
|
||||
network_(network),
|
||||
cache_(new ScrobblerCache(cache_file, this)),
|
||||
server_(nullptr),
|
||||
enabled_(false),
|
||||
@ -398,7 +397,7 @@ void ScrobblingAPI20::UpdateNowPlaying(const Song &song) {
|
||||
timestamp_ = QDateTime::currentDateTime().toSecsSinceEpoch();
|
||||
scrobbled_ = false;
|
||||
|
||||
if (!IsAuthenticated() || !song.is_metadata_good() || app_->scrobbler()->IsOffline()) return;
|
||||
if (!IsAuthenticated() || !song.is_metadata_good() || scrobbler_->IsOffline()) return;
|
||||
|
||||
ParamList params = ParamList()
|
||||
<< Param("method", "track.updateNowPlaying")
|
||||
@ -457,10 +456,10 @@ void ScrobblingAPI20::Scrobble(const Song &song) {
|
||||
|
||||
cache_->Add(song, timestamp_);
|
||||
|
||||
if (app_->scrobbler()->IsOffline()) return;
|
||||
if (scrobbler_->IsOffline()) return;
|
||||
|
||||
if (!IsAuthenticated()) {
|
||||
if (app_->scrobbler()->ShowErrorDialog()) {
|
||||
if (scrobbler_->ShowErrorDialog()) {
|
||||
emit ErrorMessage(tr("Scrobbler %1 is not authenticated!").arg(name_));
|
||||
}
|
||||
return;
|
||||
@ -472,14 +471,14 @@ void ScrobblingAPI20::Scrobble(const Song &song) {
|
||||
void ScrobblingAPI20::StartSubmit(const bool initial) {
|
||||
|
||||
if (!submitted_ && cache_->Count() > 0) {
|
||||
if (initial && (!batch_ || app_->scrobbler()->SubmitDelay() <= 0) && !submit_error_) {
|
||||
if (initial && (!batch_ || scrobbler_->SubmitDelay() <= 0) && !submit_error_) {
|
||||
if (timer_submit_.isActive()) {
|
||||
timer_submit_.stop();
|
||||
}
|
||||
Submit();
|
||||
}
|
||||
else if (!timer_submit_.isActive()) {
|
||||
int submit_delay = static_cast<int>(std::max(app_->scrobbler()->SubmitDelay(), submit_error_ ? 30 : 5) * kMsecPerSec);
|
||||
int submit_delay = static_cast<int>(std::max(scrobbler_->SubmitDelay(), submit_error_ ? 30 : 5) * kMsecPerSec);
|
||||
timer_submit_.setInterval(submit_delay);
|
||||
timer_submit_.start();
|
||||
}
|
||||
@ -489,7 +488,7 @@ void ScrobblingAPI20::StartSubmit(const bool initial) {
|
||||
|
||||
void ScrobblingAPI20::Submit() {
|
||||
|
||||
if (!IsEnabled() || !IsAuthenticated() || app_->scrobbler()->IsOffline()) return;
|
||||
if (!IsEnabled() || !IsAuthenticated() || scrobbler_->IsOffline()) return;
|
||||
|
||||
qLog(Debug) << name_ << "Submitting scrobbles.";
|
||||
|
||||
@ -827,7 +826,7 @@ void ScrobblingAPI20::Love() {
|
||||
|
||||
if (!song_playing_.is_valid() || !song_playing_.is_metadata_good()) return;
|
||||
|
||||
if (!IsAuthenticated()) app_->scrobbler()->ShowConfig();
|
||||
if (!IsAuthenticated()) scrobbler_->ShowConfig();
|
||||
|
||||
qLog(Debug) << name_ << "Sending love for song" << song_playing_.artist() << song_playing_.album() << song_playing_.title();
|
||||
|
||||
@ -909,7 +908,7 @@ void ScrobblingAPI20::Error(const QString &error, const QVariant &debug) {
|
||||
qLog(Error) << name_ << error;
|
||||
if (debug.isValid()) qLog(Debug) << debug;
|
||||
|
||||
if (app_->scrobbler()->ShowErrorDialog()) {
|
||||
if (scrobbler_->ShowErrorDialog()) {
|
||||
emit ErrorMessage(tr("Scrobbler %1 error: %2").arg(name_, error));
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
class Application;
|
||||
class AudioScrobbler;
|
||||
class NetworkAccessManager;
|
||||
class LocalRedirectServer;
|
||||
|
||||
@ -45,7 +45,7 @@ class ScrobblingAPI20 : public ScrobblerService {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ScrobblingAPI20(const QString &name, const QString &settings_group, const QString &auth_url, const QString &api_url, const bool batch, const QString &cache_file, Application *app, QObject *parent = nullptr);
|
||||
explicit ScrobblingAPI20(const QString &name, const QString &settings_group, const QString &auth_url, const QString &api_url, const bool batch, const QString &cache_file, AudioScrobbler *scrobbler, NetworkAccessManager *network, QObject *parent = nullptr);
|
||||
~ScrobblingAPI20() override;
|
||||
|
||||
static const char *kApiKey;
|
||||
@ -142,7 +142,7 @@ class ScrobblingAPI20 : public ScrobblerService {
|
||||
QString api_url_;
|
||||
bool batch_;
|
||||
|
||||
Application *app_;
|
||||
AudioScrobbler *scrobbler_;
|
||||
NetworkAccessManager *network_;
|
||||
ScrobblerCache *cache_;
|
||||
LocalRedirectServer *server_;
|
||||
|
@ -39,13 +39,15 @@
|
||||
|
||||
const char *SubsonicScrobbler::kName = "Subsonic";
|
||||
|
||||
SubsonicScrobbler::SubsonicScrobbler(Application *app, QObject *parent)
|
||||
: ScrobblerService(kName, app, parent),
|
||||
app_(app),
|
||||
service_(app->internet_services()->Service<SubsonicService>()),
|
||||
SubsonicScrobbler::SubsonicScrobbler(AudioScrobbler *scrobbler, SubsonicService *service, QObject *parent)
|
||||
: ScrobblerService(kName, parent),
|
||||
scrobbler_(scrobbler),
|
||||
service_(service),
|
||||
enabled_(false),
|
||||
submitted_(false) {
|
||||
|
||||
ReloadSettings();
|
||||
|
||||
timer_submit_.setSingleShot(true);
|
||||
QObject::connect(&timer_submit_, &QTimer::timeout, this, &SubsonicScrobbler::Submit);
|
||||
|
||||
@ -67,7 +69,7 @@ void SubsonicScrobbler::UpdateNowPlaying(const Song &song) {
|
||||
song_playing_ = song;
|
||||
time_ = QDateTime::currentDateTime();
|
||||
|
||||
if (!song.is_metadata_good() || app_->scrobbler()->IsOffline()) return;
|
||||
if (!song.is_metadata_good() || scrobbler_->IsOffline()) return;
|
||||
|
||||
service_->Scrobble(song.song_id(), false, time_);
|
||||
|
||||
@ -84,15 +86,15 @@ void SubsonicScrobbler::Scrobble(const Song &song) {
|
||||
|
||||
if (song.source() != Song::Source::Subsonic || song.id() != song_playing_.id() || song.url() != song_playing_.url() || !song.is_metadata_good()) return;
|
||||
|
||||
if (app_->scrobbler()->IsOffline()) return;
|
||||
if (scrobbler_->IsOffline()) return;
|
||||
|
||||
if (!submitted_) {
|
||||
submitted_ = true;
|
||||
if (app_->scrobbler()->SubmitDelay() <= 0) {
|
||||
if (scrobbler_->SubmitDelay() <= 0) {
|
||||
Submit();
|
||||
}
|
||||
else if (!timer_submit_.isActive()) {
|
||||
timer_submit_.setInterval(static_cast<int>(app_->scrobbler()->SubmitDelay() * kMsecPerSec));
|
||||
timer_submit_.setInterval(static_cast<int>(scrobbler_->SubmitDelay() * kMsecPerSec));
|
||||
timer_submit_.start();
|
||||
}
|
||||
}
|
||||
@ -104,7 +106,7 @@ void SubsonicScrobbler::Submit() {
|
||||
qLog(Debug) << "SubsonicScrobbler: Submitting scrobble for" << song_playing_.artist() << song_playing_.title();
|
||||
submitted_ = false;
|
||||
|
||||
if (app_->scrobbler()->IsOffline()) return;
|
||||
if (scrobbler_->IsOffline()) return;
|
||||
|
||||
service_->Scrobble(song_playing_.song_id(), true, time_);
|
||||
|
||||
|
@ -34,13 +34,14 @@
|
||||
#include "scrobblerservice.h"
|
||||
|
||||
class Application;
|
||||
class AudioScrobbler;
|
||||
class SubsonicService;
|
||||
|
||||
class SubsonicScrobbler : public ScrobblerService {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SubsonicScrobbler(Application *app, QObject *parent = nullptr);
|
||||
explicit SubsonicScrobbler(AudioScrobbler *scrobbler, SubsonicService *service, QObject *parent = nullptr);
|
||||
|
||||
static const char *kName;
|
||||
|
||||
@ -62,7 +63,7 @@ class SubsonicScrobbler : public ScrobblerService {
|
||||
void Submit() override;
|
||||
|
||||
private:
|
||||
Application *app_;
|
||||
AudioScrobbler *scrobbler_;
|
||||
SubsonicService *service_;
|
||||
bool enabled_;
|
||||
bool submitted_;
|
||||
|
@ -57,6 +57,8 @@
|
||||
#include "subsonicscrobblerequest.h"
|
||||
#include "settings/settingsdialog.h"
|
||||
#include "settings/subsonicsettingspage.h"
|
||||
#include "scrobbler/audioscrobbler.h"
|
||||
#include "scrobbler/subsonicscrobbler.h"
|
||||
|
||||
const Song::Source SubsonicService::kSource = Song::Source::Subsonic;
|
||||
const char *SubsonicService::kClientName = "Strawberry";
|
||||
@ -97,6 +99,8 @@ SubsonicService::SubsonicService(Application *app, QObject *parent)
|
||||
|
||||
SubsonicService::ReloadSettings();
|
||||
|
||||
app->scrobbler()->AddService(new SubsonicScrobbler(app->scrobbler(), this, this));
|
||||
|
||||
}
|
||||
|
||||
SubsonicService::~SubsonicService() {
|
||||
|
@ -87,7 +87,7 @@ using namespace std::chrono_literals;
|
||||
TidalService::TidalService(Application *app, QObject *parent)
|
||||
: InternetService(Song::Source::Tidal, "Tidal", "tidal", TidalSettingsPage::kSettingsGroup, SettingsDialog::Page::Tidal, app, parent),
|
||||
app_(app),
|
||||
network_(new NetworkAccessManager(this)),
|
||||
network_(app->network()),
|
||||
url_handler_(new TidalUrlHandler(app, this)),
|
||||
artists_collection_backend_(nullptr),
|
||||
albums_collection_backend_(nullptr),
|
||||
|
Loading…
x
Reference in New Issue
Block a user