From ecebf75b887e6d3865883f897363aef0c98014a9 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 6 Jul 2018 00:34:16 -0700 Subject: [PATCH] Implement manually adding PCs --- app/backend/computermanager.cpp | 56 ++----------------- app/backend/computermanager.h | 95 ++++++++++++++++++++++++++++++++- app/gui/AppView.qml | 10 ++++ app/gui/PcView.qml | 23 +++++--- app/gui/computermodel.cpp | 7 +++ app/gui/computermodel.h | 2 + 6 files changed, 135 insertions(+), 58 deletions(-) diff --git a/app/backend/computermanager.cpp b/app/backend/computermanager.cpp index f430669f..6b89d036 100644 --- a/app/backend/computermanager.cpp +++ b/app/backend/computermanager.cpp @@ -421,58 +421,12 @@ void ComputerManager::stopPollingAsync() } } -bool ComputerManager::addNewHost(QString address, bool mdns) +void ComputerManager::addNewHost(QString address, bool mdns) { - NvHTTP http(address); - - QString serverInfo; - try { - serverInfo = http.getServerInfo(); - } catch (...) { - return false; - } - - NvComputer* newComputer = new NvComputer(address, serverInfo); - - // Update addresses depending on the context - if (mdns) { - newComputer->localAddress = address; - } - else { - newComputer->manualAddress = address; - } - - // Check if this PC already exists - QWriteLocker lock(&m_Lock); - NvComputer* existingComputer = m_KnownHosts[newComputer->uuid]; - if (existingComputer != nullptr) { - // Fold it into the existing PC - bool changed = existingComputer->update(*newComputer); - delete newComputer; - - // Drop the lock before notifying - lock.unlock(); - - // Tell our client if something changed - if (changed) { - handleComputerStateChanged(existingComputer); - } - } - else { - // Store this in our active sets - m_KnownHosts[newComputer->uuid] = newComputer; - - // Start polling if enabled (write lock required) - startPollingComputer(newComputer); - - // Drop the lock before notifying - lock.unlock(); - - // Tell our client about this new PC - handleComputerStateChanged(newComputer); - } - - return true; + // Punt to a worker thread to avoid stalling the + // UI while waiting for serverinfo query to complete + PendingAddTask* addTask = new PendingAddTask(this, address, mdns); + QThreadPool::globalInstance()->start(addTask); } void diff --git a/app/backend/computermanager.h b/app/backend/computermanager.h index 388ae258..359073d4 100644 --- a/app/backend/computermanager.h +++ b/app/backend/computermanager.h @@ -242,6 +242,7 @@ class ComputerManager : public QObject Q_OBJECT friend class DeferredHostDeletionTask; + friend class PendingAddTask; public: explicit ComputerManager(QObject *parent = nullptr); @@ -250,7 +251,7 @@ public: Q_INVOKABLE void stopPollingAsync(); - Q_INVOKABLE bool addNewHost(QString address, bool mdns); + Q_INVOKABLE void addNewHost(QString address, bool mdns); void pairHost(NvComputer* computer, QString pin); @@ -264,6 +265,8 @@ signals: void pairingCompleted(NvComputer* computer, QString error); + void computerAddCompleted(QVariant success); + private slots: void handleComputerStateChanged(NvComputer* computer); @@ -334,3 +337,93 @@ private: NvComputer* m_Computer; QString m_Pin; }; + +class PendingAddTask : public QObject, public QRunnable +{ + Q_OBJECT + +public: + PendingAddTask(ComputerManager* computerManager, QString address, bool mdns) + : m_ComputerManager(computerManager), + m_Address(address), + m_Mdns(mdns) + { + connect(this, &PendingAddTask::computerAddCompleted, + computerManager, &ComputerManager::computerAddCompleted); + connect(this, &PendingAddTask::computerStateChanged, + computerManager, &ComputerManager::handleComputerStateChanged); + } + +signals: + void computerAddCompleted(QVariant success); + + void computerStateChanged(NvComputer* computer); + +private: + void run() + { + NvHTTP http(m_Address); + + QString serverInfo; + try { + serverInfo = http.getServerInfo(); + } catch (...) { + emit computerAddCompleted(false); + return; + } + + NvComputer* newComputer = new NvComputer(m_Address, serverInfo); + + // Update addresses depending on the context + if (m_Mdns) { + newComputer->localAddress = m_Address; + } + else { + newComputer->manualAddress = m_Address; + } + + // Check if this PC already exists + QWriteLocker lock(&m_ComputerManager->m_Lock); + NvComputer* existingComputer = m_ComputerManager->m_KnownHosts[newComputer->uuid]; + if (existingComputer != nullptr) { + // Fold it into the existing PC + bool changed = existingComputer->update(*newComputer); + delete newComputer; + + // Drop the lock before notifying + lock.unlock(); + + // For non-mDNS clients, let them know it succeeded + if (!m_Mdns) { + emit computerAddCompleted(true); + } + + // Tell our client if something changed + if (changed) { + emit computerStateChanged(existingComputer); + } + } + else { + // Store this in our active sets + m_ComputerManager->m_KnownHosts[newComputer->uuid] = newComputer; + + // Start polling if enabled (write lock required) + m_ComputerManager->startPollingComputer(newComputer); + + // Drop the lock before notifying + lock.unlock(); + + // For non-mDNS clients, let them know it succeeded + if (!m_Mdns) { + emit computerAddCompleted(true); + } + + // Tell our client about this new PC + emit computerStateChanged(newComputer); + } + } + + ComputerManager* m_ComputerManager; + QString m_Address; + bool m_Mdns; +}; diff --git a/app/gui/AppView.qml b/app/gui/AppView.qml index 9abd7b53..70c73d5e 100644 --- a/app/gui/AppView.qml +++ b/app/gui/AppView.qml @@ -16,6 +16,16 @@ GridView { cellWidth: 225; cellHeight: 350; focus: true + Component.onCompleted: { + // Start polling when this view is shown + ComputerManager.startPolling() + } + + Component.onDestruction: { + // Stop polling when this view is destroyed + ComputerManager.stopPollingAsync() + } + function createModel() { var model = Qt.createQmlObject('import AppModel 1.0; AppModel {}', parent, '') diff --git a/app/gui/PcView.qml b/app/gui/PcView.qml index 0bdfc435..f4088b81 100644 --- a/app/gui/PcView.qml +++ b/app/gui/PcView.qml @@ -21,6 +21,9 @@ GridView { Component.onCompleted: { // Start polling when this view is shown ComputerManager.startPolling() + + // Setup signals on CM + ComputerManager.computerAddCompleted.connect(addComplete) } Component.onDestruction: { @@ -38,8 +41,16 @@ GridView { // Display a failed dialog if we got an error if (error !== null) { - pairingFailedDialog.text = error - pairingFailedDialog.open() + errorDialog.text = error + errorDialog.open() + } + } + + function addComplete(success) + { + if (!success) { + errorDialog.text = "Unable to connect to the specified PC. Ensure GameStream is enabled in GeForce Experience." + errorDialog.open() } } @@ -145,8 +156,8 @@ GridView { } else { // cannot pair while something is streaming or attempting to pair - pairingFailedDialog.text = "This PC is currently busy. Make sure to quit any running games and try again." - pairingFailedDialog.open() + errorDialog.text = "This PC is currently busy. Make sure to quit any running games and try again." + errorDialog.open() } } } @@ -158,7 +169,7 @@ GridView { } MessageDialog { - id: pairingFailedDialog + id: errorDialog // don't allow edits to the rest of the window while open modality:Qt.WindowModal icon: StandardIcon.Critical @@ -189,7 +200,7 @@ GridView { editTextItem.selectAll() } onAccepted: { - console.log("accepted, with value: " + editText.text) + ComputerManager.addNewHost(editText.text, false) } ColumnLayout { diff --git a/app/gui/computermodel.cpp b/app/gui/computermodel.cpp index 09689621..7c5202d7 100644 --- a/app/gui/computermodel.cpp +++ b/app/gui/computermodel.cpp @@ -93,6 +93,13 @@ void ComputerModel::deleteComputer(int computerIndex) endRemoveRows(); } +bool ComputerModel::wakeComputer(int computerIndex) +{ + Q_ASSERT(computerIndex < m_Computers.count()); + + return m_Computers[computerIndex]->wake(); +} + void ComputerModel::pairComputer(int computerIndex, QString pin) { Q_ASSERT(computerIndex < m_Computers.count()); diff --git a/app/gui/computermodel.h b/app/gui/computermodel.h index a173dd17..d1db61dd 100644 --- a/app/gui/computermodel.h +++ b/app/gui/computermodel.h @@ -31,6 +31,8 @@ public: Q_INVOKABLE void pairComputer(int computerIndex, QString pin); + Q_INVOKABLE bool wakeComputer(int computerIndex); + signals: void pairingCompleted(QVariant error);