diff --git a/app/backend/computermanager.cpp b/app/backend/computermanager.cpp index 9cc83ced..c3cc9996 100644 --- a/app/backend/computermanager.cpp +++ b/app/backend/computermanager.cpp @@ -446,6 +446,15 @@ void ComputerManager::pairHost(NvComputer* computer, QString pin) QThreadPool::globalInstance()->start(pairing); } +void ComputerManager::quitRunningApp(NvComputer* computer) +{ + QWriteLocker lock(&computer->lock); + computer->pendingQuit = true; + + PendingQuitTask* quit = new PendingQuitTask(this, computer); + QThreadPool::globalInstance()->start(quit); +} + void ComputerManager::stopPollingAsync() { QWriteLocker lock(&m_Lock); @@ -497,6 +506,11 @@ ComputerManager::handleComputerStateChanged(NvComputer* computer) { emit computerStateChanged(computer); + if (computer->pendingQuit && computer->currentGameId == 0) { + computer->pendingQuit = false; + emit quitAppCompleted(nullptr); + } + // Save updated hosts to QSettings saveHosts(); } diff --git a/app/backend/computermanager.h b/app/backend/computermanager.h index ad668eea..06aae502 100644 --- a/app/backend/computermanager.h +++ b/app/backend/computermanager.h @@ -16,10 +16,14 @@ class NvComputer { friend class PcMonitorThread; + friend class ComputerManager; + friend class PendingQuitTask; private: void sortAppList(); + bool pendingQuit; + public: explicit NvComputer(QString address, QString serverInfo); @@ -254,6 +258,8 @@ public: void pairHost(NvComputer* computer, QString pin); + void quitRunningApp(NvComputer* computer); + QVector getComputers(); // computer is deleted inside this call @@ -266,6 +272,8 @@ signals: void computerAddCompleted(QVariant success); + void quitAppCompleted(QString error); + private slots: void handleComputerStateChanged(NvComputer* computer); @@ -333,6 +341,51 @@ private: QString m_Pin; }; +class PendingQuitTask : public QObject, public QRunnable +{ + Q_OBJECT + +public: + PendingQuitTask(ComputerManager* computerManager, NvComputer* computer) + : m_Computer(computer) + { + connect(this, &PendingQuitTask::quitAppFailed, + computerManager, &ComputerManager::quitAppCompleted); + } + +signals: + void quitAppFailed(QString error); + +private: + void run() + { + NvHTTP http(m_Computer->activeAddress); + + try { + if (m_Computer->currentGameId != 0) { + http.quitApp(); + + if (http.getCurrentGame(http.getServerInfo()) != 0) { + { + QWriteLocker lock(&m_Computer->lock); + m_Computer->pendingQuit = false; + } + emit quitAppFailed("Unable to quit game that wasn't started by this computer. " + "You must quit the game on the host PC manually or use the device that originally started the game."); + } + } + } catch (const GfeHttpResponseException& e) { + { + QWriteLocker lock(&m_Computer->lock); + m_Computer->pendingQuit = false; + } + emit quitAppFailed(e.toQString()); + } + } + + NvComputer* m_Computer; +}; + class PendingAddTask : public QObject, public QRunnable { Q_OBJECT diff --git a/app/gui/appmodel.cpp b/app/gui/appmodel.cpp index 491068df..ba951b74 100644 --- a/app/gui/appmodel.cpp +++ b/app/gui/appmodel.cpp @@ -19,6 +19,32 @@ void AppModel::initialize(ComputerManager* computerManager, int computerIndex) m_CurrentGameId = m_Computer->currentGameId; } +int AppModel::getRunningAppIndex() +{ + if (m_CurrentGameId != 0) { + for (int i = 0; i < m_Apps.count(); i++) { + if (m_Apps[i].id == m_CurrentGameId) { + return i; + } + } + } + + return -1; +} + +QString AppModel::getRunningAppName() +{ + if (m_CurrentGameId != 0) { + for (int i = 0; i < m_Apps.count(); i++) { + if (m_Apps[i].id == m_CurrentGameId) { + return m_Apps[i].name; + } + } + } + + return nullptr; +} + Session* AppModel::createSessionForApp(int appIndex) { Q_ASSERT(appIndex < m_Apps.count()); @@ -70,6 +96,11 @@ QHash AppModel::roleNames() const return names; } +void AppModel::quitRunningApp() +{ + m_ComputerManager->quitRunningApp(m_Computer); +} + void AppModel::handleComputerStateChanged(NvComputer* computer) { // Ignore updates for computers that aren't ours diff --git a/app/gui/appmodel.h b/app/gui/appmodel.h index 87e9bcce..07e94126 100644 --- a/app/gui/appmodel.h +++ b/app/gui/appmodel.h @@ -25,6 +25,12 @@ public: Q_INVOKABLE Session* createSessionForApp(int appIndex); + Q_INVOKABLE int getRunningAppIndex(); + + Q_INVOKABLE QString getRunningAppName(); + + Q_INVOKABLE void quitRunningApp(); + QVariant data(const QModelIndex &index, int role) const override; int rowCount(const QModelIndex &parent) const override;