feat: single app with local socket

This commit is contained in:
Gary Wang 2020-04-11 19:54:51 +08:00
parent 099284d5d4
commit 14d20fd925
6 changed files with 147 additions and 20 deletions

View File

@ -25,6 +25,8 @@ add_executable(${EXE_NAME}
seekableslider.h
playlistmodel.h
playlistmodel.cpp
singleapplicationmanager.h
singleapplicationmanager.cpp
mainwindow.ui
resources.qrc

View File

@ -1,8 +1,11 @@
#include "mainwindow.h"
#include "singleapplicationmanager.h"
#include <QApplication>
#include <QCommandLineParser>
#include <QUrl>
#include <QDebug>
int main(int argc, char *argv[])
{
@ -16,20 +19,22 @@ int main(int argc, char *argv[])
parser.process(a);
QStringList urlStrList = parser.positionalArguments();
QList<QUrl> 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();
}

View File

@ -40,13 +40,15 @@ MainWindow::~MainWindow()
delete ui;
}
void MainWindow::commandlinePlayAudioFiles(QList<QUrl> audioFiles)
void MainWindow::commandlinePlayAudioFiles(QStringList audioFiles)
{
if (!audioFiles.isEmpty()) {
if (audioFiles.count() == 1) {
loadPlaylistBySingleLocalFile(audioFiles.first().toLocalFile());
QList<QUrl> 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<QUrl> 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<QUrl> MainWindow::strlst2urllst(QStringList strlst)
{
QList<QUrl> 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()) {

View File

@ -2,6 +2,7 @@
#define MAINWINDOW_H
#include <QMainWindow>
#include <QVariant>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
@ -20,9 +21,12 @@ public:
MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
void commandlinePlayAudioFiles(QList<QUrl> 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<QUrl> strlst2urllst(QStringList strlst);
};
#endif // MAINWINDOW_H

View File

@ -0,0 +1,57 @@
#include "singleapplicationmanager.h"
#include <QDataStream>
#include <QLocalServer>
#include <QLocalSocket>
SingleApplicationManager::SingleApplicationManager(QString applicationKey, QObject *parent)
: QObject(parent)
, m_applicationKey(applicationKey)
{
}
void SingleApplicationManager::on_localSocket_newConnection()
{
QScopedPointer<QLocalSocket> 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;
}

View File

@ -0,0 +1,32 @@
#ifndef SINGLEAPPLICATIONMANAGER_H
#define SINGLEAPPLICATIONMANAGER_H
#include <QObject>
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