From cded01187d76f4447c761e39c6688de8be63373d Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 24 Jun 2018 00:14:23 -0700 Subject: [PATCH] More streaming code --- app/http/nvhttp.cpp | 91 +++++++++++++++++++++++++++++++++++++++ app/http/nvhttp.h | 15 +++++++ app/streaming/input.c | 16 +++++++ app/streaming/streaming.h | 1 + 4 files changed, 123 insertions(+) diff --git a/app/http/nvhttp.cpp b/app/http/nvhttp.cpp index f1674bb5..e32e9759 100644 --- a/app/http/nvhttp.cpp +++ b/app/http/nvhttp.cpp @@ -1,4 +1,5 @@ #include "nvhttp.h" +#include #include #include @@ -130,6 +131,96 @@ NvHTTP::getServerInfo() return serverInfo; } +static QString +getSurroundAudioInfoString(int audioConfig) +{ + int channelMask; + int channelCount; + + switch (audioConfig) + { + case AUDIO_CONFIGURATION_STEREO: + channelCount = 2; + channelMask = 0x3; + break; + case AUDIO_CONFIGURATION_51_SURROUND: + channelCount = 6; + channelMask = 0xFC; + break; + default: + Q_ASSERT(false); + return 0; + } + + return QString::number(channelMask << 16 | channelCount); +} + +void +NvHTTP::launchApp(int appId, + PSTREAM_CONFIGURATION streamConfig, + bool sops, + bool localAudio, + int gamepadMask) +{ + QString response = + openConnectionToString(m_BaseUrlHttps, + "launch", + "appid="+QString::number(appId)+ + "&mode="+QString::number(streamConfig->width)+"x"+ + QString::number(streamConfig->height)+"x"+ + QString::number(streamConfig->fps)+ + "&additionalStates=1&sops="+QString::number(sops ? 1 : 0)+ + "&rikey="+QByteArray(streamConfig->remoteInputAesKey, sizeof(streamConfig->remoteInputAesKey)).toHex()+ + "&rikeyid="+QString::number(*(int*)streamConfig->remoteInputAesIv)+ + (streamConfig->enableHdr ? + "&hdrMode=1&clientHdrCapVersion=0&clientHdrCapSupportedFlagsInUint32=0&clientHdrCapMetaDataId=NV_STATIC_METADATA_TYPE_1&clientHdrCapDisplayData=0x0x0x0x0x0x0x0x0x0x0" : + "")+ + "&localAudioPlayMode="+QString::number(localAudio ? 1 : 0)+ + "&surroundAudioInfo="+getSurroundAudioInfoString(streamConfig->audioConfiguration)+ + "&remoteControllersBitmap="+QString::number(gamepadMask)+ + "&gcmap="+QString::number(gamepadMask), + false); + + // Throws if the request failed + verifyResponseStatus(response); +} + +void +NvHTTP::resumeApp(PSTREAM_CONFIGURATION streamConfig) +{ + QString response = + openConnectionToString(m_BaseUrlHttps, + "resume", + "rikey="+QString(QByteArray(streamConfig->remoteInputAesKey, sizeof(streamConfig->remoteInputAesKey)).toHex())+ + "&rikeyid="+QString::number(*(int*)streamConfig->remoteInputAesIv)+ + "&surroundAudioInfo="+getSurroundAudioInfoString(streamConfig->audioConfiguration), + false); + + // Throws if the request failed + verifyResponseStatus(response); +} + +void +NvHTTP::quitApp() +{ + QString response = + openConnectionToString(m_BaseUrlHttps, + "cancel", + nullptr, + false); + + // Throws if the request failed + verifyResponseStatus(response); + + // Newer GFE versions will just return success even if quitting fails + // if we're not the original requestor. + if (getCurrentGame(getServerInfo()) != 0) { + // Generate a synthetic GfeResponseException letting the caller know + // that they can't kill someone else's stream. + throw GfeHttpResponseException(599, ""); + } +} + void NvHTTP::verifyResponseStatus(QString xml) { diff --git a/app/http/nvhttp.h b/app/http/nvhttp.h index 6df48887..402c72a7 100644 --- a/app/http/nvhttp.h +++ b/app/http/nvhttp.h @@ -2,6 +2,8 @@ #include "identitymanager.h" +#include + #include #include @@ -98,6 +100,19 @@ public: QVector getServerVersionQuad(QString serverInfo); + void + quitApp(); + + void + resumeApp(PSTREAM_CONFIGURATION streamConfig); + + void + launchApp(int appId, + PSTREAM_CONFIGURATION streamConfig, + bool sops, + bool localAudio, + int gamepadMask); + QUrl m_BaseUrlHttp; QUrl m_BaseUrlHttps; private: diff --git a/app/streaming/input.c b/app/streaming/input.c index 9af88643..16a5090f 100644 --- a/app/streaming/input.c +++ b/app/streaming/input.c @@ -474,6 +474,22 @@ void SdlHandleControllerDeviceEvent(SDL_ControllerDeviceEvent* event) } } +int SdlGetAttachedGamepadMask(void) +{ + int i; + int count; + int mask; + + count = mask = 0; + for (i = 0; i < SDL_NumJoysticks(); i++) { + if (SDL_IsGameController(i)) { + mask |= (1 << count++); + } + } + + return mask; +} + void SdlInitializeGamepad(bool multiController) { g_MultiController = multiController; diff --git a/app/streaming/streaming.h b/app/streaming/streaming.h index 74309de8..43305afc 100644 --- a/app/streaming/streaming.h +++ b/app/streaming/streaming.h @@ -14,6 +14,7 @@ extern DECODER_RENDERER_CALLBACKS k_VideoCallbacks; int SdlDetermineAudioConfiguration(void); void SdlInitializeGamepad(bool multiController); +int SdlGetAttachedGamepadMask(void); void SdlHandleControllerDeviceEvent(SDL_ControllerDeviceEvent* event); void SdlHandleControllerButtonEvent(SDL_ControllerButtonEvent* event); void SdlHandleControllerAxisEvent(SDL_ControllerAxisEvent* event);