From 14d20fd9255a11fec0fee2032d8c1fa4a9508d81 Mon Sep 17 00:00:00 2001 From: Gary Wang Date: Sat, 11 Apr 2020 19:54:51 +0800 Subject: [PATCH] feat: single app with local socket --- CMakeLists.txt | 2 ++ main.cpp | 21 ++++++++----- mainwindow.cpp | 46 +++++++++++++++++++++++------ mainwindow.h | 9 ++++-- singleapplicationmanager.cpp | 57 ++++++++++++++++++++++++++++++++++++ singleapplicationmanager.h | 32 ++++++++++++++++++++ 6 files changed, 147 insertions(+), 20 deletions(-) create mode 100644 singleapplicationmanager.cpp create mode 100644 singleapplicationmanager.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ffabb3..a344fb2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,8 @@ add_executable(${EXE_NAME} seekableslider.h playlistmodel.h playlistmodel.cpp + singleapplicationmanager.h + singleapplicationmanager.cpp mainwindow.ui resources.qrc diff --git a/main.cpp b/main.cpp index 547b926..cded6bc 100644 --- a/main.cpp +++ b/main.cpp @@ -1,8 +1,11 @@ #include "mainwindow.h" +#include "singleapplicationmanager.h" + #include #include #include +#include int main(int argc, char *argv[]) { @@ -16,20 +19,22 @@ int main(int argc, char *argv[]) parser.process(a); QStringList urlStrList = parser.positionalArguments(); - QList urlList; - for (const QString & str : urlStrList) { - QUrl url = QUrl::fromLocalFile(str); - if (url.isValid()) { - urlList.append(url); - } + + SingleApplicationManager sam("_pineapple_music_owo_"); + if (sam.checkSingleInstance(QVariant::fromValue(urlStrList))) { + return 0; + } else { + sam.createSingleInstance(); } MainWindow w; w.show(); - if (!urlList.isEmpty()) { - w.commandlinePlayAudioFiles(urlList); + if (!urlStrList.isEmpty()) { + w.commandlinePlayAudioFiles(urlStrList); } + QObject::connect(&sam, &SingleApplicationManager::dataReached, &w, &MainWindow::localSocketPlayAudioFiles); + return a.exec(); } diff --git a/mainwindow.cpp b/mainwindow.cpp index e7c557e..fe2a9c4 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -40,13 +40,15 @@ MainWindow::~MainWindow() delete ui; } -void MainWindow::commandlinePlayAudioFiles(QList audioFiles) +void MainWindow::commandlinePlayAudioFiles(QStringList audioFiles) { - if (!audioFiles.isEmpty()) { - if (audioFiles.count() == 1) { - loadPlaylistBySingleLocalFile(audioFiles.first().toLocalFile()); + QList audioFileUrls = strlst2urllst(audioFiles); + + if (!audioFileUrls.isEmpty()) { + if (audioFileUrls.count() == 1) { + loadPlaylistBySingleLocalFile(audioFileUrls.first().toLocalFile()); } else { - createPlaylist(audioFiles); + createPlaylist(audioFileUrls); } m_mediaPlayer->play(); } @@ -79,6 +81,17 @@ void MainWindow::loadPlaylistBySingleLocalFile(const QString &path) playlist->setCurrentIndex(currentFileIndex); } +void MainWindow::localSocketPlayAudioFiles(QVariant audioFilesVariant) +{ + QStringList urlStrList = audioFilesVariant.toStringList(); + qDebug() << urlStrList << "MainWindow::localSocketPlayAudioFiles"; + commandlinePlayAudioFiles(urlStrList); + + showNormal(); + activateWindow(); + raise(); +} + void MainWindow::closeEvent(QCloseEvent *) { qApp->exit(); @@ -172,12 +185,14 @@ void MainWindow::loadFile() */ QMediaPlaylist *MainWindow::createPlaylist(QList urlList) { - if (m_mediaPlayer->playlist()) { - m_mediaPlayer->playlist()->disconnect(); - } - + QMediaPlaylist * oldPlaylist = m_mediaPlayer->playlist(); QMediaPlaylist * playlist = new QMediaPlaylist(m_mediaPlayer); + if (oldPlaylist) { + oldPlaylist->disconnect(); + oldPlaylist->deleteLater(); + } + for (const QUrl & url : urlList) { bool succ = playlist->addMedia(QMediaContent(url)); if (!succ) { @@ -253,6 +268,19 @@ QString MainWindow::ms2str(qint64 ms) } } +QList MainWindow::strlst2urllst(QStringList strlst) +{ + QList urlList; + for (const QString & str : strlst) { + QUrl url = QUrl::fromLocalFile(str); + if (url.isValid()) { + urlList.append(url); + } + } + + return urlList; +} + void MainWindow::on_volumeSlider_valueChanged(int value) { if (m_mediaPlayer->isMuted()) { diff --git a/mainwindow.h b/mainwindow.h index 4bb41ff..3f87c2b 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -2,6 +2,7 @@ #define MAINWINDOW_H #include +#include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } @@ -20,9 +21,12 @@ public: MainWindow(QWidget *parent = nullptr); ~MainWindow() override; - void commandlinePlayAudioFiles(QList audioFiles); + void commandlinePlayAudioFiles(QStringList audioFiles); void loadPlaylistBySingleLocalFile(const QString &path); +public slots: + void localSocketPlayAudioFiles(QVariant audioFilesVariant); + protected: void closeEvent(QCloseEvent *) override; void paintEvent(QPaintEvent *e) override; @@ -38,8 +42,6 @@ protected: private slots: void on_playbackModeBtn_clicked(); - -private slots: void on_closeWindowBtn_clicked(); void on_playBtn_clicked(); void on_volumeSlider_valueChanged(int value); @@ -66,5 +68,6 @@ private: void initConnections(); static QString ms2str(qint64 ms); + static QList strlst2urllst(QStringList strlst); }; #endif // MAINWINDOW_H diff --git a/singleapplicationmanager.cpp b/singleapplicationmanager.cpp new file mode 100644 index 0000000..d1c5c10 --- /dev/null +++ b/singleapplicationmanager.cpp @@ -0,0 +1,57 @@ +#include "singleapplicationmanager.h" + +#include +#include +#include + +SingleApplicationManager::SingleApplicationManager(QString applicationKey, QObject *parent) + : QObject(parent) + , m_applicationKey(applicationKey) +{ + +} + +void SingleApplicationManager::on_localSocket_newConnection() +{ + QScopedPointer socket(m_localServer->nextPendingConnection()); + if (socket) { + socket->waitForReadyRead(500); + QDataStream dataStream(socket.data()); + QVariant data; + dataStream.startTransaction(); + dataStream >> data; + dataStream.commitTransaction(); + emit dataReached(data); + } +} + +void SingleApplicationManager::createSingleInstance() +{ + m_localServer = new QLocalServer(this); + + connect(m_localServer, &QLocalServer::newConnection, this, &SingleApplicationManager::on_localSocket_newConnection); + + if (!m_localServer->listen(m_applicationKey)) { + if (m_localServer->serverError() == QAbstractSocket::AddressInUseError) { + QLocalServer::removeServer(m_applicationKey); + m_localServer->listen(m_applicationKey); + } + } +} + +bool SingleApplicationManager::checkSingleInstance(QVariant data) +{ + QLocalSocket socket; + socket.connectToServer(m_applicationKey); + if (socket.waitForConnected(500)) { + QDataStream dataStream(&socket); + dataStream << data; + + socket.waitForBytesWritten(); + socket.close(); + + return true; + } + + return false; +} diff --git a/singleapplicationmanager.h b/singleapplicationmanager.h new file mode 100644 index 0000000..3fdb17c --- /dev/null +++ b/singleapplicationmanager.h @@ -0,0 +1,32 @@ +#ifndef SINGLEAPPLICATIONMANAGER_H +#define SINGLEAPPLICATIONMANAGER_H + +#include + +QT_BEGIN_NAMESPACE +class QLocalServer; +QT_END_NAMESPACE + +class SingleApplicationManager : public QObject +{ + Q_OBJECT +public: + explicit SingleApplicationManager(QString applicationKey, QObject *parent = nullptr); + + void createSingleInstance(); + bool checkSingleInstance(QVariant data); + +signals: + void dataReached(QVariant data); + +private slots: + void on_localSocket_newConnection(); + +private: + + QString m_applicationKey; + QLocalServer * m_localServer; + +}; + +#endif // SINGLEAPPLICATIONMANAGER_H