mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-02 07:46:07 +00:00
Improve UI responsiveness when stopping a stream
This commit is contained in:
parent
908850cc5d
commit
e8e9e17e63
@ -8,6 +8,7 @@
|
|||||||
#include <QRandomGenerator>
|
#include <QRandomGenerator>
|
||||||
#include <QtEndian>
|
#include <QtEndian>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QThreadPool>
|
||||||
|
|
||||||
CONNECTION_LISTENER_CALLBACKS Session::k_ConnCallbacks = {
|
CONNECTION_LISTENER_CALLBACKS Session::k_ConnCallbacks = {
|
||||||
Session::clStageStarting,
|
Session::clStageStarting,
|
||||||
@ -30,6 +31,7 @@ AUDIO_RENDERER_CALLBACKS Session::k_AudioCallbacks = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Session* Session::s_ActiveSession;
|
Session* Session::s_ActiveSession;
|
||||||
|
QSemaphore Session::s_ActiveSessionSemaphore(1);
|
||||||
|
|
||||||
void Session::clStageStarting(int stage)
|
void Session::clStageStarting(int stage)
|
||||||
{
|
{
|
||||||
@ -76,7 +78,10 @@ void Session::clLogMessage(const char* format, ...)
|
|||||||
|
|
||||||
Session::Session(NvComputer* computer, NvApp& app)
|
Session::Session(NvComputer* computer, NvApp& app)
|
||||||
: m_Computer(computer),
|
: m_Computer(computer),
|
||||||
m_App(app)
|
m_App(app),
|
||||||
|
m_Window(nullptr),
|
||||||
|
m_Renderer(nullptr),
|
||||||
|
m_Texture(nullptr)
|
||||||
{
|
{
|
||||||
LiInitializeVideoCallbacks(&m_VideoCallbacks);
|
LiInitializeVideoCallbacks(&m_VideoCallbacks);
|
||||||
m_VideoCallbacks.setup = drSetup;
|
m_VideoCallbacks.setup = drSetup;
|
||||||
@ -194,6 +199,29 @@ bool Session::validateLaunch()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class DeferredSessionCleanupTask : public QRunnable
|
||||||
|
{
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
// Finish cleanup of the connection state
|
||||||
|
LiStopConnection();
|
||||||
|
if (Session::s_ActiveSession->m_Texture != nullptr) {
|
||||||
|
SDL_DestroyTexture(Session::s_ActiveSession->m_Texture);
|
||||||
|
}
|
||||||
|
if (Session::s_ActiveSession->m_Renderer != nullptr) {
|
||||||
|
SDL_DestroyRenderer(Session::s_ActiveSession->m_Renderer);
|
||||||
|
}
|
||||||
|
if (Session::s_ActiveSession->m_Window != nullptr) {
|
||||||
|
SDL_DestroyWindow(Session::s_ActiveSession->m_Window);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow another session to start now that we're cleaned up
|
||||||
|
Session::s_ActiveSession = nullptr;
|
||||||
|
Session::s_ActiveSessionSemaphore.release();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void Session::exec()
|
void Session::exec()
|
||||||
{
|
{
|
||||||
// Check for validation errors/warnings and emit
|
// Check for validation errors/warnings and emit
|
||||||
@ -205,6 +233,9 @@ void Session::exec()
|
|||||||
// Manually pump the UI thread for the view
|
// Manually pump the UI thread for the view
|
||||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||||
|
|
||||||
|
// Wait for any old session to finish cleanup
|
||||||
|
s_ActiveSessionSemaphore.acquire();
|
||||||
|
|
||||||
// We're now active
|
// We're now active
|
||||||
s_ActiveSession = this;
|
s_ActiveSession = this;
|
||||||
|
|
||||||
@ -230,6 +261,7 @@ void Session::exec()
|
|||||||
}
|
}
|
||||||
} catch (const GfeHttpResponseException& e) {
|
} catch (const GfeHttpResponseException& e) {
|
||||||
emit displayLaunchError(e.toQString());
|
emit displayLaunchError(e.toQString());
|
||||||
|
s_ActiveSessionSemaphore.release();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,6 +287,7 @@ void Session::exec()
|
|||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
// We already displayed an error dialog in the stage failure
|
// We already displayed an error dialog in the stage failure
|
||||||
// listener.
|
// listener.
|
||||||
|
s_ActiveSessionSemaphore.release();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,8 +307,7 @@ void Session::exec()
|
|||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"SDL_CreateWindow() failed: %s",
|
"SDL_CreateWindow() failed: %s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
LiStopConnection();
|
goto DispatchDeferredCleanup;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Renderer = SDL_CreateRenderer(m_Window, -1,
|
m_Renderer = SDL_CreateRenderer(m_Window, -1,
|
||||||
@ -284,9 +316,7 @@ void Session::exec()
|
|||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"SDL_CreateRenderer() failed: %s",
|
"SDL_CreateRenderer() failed: %s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
LiStopConnection();
|
goto DispatchDeferredCleanup;
|
||||||
SDL_DestroyWindow(m_Window);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Texture = SDL_CreateTexture(m_Renderer,
|
m_Texture = SDL_CreateTexture(m_Renderer,
|
||||||
@ -298,10 +328,7 @@ void Session::exec()
|
|||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"SDL_CreateRenderer() failed: %s",
|
"SDL_CreateRenderer() failed: %s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
LiStopConnection();
|
goto DispatchDeferredCleanup;
|
||||||
SDL_DestroyRenderer(m_Renderer);
|
|
||||||
SDL_DestroyWindow(m_Window);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Capture the mouse
|
// Capture the mouse
|
||||||
@ -315,7 +342,7 @@ void Session::exec()
|
|||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"Quit event received");
|
"Quit event received");
|
||||||
goto Exit;
|
goto DispatchDeferredCleanup;
|
||||||
case SDL_USEREVENT: {
|
case SDL_USEREVENT: {
|
||||||
SDL_Event nextEvent;
|
SDL_Event nextEvent;
|
||||||
|
|
||||||
@ -367,10 +394,17 @@ void Session::exec()
|
|||||||
"SDL_WaitEvent() failed: %s",
|
"SDL_WaitEvent() failed: %s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
|
|
||||||
Exit:
|
DispatchDeferredCleanup:
|
||||||
s_ActiveSession = nullptr;
|
// Uncapture the mouse and hide the window immediately,
|
||||||
LiStopConnection();
|
// so we can return to the Qt GUI ASAP.
|
||||||
SDL_DestroyTexture(m_Texture);
|
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||||
SDL_DestroyRenderer(m_Renderer);
|
if (m_Window != nullptr) {
|
||||||
SDL_DestroyWindow(m_Window);
|
SDL_HideWindow(m_Window);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup can take a while, so dispatch it to a worker thread.
|
||||||
|
// When it is complete, it will release our s_ActiveSessionSemaphore
|
||||||
|
// reference.
|
||||||
|
QThreadPool::globalInstance()->start(new DeferredSessionCleanupTask());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QSemaphore>
|
||||||
|
|
||||||
#include <Limelight.h>
|
#include <Limelight.h>
|
||||||
#include <opus_multistream.h>
|
#include <opus_multistream.h>
|
||||||
#include "backend/computermanager.h"
|
#include "backend/computermanager.h"
|
||||||
@ -17,6 +19,7 @@ class Session : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
friend class SdlInputHandler;
|
friend class SdlInputHandler;
|
||||||
|
friend class DeferredSessionCleanupTask;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Session(NvComputer* computer, NvApp& app);
|
explicit Session(NvComputer* computer, NvApp& app);
|
||||||
@ -104,4 +107,5 @@ private:
|
|||||||
static AUDIO_RENDERER_CALLBACKS k_AudioCallbacks;
|
static AUDIO_RENDERER_CALLBACKS k_AudioCallbacks;
|
||||||
static CONNECTION_LISTENER_CALLBACKS k_ConnCallbacks;
|
static CONNECTION_LISTENER_CALLBACKS k_ConnCallbacks;
|
||||||
static Session* s_ActiveSession;
|
static Session* s_ActiveSession;
|
||||||
|
static QSemaphore s_ActiveSessionSemaphore;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user