mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-02 07:46:07 +00:00
Simplify app quitting implementation a bit
This commit is contained in:
parent
2eee839eaa
commit
5029c855f0
@ -1,7 +1,6 @@
|
|||||||
#include "computermanager.h"
|
#include "computermanager.h"
|
||||||
#include "nvhttp.h"
|
#include "nvhttp.h"
|
||||||
#include "settings/streamingpreferences.h"
|
#include "settings/streamingpreferences.h"
|
||||||
#include "streaming/session.h"
|
|
||||||
|
|
||||||
#include <Limelight.h>
|
#include <Limelight.h>
|
||||||
#include <QtEndian>
|
#include <QtEndian>
|
||||||
@ -479,11 +478,6 @@ void ComputerManager::quitRunningApp(NvComputer* computer)
|
|||||||
QThreadPool::globalInstance()->start(quit);
|
QThreadPool::globalInstance()->start(quit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComputerManager::quitRunningApp(Session *session)
|
|
||||||
{
|
|
||||||
quitRunningApp(session->getComputer());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComputerManager::stopPollingAsync()
|
void ComputerManager::stopPollingAsync()
|
||||||
{
|
{
|
||||||
QWriteLocker lock(&m_Lock);
|
QWriteLocker lock(&m_Lock);
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QRunnable>
|
#include <QRunnable>
|
||||||
|
|
||||||
class Session;
|
|
||||||
|
|
||||||
class MdnsPendingComputer : public QObject
|
class MdnsPendingComputer : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -74,7 +72,6 @@ public:
|
|||||||
void pairHost(NvComputer* computer, QString pin);
|
void pairHost(NvComputer* computer, QString pin);
|
||||||
|
|
||||||
void quitRunningApp(NvComputer* computer);
|
void quitRunningApp(NvComputer* computer);
|
||||||
Q_INVOKABLE void quitRunningApp(Session* session);
|
|
||||||
|
|
||||||
QVector<NvComputer*> getComputers();
|
QVector<NvComputer*> getComputers();
|
||||||
|
|
||||||
|
@ -57,13 +57,8 @@ NvHTTP::getCurrentGame(QString serverInfo)
|
|||||||
// GFE 2.8 started keeping currentgame set to the last game played. As a result, it no longer
|
// GFE 2.8 started keeping currentgame set to the last game played. As a result, it no longer
|
||||||
// has the semantics that its name would indicate. To contain the effects of this change as much
|
// has the semantics that its name would indicate. To contain the effects of this change as much
|
||||||
// as possible, we'll force the current game to zero if the server isn't in a streaming session.
|
// as possible, we'll force the current game to zero if the server isn't in a streaming session.
|
||||||
//
|
|
||||||
// However, current game info must be available also in other states than just _SERVER_BUSY as
|
|
||||||
// it is required for quitting currently running app. Quitting app occurs at end of stream if
|
|
||||||
// configured so. At that point the server state may be in some other state than _SERVER_BUSY
|
|
||||||
// for a short while, but that must not prevent quitting of the app.
|
|
||||||
QString serverState = getXmlString(serverInfo, "state");
|
QString serverState = getXmlString(serverInfo, "state");
|
||||||
if (serverState != nullptr && !serverState.endsWith("_SERVER_AVAILABLE"))
|
if (serverState != nullptr && serverState.endsWith("_SERVER_BUSY"))
|
||||||
{
|
{
|
||||||
return getXmlString(serverInfo, "currentgame").toInt();
|
return getXmlString(serverInfo, "currentgame").toInt();
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ Item {
|
|||||||
property string appName
|
property string appName
|
||||||
property string stageText : "Starting " + appName + "..."
|
property string stageText : "Starting " + appName + "..."
|
||||||
property bool quitAfter : false
|
property bool quitAfter : false
|
||||||
property bool sessionLaunched : false
|
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
@ -61,17 +60,27 @@ Item {
|
|||||||
toast.visible = true
|
toast.visible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamingFinished() {
|
function quitStarting()
|
||||||
|
{
|
||||||
|
// Avoid the push transition animation
|
||||||
|
var component = Qt.createComponent("QuitSegue.qml")
|
||||||
|
stackView.replace(stackView.currentItem, component.createObject(stackView, {"appName": appName}), StackView.Immediate)
|
||||||
|
|
||||||
|
// Show the Qt window again to show quit segue
|
||||||
|
window.visible = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function sessionFinished()
|
||||||
|
{
|
||||||
if (quitAfter) {
|
if (quitAfter) {
|
||||||
window.visible = false
|
|
||||||
Qt.quit()
|
Qt.quit()
|
||||||
} else {
|
} else {
|
||||||
// Show the Qt window again after streaming
|
|
||||||
window.visible = true
|
|
||||||
|
|
||||||
// Exit this view
|
// Exit this view
|
||||||
stackView.pop()
|
stackView.pop()
|
||||||
|
|
||||||
|
// Show the Qt window again after streaming
|
||||||
|
window.visible = true
|
||||||
|
|
||||||
// Display any launch errors. We do this after
|
// Display any launch errors. We do this after
|
||||||
// the Qt UI is visible again to prevent losing
|
// the Qt UI is visible again to prevent losing
|
||||||
// focus on the dialog which would impact gamepad
|
// focus on the dialog which would impact gamepad
|
||||||
@ -91,12 +100,6 @@ Item {
|
|||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
// Prevent session restart after execution returns from QuitSegue
|
|
||||||
if (sessionLaunched) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sessionLaunched = true
|
|
||||||
|
|
||||||
// Hide the toolbar before we start loading
|
// Hide the toolbar before we start loading
|
||||||
toolBar.visible = false
|
toolBar.visible = false
|
||||||
|
|
||||||
@ -114,21 +117,11 @@ Item {
|
|||||||
session.connectionStarted.connect(connectionStarted)
|
session.connectionStarted.connect(connectionStarted)
|
||||||
session.displayLaunchError.connect(displayLaunchError)
|
session.displayLaunchError.connect(displayLaunchError)
|
||||||
session.displayLaunchWarning.connect(displayLaunchWarning)
|
session.displayLaunchWarning.connect(displayLaunchWarning)
|
||||||
|
session.quitStarting.connect(quitStarting)
|
||||||
|
session.sessionFinished.connect(sessionFinished)
|
||||||
|
|
||||||
// Run the streaming session to completion
|
// Run the streaming session to completion
|
||||||
session.exec(Screen.virtualX, Screen.virtualY);
|
session.exec(Screen.virtualX, Screen.virtualY)
|
||||||
|
|
||||||
if (!errorDialog.text && session.shouldQuitAppAfter()) {
|
|
||||||
// Show the Qt window again to show quit segue
|
|
||||||
window.visible = true
|
|
||||||
var component = Qt.createComponent("QuitSegue.qml")
|
|
||||||
stackView.push(component.createObject(stackView, {"appName": appName}))
|
|
||||||
// Quit app
|
|
||||||
ComputerManager.quitAppCompleted.connect(streamingFinished)
|
|
||||||
ComputerManager.quitRunningApp(session)
|
|
||||||
} else {
|
|
||||||
streamingFinished()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (!quitAfter) {
|
else if (!quitAfter) {
|
||||||
// Show the toolbar again when we become hidden
|
// Show the toolbar again when we become hidden
|
||||||
|
@ -275,16 +275,6 @@ int Session::getDecoderCapabilities(StreamingPreferences::VideoDecoderSelection
|
|||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvComputer *Session::getComputer() const
|
|
||||||
{
|
|
||||||
return m_Computer;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Session::shouldQuitAppAfter() const
|
|
||||||
{
|
|
||||||
return m_Preferences->quitAppAfter;
|
|
||||||
}
|
|
||||||
|
|
||||||
Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *preferences)
|
Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *preferences)
|
||||||
: m_Preferences(preferences ? preferences : new StreamingPreferences(this)),
|
: m_Preferences(preferences ? preferences : new StreamingPreferences(this)),
|
||||||
m_Computer(computer),
|
m_Computer(computer),
|
||||||
@ -303,6 +293,14 @@ Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *prefere
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Session::~Session()
|
||||||
|
{
|
||||||
|
// Acquire session semaphore to ensure all cleanup is done before the destructor returns
|
||||||
|
// and the object is deallocated.
|
||||||
|
s_ActiveSessionSemaphore.acquire();
|
||||||
|
s_ActiveSessionSemaphore.release();
|
||||||
|
}
|
||||||
|
|
||||||
void Session::initialize()
|
void Session::initialize()
|
||||||
{
|
{
|
||||||
qInfo() << "Server GPU:" << m_Computer->gpuModel;
|
qInfo() << "Server GPU:" << m_Computer->gpuModel;
|
||||||
@ -561,15 +559,48 @@ bool Session::validateLaunch()
|
|||||||
|
|
||||||
class DeferredSessionCleanupTask : public QRunnable
|
class DeferredSessionCleanupTask : public QRunnable
|
||||||
{
|
{
|
||||||
void run() override
|
public:
|
||||||
{
|
DeferredSessionCleanupTask(Session* session) :
|
||||||
// Finish cleanup of the connection state
|
m_Session(session) {}
|
||||||
LiStopConnection();
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual ~DeferredSessionCleanupTask() override
|
||||||
|
{
|
||||||
// Allow another session to start now that we're cleaned up
|
// Allow another session to start now that we're cleaned up
|
||||||
Session::s_ActiveSession = nullptr;
|
Session::s_ActiveSession = nullptr;
|
||||||
Session::s_ActiveSessionSemaphore.release();
|
Session::s_ActiveSessionSemaphore.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
// Notify the UI
|
||||||
|
if (!m_Session->m_Preferences->quitAppAfter) {
|
||||||
|
emit m_Session->sessionFinished();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
emit m_Session->quitStarting();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish cleanup of the connection state
|
||||||
|
LiStopConnection();
|
||||||
|
|
||||||
|
// Perform a best-effort app quit
|
||||||
|
if (m_Session->m_Preferences->quitAppAfter) {
|
||||||
|
NvHTTP http(m_Session->m_Computer->activeAddress);
|
||||||
|
|
||||||
|
// Logging is already done inside NvHTTP
|
||||||
|
try {
|
||||||
|
http.quitApp();
|
||||||
|
} catch (const GfeHttpResponseException&) {
|
||||||
|
} catch (const QtNetworkReplyException&) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Session is finished now
|
||||||
|
emit m_Session->sessionFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Session* m_Session;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Session::getWindowDimensions(int& x, int& y,
|
void Session::getWindowDimensions(int& x, int& y,
|
||||||
@ -1162,6 +1193,6 @@ DispatchDeferredCleanup:
|
|||||||
// Cleanup can take a while, so dispatch it to a worker thread.
|
// Cleanup can take a while, so dispatch it to a worker thread.
|
||||||
// When it is complete, it will release our s_ActiveSessionSemaphore
|
// When it is complete, it will release our s_ActiveSessionSemaphore
|
||||||
// reference.
|
// reference.
|
||||||
QThreadPool::globalInstance()->start(new DeferredSessionCleanupTask());
|
QThreadPool::globalInstance()->start(new DeferredSessionCleanupTask(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ class Session : public QObject
|
|||||||
public:
|
public:
|
||||||
explicit Session(NvComputer* computer, NvApp& app, StreamingPreferences *preferences = nullptr);
|
explicit Session(NvComputer* computer, NvApp& app, StreamingPreferences *preferences = nullptr);
|
||||||
|
|
||||||
|
virtual ~Session();
|
||||||
|
|
||||||
Q_INVOKABLE void exec(int displayOriginX, int displayOriginY);
|
Q_INVOKABLE void exec(int displayOriginX, int displayOriginY);
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -30,10 +32,6 @@ public:
|
|||||||
int getDecoderCapabilities(StreamingPreferences::VideoDecoderSelection vds,
|
int getDecoderCapabilities(StreamingPreferences::VideoDecoderSelection vds,
|
||||||
int videoFormat, int width, int height, int frameRate);
|
int videoFormat, int width, int height, int frameRate);
|
||||||
|
|
||||||
NvComputer* getComputer() const;
|
|
||||||
|
|
||||||
Q_INVOKABLE bool shouldQuitAppAfter() const;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void stageStarting(QString stage);
|
void stageStarting(QString stage);
|
||||||
|
|
||||||
@ -45,6 +43,10 @@ signals:
|
|||||||
|
|
||||||
void displayLaunchWarning(QString text);
|
void displayLaunchWarning(QString text);
|
||||||
|
|
||||||
|
void quitStarting();
|
||||||
|
|
||||||
|
void sessionFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user