From a11f623b17a38df438d35d5b918e1808b7f66087 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 25 Dec 2020 15:32:11 -0600 Subject: [PATCH] Add option to mute audio on minimize and background gamepad input Fixes #461 --- app/cli/commandlineparser.cpp | 8 ++++++++ app/gui/SettingsView.qml | 29 ++++++++++++++++++++++++++- app/settings/streamingpreferences.cpp | 6 ++++++ app/settings/streamingpreferences.h | 6 ++++++ app/streaming/audio/audio.cpp | 5 +++++ app/streaming/input/input.cpp | 4 ++-- app/streaming/session.cpp | 21 ++++++++++++++++--- app/streaming/session.h | 1 + 8 files changed, 74 insertions(+), 6 deletions(-) diff --git a/app/cli/commandlineparser.cpp b/app/cli/commandlineparser.cpp index 413d7513..cf01d175 100644 --- a/app/cli/commandlineparser.cpp +++ b/app/cli/commandlineparser.cpp @@ -303,6 +303,8 @@ void StreamCommandLineParser::parse(const QStringList &args, StreamingPreference parser.addToggleOption("game-optimization", "game optimizations"); parser.addToggleOption("audio-on-host", "audio on host PC"); parser.addToggleOption("frame-pacing", "frame pacing"); + parser.addToggleOption("mute-on-minimize", "mute audio whe minimized"); + parser.addToggleOption("background-gamepad", "background gamepad input"); parser.addChoiceOption("video-codec", "video codec", m_VideoCodecMap.keys()); parser.addChoiceOption("video-decoder", "video decoder", m_VideoDecoderMap.keys()); @@ -405,6 +407,12 @@ void StreamCommandLineParser::parse(const QStringList &args, StreamingPreference // Resolve --frame-pacing and --no-frame-pacing options preferences->framePacing = parser.getToggleOptionValue("frame-pacing", preferences->framePacing); + // Resolve --mute-on-minimize and --no-mute-on-minimize options + preferences->muteOnMinimize = parser.getToggleOptionValue("mute-on-minimize", preferences->muteOnMinimize); + + // Resolve --background-gamepad and --no-background-gamepad options + preferences->backgroundGamepad = parser.getToggleOptionValue("background-gamepad", preferences->backgroundGamepad); + // Resolve --video-codec option if (parser.isSet("video-codec")) { preferences->videoCodecConfig = mapValue(m_VideoCodecMap, parser.getChoiceOptionValue("video-codec")); diff --git a/app/gui/SettingsView.qml b/app/gui/SettingsView.qml index 1b5ce51e..88b6377d 100644 --- a/app/gui/SettingsView.qml +++ b/app/gui/SettingsView.qml @@ -683,6 +683,17 @@ Flickable { ToolTip.visible: hovered ToolTip.text: qsTr("You must restart any game currently in progress for this setting to take effect") } + + CheckBox { + id: muteOnMinimizeCheck + width: parent.width + text: qsTr("Mute audio stream when Moonlight is minimized") + font.pointSize: 12 + checked: StreamingPreferences.muteOnMinimize + onCheckedChanged: { + StreamingPreferences.muteOnMinimize = checked + } + } } } @@ -823,7 +834,7 @@ Flickable { CheckBox { id: singleControllerCheck width: parent.width - text: qsTr("Force gamepad #1 always present") + text: qsTr("Force gamepad #1 always connected") font.pointSize: 12 checked: !StreamingPreferences.multiController onCheckedChanged: { @@ -853,6 +864,22 @@ Flickable { ToolTip.visible: hovered ToolTip.text: qsTr("When enabled, holding the Start button will toggle mouse mode") } + + CheckBox { + id: backgroundGamepadCheck + width: parent.width + text: qsTr("Process gamepad input when Moonlight is in the background") + font.pointSize: 12 + checked: StreamingPreferences.backgroundGamepad + onCheckedChanged: { + StreamingPreferences.backgroundGamepad = checked + } + + ToolTip.delay: 1000 + ToolTip.timeout: 5000 + ToolTip.visible: hovered + ToolTip.text: qsTr("Allows Moonlight to capture gamepad inputs even if it's not the current window in focus") + } } } diff --git a/app/settings/streamingpreferences.cpp b/app/settings/streamingpreferences.cpp index 90dd7777..aacfd04d 100644 --- a/app/settings/streamingpreferences.cpp +++ b/app/settings/streamingpreferences.cpp @@ -30,6 +30,8 @@ #define SER_PACKETSIZE "packetsize" #define SER_DETECTNETBLOCKING "detectnetblocking" #define SER_SWAPMOUSEBUTTONS "swapmousebuttons" +#define SER_MUTEONMINIMIZE "muteonminimize" +#define SER_BACKGROUNDGAMEPAD "backgroundgamepad" #define CURRENT_DEFAULT_VER 1 @@ -72,6 +74,8 @@ void StreamingPreferences::reload() detectNetworkBlocking = settings.value(SER_DETECTNETBLOCKING, true).toBool(); packetSize = settings.value(SER_PACKETSIZE, 0).toInt(); swapMouseButtons = settings.value(SER_SWAPMOUSEBUTTONS, false).toBool(); + muteOnMinimize = settings.value(SER_MUTEONMINIMIZE, false).toBool(); + backgroundGamepad = settings.value(SER_BACKGROUNDGAMEPAD, false).toBool(); audioConfig = static_cast(settings.value(SER_AUDIOCFG, static_cast(AudioConfig::AC_STEREO)).toInt()); videoCodecConfig = static_cast(settings.value(SER_VIDEOCFG, @@ -124,6 +128,8 @@ void StreamingPreferences::save() settings.setValue(SER_WINDOWMODE, static_cast(windowMode)); settings.setValue(SER_DEFAULTVER, CURRENT_DEFAULT_VER); settings.setValue(SER_SWAPMOUSEBUTTONS, swapMouseButtons); + settings.setValue(SER_MUTEONMINIMIZE, muteOnMinimize); + settings.setValue(SER_BACKGROUNDGAMEPAD, backgroundGamepad); } int StreamingPreferences::getDefaultBitrate(int width, int height, int fps) diff --git a/app/settings/streamingpreferences.h b/app/settings/streamingpreferences.h index 92311756..8504b189 100644 --- a/app/settings/streamingpreferences.h +++ b/app/settings/streamingpreferences.h @@ -75,6 +75,8 @@ public: Q_PROPERTY(WindowMode windowMode MEMBER windowMode NOTIFY windowModeChanged) Q_PROPERTY(WindowMode recommendedFullScreenMode MEMBER recommendedFullScreenMode CONSTANT) Q_PROPERTY(bool swapMouseButtons MEMBER swapMouseButtons NOTIFY mouseButtonsChanged) + Q_PROPERTY(bool muteOnMinimize MEMBER muteOnMinimize NOTIFY muteOnMinimizeChanged) + Q_PROPERTY(bool backgroundGamepad MEMBER backgroundGamepad NOTIFY backgroundGamepadChanged) // Directly accessible members for preferences int width; @@ -97,6 +99,8 @@ public: bool gamepadMouse; bool detectNetworkBlocking; bool swapMouseButtons; + bool muteOnMinimize; + bool backgroundGamepad; int packetSize; AudioConfig audioConfig; VideoCodecConfig videoCodecConfig; @@ -127,5 +131,7 @@ signals: void gamepadMouseChanged(); void detectNetworkBlockingChanged(); void mouseButtonsChanged(); + void muteOnMinimizeChanged(); + void backgroundGamepadChanged(); }; diff --git a/app/streaming/audio/audio.cpp b/app/streaming/audio/audio.cpp index 29588296..75dc7258 100644 --- a/app/streaming/audio/audio.cpp +++ b/app/streaming/audio/audio.cpp @@ -197,6 +197,11 @@ void Session::arDecodeAndPlaySample(char* sampleData, int sampleLength) s_ActiveSession->m_AudioSampleCount++; + // If audio is muted, don't decode or play the audio + if (s_ActiveSession->m_AudioMuted) { + return; + } + if (s_ActiveSession->m_AudioRenderer != nullptr) { int desiredSize = sizeof(short) * s_ActiveSession->m_AudioConfig.samplesPerFrame * s_ActiveSession->m_AudioConfig.channelCount; void* buffer = s_ActiveSession->m_AudioRenderer->getAudioBuffer(&desiredSize); diff --git a/app/streaming/input/input.cpp b/app/streaming/input/input.cpp index bfef61d1..3428e50d 100644 --- a/app/streaming/input/input.cpp +++ b/app/streaming/input/input.cpp @@ -30,8 +30,8 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int s m_DragButton(0), m_NumFingersDown(0) { - // Allow gamepad input when the app doesn't have focus - SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); + // Allow gamepad input when the app doesn't have focus if requested + SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, prefs.backgroundGamepad ? "1" : "0"); // If absolute mouse mode is enabled, use relative mode warp (which // is via normal motion events that are influenced by mouse acceleration). diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index 88e19eb0..bf841e59 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -370,6 +370,7 @@ Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *prefere m_DecoderLock(0), m_NeedsIdr(false), m_AudioDisabled(false), + m_AudioMuted(false), m_DisplayOriginX(0), m_DisplayOriginY(0), m_PendingWindowedTransition(false), @@ -1318,11 +1319,25 @@ void Session::exec(int displayOriginX, int displayOriginY) break; case SDL_WINDOWEVENT: - if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) { + // Early handling of some events + switch (event.window.event) { + case SDL_WINDOWEVENT_FOCUS_LOST: m_InputHandler->notifyFocusLost(); - } - else if (event.window.event == SDL_WINDOWEVENT_LEAVE) { + break; + case SDL_WINDOWEVENT_LEAVE: m_InputHandler->notifyMouseLeave(); + break; + case SDL_WINDOWEVENT_MINIMIZED: + if (m_Preferences->muteOnMinimize) { + m_AudioMuted = true; + } + break; + case SDL_WINDOWEVENT_MAXIMIZED: + case SDL_WINDOWEVENT_RESTORED: + if (m_Preferences->muteOnMinimize) { + m_AudioMuted = false; + } + break; } // Capture the mouse on SDL_WINDOWEVENT_ENTER if needed diff --git a/app/streaming/session.h b/app/streaming/session.h index 98c6df7b..59653108 100644 --- a/app/streaming/session.h +++ b/app/streaming/session.h @@ -141,6 +141,7 @@ private: SDL_SpinLock m_DecoderLock; bool m_NeedsIdr; bool m_AudioDisabled; + bool m_AudioMuted; Uint32 m_FullScreenFlag; int m_DisplayOriginX; int m_DisplayOriginY;