From c1f663cec13bc10a3fa211bb9420e5be87e9e362 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 24 Aug 2022 17:31:22 -0500 Subject: [PATCH] Add missing files from previous commit --- app/cli/pair.cpp | 186 +++++++++++++++++++++++++++++++++++++++++++++++ app/cli/pair.h | 44 +++++++++++ 2 files changed, 230 insertions(+) create mode 100644 app/cli/pair.cpp create mode 100644 app/cli/pair.h diff --git a/app/cli/pair.cpp b/app/cli/pair.cpp new file mode 100644 index 00000000..ebf10101 --- /dev/null +++ b/app/cli/pair.cpp @@ -0,0 +1,186 @@ +#include "pair.h" + +#include "backend/computermanager.h" +#include "backend/computerseeker.h" +#include +#include + +#define COMPUTER_SEEK_TIMEOUT 10000 + +namespace CliPair +{ + +enum State { + StateInit, + StateSeekComputer, + StatePairing, + StateFailure, + StateComplete, +}; + +class Event +{ +public: + enum Type { + ComputerFound, + Executed, + PairingCompleted, + Timedout, + }; + + Event(Type type) + : type(type), computerManager(nullptr), computer(nullptr) {} + + Type type; + ComputerManager *computerManager; + NvComputer *computer; + QString errorMessage; +}; + +class LauncherPrivate +{ + Q_DECLARE_PUBLIC(Launcher) + +public: + LauncherPrivate(Launcher *q) : q_ptr(q) {} + + void handleEvent(Event event) + { + Q_Q(Launcher); + + switch (event.type) { + // Occurs when CliPair becomes visible and the UI calls launcher's execute() + case Event::Executed: + if (m_State == StateInit) { + m_State = StateSeekComputer; + m_ComputerManager = event.computerManager; + q->connect(m_ComputerManager, &ComputerManager::pairingCompleted, + q, &Launcher::onPairingCompleted); + + // If we weren't provided a predefined PIN, generate one now + if (m_PredefinedPin.isEmpty()) { + m_PredefinedPin = m_ComputerManager->generatePinString(); + } + + m_ComputerSeeker = new ComputerSeeker(m_ComputerManager, m_ComputerName, q); + q->connect(m_ComputerSeeker, &ComputerSeeker::computerFound, + q, &Launcher::onComputerFound); + q->connect(m_ComputerSeeker, &ComputerSeeker::errorTimeout, + q, &Launcher::onTimeout); + m_ComputerSeeker->start(COMPUTER_SEEK_TIMEOUT); + + emit q->searchingComputer(); + } + break; + // Occurs when searched computer is found + case Event::ComputerFound: + if (m_State == StateSeekComputer) { + if (event.computer->pairState == NvComputer::PS_PAIRED) { + m_State = StateFailure; + QString msg = QObject::tr("%1 is already paired").arg(event.computer->name); + emit q->failed(msg); + } + else if (event.computer->currentGameId != 0) { + m_State = StateFailure; + QString msg = QObject::tr("You cannot pair while a previous session is still running on the host PC. Quit any running games or reboot the host PC, then try pairing again."); + emit q->failed(msg); + } + else { + Q_ASSERT(!m_PredefinedPin.isEmpty()); + + m_State = StatePairing; + m_ComputerManager->pairHost(event.computer, m_PredefinedPin); + emit q->pairing(event.computer->name, m_PredefinedPin); + } + } + break; + // Occurs when pairing operation completes + case Event::PairingCompleted: + if (m_State == StatePairing) { + if (event.errorMessage.isEmpty()) { + m_State = StateComplete; + emit q->success(); + } + else { + m_State = StateFailure; + emit q->failed(event.errorMessage); + } + } + break; + // Occurs when computer search timed out + case Event::Timedout: + if (m_State == StateSeekComputer) { + m_State = StateFailure; + emit q->failed(QObject::tr("Failed to connect to %1").arg(m_ComputerName)); + } + break; + } + } + + Launcher *q_ptr; + QString m_ComputerName; + QString m_PredefinedPin; + ComputerManager *m_ComputerManager; + ComputerSeeker *m_ComputerSeeker; + NvComputer *m_Computer; + State m_State; + QTimer *m_TimeoutTimer; +}; + +Launcher::Launcher(QString computer, QString predefinedPin, QObject *parent) + : QObject(parent), + m_DPtr(new LauncherPrivate(this)) +{ + Q_D(Launcher); + d->m_ComputerName = computer; + d->m_PredefinedPin = predefinedPin; + d->m_State = StateInit; + d->m_TimeoutTimer = new QTimer(this); + d->m_TimeoutTimer->setSingleShot(true); + connect(d->m_TimeoutTimer, &QTimer::timeout, + this, &Launcher::onTimeout); +} + +Launcher::~Launcher() +{ +} + +void Launcher::execute(ComputerManager *manager) +{ + Q_D(Launcher); + Event event(Event::Executed); + event.computerManager = manager; + d->handleEvent(event); +} + +bool Launcher::isExecuted() const +{ + Q_D(const Launcher); + return d->m_State != StateInit; +} + +void Launcher::onComputerFound(NvComputer *computer) +{ + Q_D(Launcher); + Event event(Event::ComputerFound); + event.computer = computer; + d->handleEvent(event); +} + +void Launcher::onTimeout() +{ + Q_D(Launcher); + Event event(Event::Timedout); + d->handleEvent(event); +} + +void Launcher::onPairingCompleted(NvComputer* computer, QString error) +{ + Q_D(Launcher); + Event event(Event::PairingCompleted); + event.computer = computer; + event.errorMessage = error; + d->handleEvent(event); +} + +} diff --git a/app/cli/pair.h b/app/cli/pair.h new file mode 100644 index 00000000..df201914 --- /dev/null +++ b/app/cli/pair.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +class ComputerManager; +class NvComputer; +class Session; +class StreamingPreferences; + +namespace CliPair +{ + +class Event; +class LauncherPrivate; + +class Launcher : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE_D(m_DPtr, Launcher) + +public: + explicit Launcher(QString computer, QString predefinedPin, + QObject *parent = nullptr); + ~Launcher(); + Q_INVOKABLE void execute(ComputerManager *manager); + Q_INVOKABLE bool isExecuted() const; + +signals: + void searchingComputer(); + void pairing(QString pcName, QString pin); + void failed(QString text); + void success(); + +private slots: + void onComputerFound(NvComputer *computer); + void onPairingCompleted(NvComputer *computer, QString error); + void onTimeout(); + +private: + QScopedPointer m_DPtr; +}; + +}