mirror of
https://github.com/strawberrymusicplayer/strawberry
synced 2025-01-27 15:49:43 +01:00
Fix exit
This commit is contained in:
parent
da0d61f36a
commit
41484f8673
@ -127,8 +127,10 @@ void SCollection::Exit() {
|
||||
|
||||
void SCollection::ExitReceived() {
|
||||
|
||||
disconnect(sender(), 0, this, 0);
|
||||
wait_for_exit_.removeAll(sender());
|
||||
QObject *obj = static_cast<QObject*>(sender());
|
||||
disconnect(obj, 0, this, 0);
|
||||
qLog(Debug) << obj << "successfully exited.";
|
||||
wait_for_exit_.removeAll(obj);
|
||||
if (wait_for_exit_.isEmpty()) emit ExitFinished();
|
||||
|
||||
}
|
||||
|
@ -248,19 +248,27 @@ void Application::MoveToThread(QObject *object, QThread *thread) {
|
||||
|
||||
void Application::Exit() {
|
||||
|
||||
wait_for_exit_ << collection()
|
||||
wait_for_exit_ << tag_reader_client()
|
||||
<< collection()
|
||||
<< playlist_backend()
|
||||
<< album_cover_loader()
|
||||
#ifndef Q_OS_WIN
|
||||
<< device_manager()
|
||||
#endif
|
||||
<< internet_services();
|
||||
|
||||
connect(tag_reader_client(), SIGNAL(ExitFinished()), this, SLOT(ExitReceived()));
|
||||
tag_reader_client()->ExitAsync();
|
||||
|
||||
connect(collection(), SIGNAL(ExitFinished()), this, SLOT(ExitReceived()));
|
||||
collection()->Exit();
|
||||
|
||||
connect(playlist_backend(), SIGNAL(ExitFinished()), this, SLOT(ExitReceived()));
|
||||
playlist_backend()->ExitAsync();
|
||||
|
||||
connect(album_cover_loader(), SIGNAL(ExitFinished()), this, SLOT(ExitReceived()));
|
||||
album_cover_loader()->ExitAsync();
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
connect(device_manager(), SIGNAL(ExitFinished()), this, SLOT(ExitReceived()));
|
||||
device_manager()->Exit();
|
||||
@ -269,16 +277,21 @@ void Application::Exit() {
|
||||
connect(internet_services(), SIGNAL(ExitFinished()), this, SLOT(ExitReceived()));
|
||||
internet_services()->Exit();
|
||||
|
||||
database()->Close();
|
||||
|
||||
}
|
||||
|
||||
void Application::ExitReceived() {
|
||||
|
||||
disconnect(sender(), 0, this, 0);
|
||||
QObject *obj = static_cast<QObject*>(sender());
|
||||
disconnect(obj, 0, this, 0);
|
||||
|
||||
wait_for_exit_.removeAll(sender());
|
||||
if (wait_for_exit_.isEmpty()) emit ExitFinished();
|
||||
qLog(Debug) << obj << "successfully exited.";
|
||||
|
||||
wait_for_exit_.removeAll(obj);
|
||||
if (wait_for_exit_.isEmpty()) {
|
||||
database()->Close();
|
||||
connect(database(), SIGNAL(ExitFinished()), this, SIGNAL(ExitFinished()));
|
||||
database()->ExitAsync();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -229,7 +229,10 @@ Database::Database(Application *app, QObject *parent, const QString &database_na
|
||||
mutex_(QMutex::Recursive),
|
||||
injected_database_name_(database_name),
|
||||
query_hash_(0),
|
||||
startup_schema_version_(-1) {
|
||||
startup_schema_version_(-1),
|
||||
original_thread_(nullptr) {
|
||||
|
||||
original_thread_ = thread();
|
||||
|
||||
{
|
||||
QMutexLocker l(&sNextConnectionIdMutex);
|
||||
@ -259,6 +262,19 @@ Database::~Database() {
|
||||
|
||||
}
|
||||
|
||||
void Database::ExitAsync() {
|
||||
metaObject()->invokeMethod(this, "Exit", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void Database::Exit() {
|
||||
|
||||
assert(QThread::currentThread() == thread());
|
||||
Close();
|
||||
moveToThread(original_thread_);
|
||||
emit ExitFinished();
|
||||
|
||||
}
|
||||
|
||||
QSqlDatabase Database::Connect() {
|
||||
|
||||
QMutexLocker l(&connect_mutex_);
|
||||
|
@ -44,6 +44,7 @@ struct sqlite3_tokenizer_cursor;
|
||||
struct sqlite3_tokenizer_module;
|
||||
}
|
||||
|
||||
class QThread;
|
||||
class Application;
|
||||
|
||||
class Database : public QObject {
|
||||
@ -67,6 +68,7 @@ class Database : public QObject {
|
||||
static const char *kDatabaseFilename;
|
||||
static const char *kMagicAllSongsTables;
|
||||
|
||||
void ExitAsync();
|
||||
QSqlDatabase Connect();
|
||||
void Close();
|
||||
bool CheckErrors(const QSqlQuery &query);
|
||||
@ -82,9 +84,13 @@ class Database : public QObject {
|
||||
void AttachDatabaseOnDbConnection(const QString &database_name, const AttachedDatabase &database, QSqlDatabase &db);
|
||||
void DetachDatabase(const QString &database_name);
|
||||
|
||||
signals:
|
||||
signals:
|
||||
void ExitFinished();
|
||||
void Error(const QString &message);
|
||||
|
||||
private slots:
|
||||
void Exit();
|
||||
|
||||
public slots:
|
||||
void DoBackup();
|
||||
|
||||
@ -126,6 +132,8 @@ signals:
|
||||
// This is the schema version of Strawberry's DB from the app's last run.
|
||||
int startup_schema_version_;
|
||||
|
||||
QThread *original_thread_;
|
||||
|
||||
// Do static initialisation like loading sqlite functions.
|
||||
static void StaticInit();
|
||||
|
||||
|
@ -237,7 +237,8 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
playing_widget_(true),
|
||||
doubleclick_addmode_(BehaviourSettingsPage::AddBehaviour_Append),
|
||||
doubleclick_playmode_(BehaviourSettingsPage::PlayBehaviour_Never),
|
||||
menu_playmode_(BehaviourSettingsPage::PlayBehaviour_Never)
|
||||
menu_playmode_(BehaviourSettingsPage::PlayBehaviour_Never),
|
||||
exit_count_(0)
|
||||
{
|
||||
|
||||
qLog(Debug) << "Starting";
|
||||
@ -985,20 +986,26 @@ void MainWindow::SaveSettings() {
|
||||
|
||||
void MainWindow::Exit() {
|
||||
|
||||
++exit_count_;
|
||||
|
||||
SaveSettings();
|
||||
|
||||
if (app_->player()->engine()->is_fadeout_enabled()) {
|
||||
// To shut down the application when fadeout will be finished
|
||||
connect(app_->player()->engine(), SIGNAL(FadeoutFinishedSignal()), this, SLOT(DoExit()));
|
||||
if (app_->player()->GetState() == Engine::Playing) {
|
||||
app_->player()->Stop();
|
||||
hide();
|
||||
if (tray_icon_) tray_icon_->SetVisible(false);
|
||||
return; // Don't quit the application now: wait for the fadeout finished signal
|
||||
}
|
||||
if (exit_count_ > 1) {
|
||||
qApp->quit();
|
||||
}
|
||||
else {
|
||||
if (app_->player()->engine()->is_fadeout_enabled()) {
|
||||
// To shut down the application when fadeout will be finished
|
||||
connect(app_->player()->engine(), SIGNAL(FadeoutFinishedSignal()), this, SLOT(DoExit()));
|
||||
if (app_->player()->GetState() == Engine::Playing) {
|
||||
app_->player()->Stop();
|
||||
hide();
|
||||
if (tray_icon_) tray_icon_->SetVisible(false);
|
||||
return; // Don't quit the application now: wait for the fadeout finished signal
|
||||
}
|
||||
}
|
||||
DoExit();
|
||||
}
|
||||
|
||||
DoExit();
|
||||
|
||||
}
|
||||
|
||||
@ -1323,8 +1330,8 @@ void MainWindow::closeEvent(QCloseEvent *event) {
|
||||
}
|
||||
else {
|
||||
Exit();
|
||||
QApplication::quit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::SetHiddenInTray(bool hidden) {
|
||||
|
@ -369,6 +369,7 @@ signals:
|
||||
Song song_;
|
||||
Song song_playing_;
|
||||
QImage image_original_;
|
||||
int exit_count_;
|
||||
|
||||
};
|
||||
|
||||
|
@ -42,6 +42,7 @@ TagReaderClient *TagReaderClient::sInstance = nullptr;
|
||||
TagReaderClient::TagReaderClient(QObject *parent) : QObject(parent), worker_pool_(new WorkerPool<HandlerType>(this)) {
|
||||
|
||||
sInstance = this;
|
||||
original_thread_ = thread();
|
||||
|
||||
worker_pool_->SetExecutableName(kWorkerExecutableName);
|
||||
worker_pool_->SetWorkerCount(QThread::idealThreadCount());
|
||||
@ -50,6 +51,18 @@ TagReaderClient::TagReaderClient(QObject *parent) : QObject(parent), worker_pool
|
||||
|
||||
void TagReaderClient::Start() { worker_pool_->Start(); }
|
||||
|
||||
void TagReaderClient::ExitAsync() {
|
||||
metaObject()->invokeMethod(this, "Exit", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void TagReaderClient::Exit() {
|
||||
|
||||
assert(QThread::currentThread() == thread());
|
||||
moveToThread(original_thread_);
|
||||
emit ExitFinished();
|
||||
|
||||
}
|
||||
|
||||
void TagReaderClient::WorkerFailedToStart() {
|
||||
qLog(Error) << "The" << kWorkerExecutableName << "executable was not found in the current directory or on the PATH. Strawberry will not be able to read music file tags without it.";
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "song.h"
|
||||
#include "tagreadermessages.pb.h"
|
||||
|
||||
class QThread;
|
||||
class Song;
|
||||
template <typename HandlerType> class WorkerPool;
|
||||
|
||||
@ -51,6 +52,7 @@ class TagReaderClient : public QObject {
|
||||
static const char *kWorkerExecutableName;
|
||||
|
||||
void Start();
|
||||
void ExitAsync();
|
||||
|
||||
ReplyType *ReadFile(const QString &filename);
|
||||
ReplyType *SaveFile(const QString &filename, const Song &metadata);
|
||||
@ -67,7 +69,11 @@ class TagReaderClient : public QObject {
|
||||
// TODO: Make this not a singleton
|
||||
static TagReaderClient *Instance() { return sInstance; }
|
||||
|
||||
signals:
|
||||
void ExitFinished();
|
||||
|
||||
private slots:
|
||||
void Exit();
|
||||
void WorkerFailedToStart();
|
||||
|
||||
private:
|
||||
@ -75,6 +81,7 @@ class TagReaderClient : public QObject {
|
||||
|
||||
WorkerPool<HandlerType> *worker_pool_;
|
||||
QList<pb::tagreader::Message> message_queue_;
|
||||
QThread *original_thread_;
|
||||
};
|
||||
|
||||
typedef TagReaderClient::ReplyType TagReaderReply;
|
||||
|
@ -23,12 +23,12 @@
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QDir>
|
||||
#include <QQueue>
|
||||
#include <QMutex>
|
||||
#include <QStandardPaths>
|
||||
#include <QSize>
|
||||
#include <QDir>
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QList>
|
||||
#include <QQueue>
|
||||
#include <QSet>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
@ -37,6 +37,7 @@
|
||||
#include <QImage>
|
||||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
#include <QSize>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
@ -61,13 +62,30 @@ AlbumCoverLoader::AlbumCoverLoader(QObject *parent)
|
||||
cover_filename_(CollectionSettingsPage::SaveCover_Hash),
|
||||
cover_overwrite_(false),
|
||||
cover_lowercase_(true),
|
||||
cover_replace_spaces_(true)
|
||||
cover_replace_spaces_(true),
|
||||
original_thread_(nullptr)
|
||||
{
|
||||
|
||||
original_thread_ = thread();
|
||||
ReloadSettings();
|
||||
|
||||
}
|
||||
|
||||
void AlbumCoverLoader::ExitAsync() {
|
||||
|
||||
stop_requested_ = true;
|
||||
metaObject()->invokeMethod(this, "Exit", Qt::QueuedConnection);
|
||||
|
||||
}
|
||||
|
||||
void AlbumCoverLoader::Exit() {
|
||||
|
||||
assert(QThread::currentThread() == thread());
|
||||
moveToThread(original_thread_);
|
||||
emit ExitFinished();
|
||||
|
||||
}
|
||||
|
||||
void AlbumCoverLoader::ReloadSettings() {
|
||||
|
||||
QSettings s;
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "settings/collectionsettingspage.h"
|
||||
#include "albumcoverloaderoptions.h"
|
||||
|
||||
class QThread;
|
||||
class Song;
|
||||
class NetworkAccessManager;
|
||||
|
||||
@ -52,6 +53,7 @@ class AlbumCoverLoader : public QObject {
|
||||
|
||||
void ReloadSettings();
|
||||
|
||||
void ExitAsync();
|
||||
void Stop() { stop_requested_ = true; }
|
||||
|
||||
static QString ImageCacheDir(const Song::Source source);
|
||||
@ -68,11 +70,13 @@ class AlbumCoverLoader : public QObject {
|
||||
static QPixmap TryLoadPixmap(const QUrl &automatic, const QUrl &manual, const QUrl &url = QUrl());
|
||||
static QImage ScaleAndPad(const AlbumCoverLoaderOptions &options, const QImage &image);
|
||||
|
||||
signals:
|
||||
signals:
|
||||
void ExitFinished();
|
||||
void ImageLoaded(const quint64 id, const QUrl &cover_url, const QImage &image);
|
||||
void ImageLoaded(const quint64 id, const QUrl &cover_url, const QImage &scaled, const QImage &original);
|
||||
|
||||
protected slots:
|
||||
void Exit();
|
||||
void ProcessTasks();
|
||||
void RemoteFetchFinished(QNetworkReply *reply, const QUrl &cover_url);
|
||||
|
||||
@ -128,6 +132,8 @@ signals:
|
||||
bool cover_lowercase_;
|
||||
bool cover_replace_spaces_;
|
||||
|
||||
QThread *original_thread_;
|
||||
|
||||
};
|
||||
|
||||
#endif // ALBUMCOVERLOADER_H
|
||||
|
@ -86,7 +86,6 @@ void InternetServices::Exit() {
|
||||
void InternetServices::ExitReceived() {
|
||||
|
||||
InternetService *service = qobject_cast<InternetService*>(sender());
|
||||
|
||||
wait_for_exit_.removeAll(service);
|
||||
if (wait_for_exit_.isEmpty()) emit ExitFinished();
|
||||
|
||||
|
@ -180,9 +180,9 @@ QobuzService::~QobuzService() {
|
||||
stream_url_req->deleteLater();
|
||||
}
|
||||
|
||||
delete artists_collection_backend_;
|
||||
delete albums_collection_backend_;
|
||||
delete songs_collection_backend_;
|
||||
artists_collection_backend_->deleteLater();
|
||||
albums_collection_backend_->deleteLater();
|
||||
songs_collection_backend_->deleteLater();
|
||||
|
||||
}
|
||||
|
||||
@ -202,8 +202,10 @@ void QobuzService::Exit() {
|
||||
|
||||
void QobuzService::ExitReceived() {
|
||||
|
||||
disconnect(sender(), 0, this, 0);
|
||||
wait_for_exit_.removeAll(sender());
|
||||
QObject *obj = static_cast<QObject*>(sender());
|
||||
disconnect(obj, 0, this, 0);
|
||||
qLog(Debug) << obj << "successfully exited.";
|
||||
wait_for_exit_.removeAll(obj);
|
||||
if (wait_for_exit_.isEmpty()) emit ExitFinished();
|
||||
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ SubsonicService::SubsonicService(Application *app, QObject *parent)
|
||||
}
|
||||
|
||||
SubsonicService::~SubsonicService() {
|
||||
delete collection_backend_;
|
||||
collection_backend_->deleteLater();
|
||||
}
|
||||
|
||||
void SubsonicService::Exit() {
|
||||
|
@ -186,9 +186,9 @@ TidalService::~TidalService() {
|
||||
stream_url_req->deleteLater();
|
||||
}
|
||||
|
||||
delete artists_collection_backend_;
|
||||
delete albums_collection_backend_;
|
||||
delete songs_collection_backend_;
|
||||
artists_collection_backend_->deleteLater();
|
||||
albums_collection_backend_->deleteLater();
|
||||
songs_collection_backend_->deleteLater();
|
||||
|
||||
}
|
||||
|
||||
@ -208,8 +208,10 @@ void TidalService::Exit() {
|
||||
|
||||
void TidalService::ExitReceived() {
|
||||
|
||||
disconnect(sender(), 0, this, 0);
|
||||
wait_for_exit_.removeAll(sender());
|
||||
QObject *obj = static_cast<QObject*>(sender());
|
||||
disconnect(obj, 0, this, 0);
|
||||
qLog(Debug) << obj << "successfully exited.";
|
||||
wait_for_exit_.removeAll(obj);
|
||||
if (wait_for_exit_.isEmpty()) emit ExitFinished();
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user