From a26573fefe2a3599c1c920722dec519c9481dc64 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 3 Aug 2023 20:40:40 +0300
Subject: [PATCH] SL-18049 Part 1; Allow voice to be enabled in second instance

---
 indra/newview/llappviewer.cpp                 |  9 +--
 indra/newview/llpanelvolumepulldown.cpp       | 31 ++++++----
 indra/newview/llpanelvolumepulldown.h         |  2 +-
 indra/newview/llvoiceclient.cpp               | 10 +++
 indra/newview/llvoiceclient.h                 |  2 +
 indra/newview/llvoicevivox.cpp                | 62 +++++++++++++------
 indra/newview/llvoicevivox.h                  |  3 +
 .../default/xui/en/panel_volume_pulldown.xml  | 13 +++-
 8 files changed, 93 insertions(+), 39 deletions(-)

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index e70fcb6e86a..e9ba0550b07 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2945,13 +2945,14 @@ bool LLAppViewer::initConfiguration()
 
 	if (mSecondInstance)
 	{
-		// This is the second instance of SL. Turn off voice support,
+		// This is the second instance of SL. Mute voice,
 		// but make sure the setting is *not* persisted.
-		LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice");
-		if(disable_voice)
+		// Also see LLVivoxVoiceClient::voiceEnabled()
+		LLControlVariable* enable_voice = gSavedSettings.getControl("EnableVoiceChat");
+		if(enable_voice)
 		{
 			const BOOL DO_NOT_PERSIST = FALSE;
-			disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST);
+			enable_voice->setValue(LLSD(FALSE), DO_NOT_PERSIST);
 		}
 	}
 
diff --git a/indra/newview/llpanelvolumepulldown.cpp b/indra/newview/llpanelvolumepulldown.cpp
index 6f11e76a72d..17975a6e6d0 100644
--- a/indra/newview/llpanelvolumepulldown.cpp
+++ b/indra/newview/llpanelvolumepulldown.cpp
@@ -40,6 +40,7 @@
 #include "llfloaterreg.h"
 #include "llfloaterpreference.h"
 #include "llsliderctrl.h"
+#include "llvoicevivox.h"
 
 ///----------------------------------------------------------------------------
 /// Class LLPanelVolumePulldown
@@ -50,7 +51,7 @@ LLPanelVolumePulldown::LLPanelVolumePulldown()
 {
 	mCommitCallbackRegistrar.add("Vol.setControlFalse", boost::bind(&LLPanelVolumePulldown::setControlFalse, this, _2));
 	mCommitCallbackRegistrar.add("Vol.SetSounds", boost::bind(&LLPanelVolumePulldown::onClickSetSounds, this));
-	mCommitCallbackRegistrar.add("Vol.updateMediaAutoPlayCheckbox",	boost::bind(&LLPanelVolumePulldown::updateMediaAutoPlayCheckbox, this, _1));
+	mCommitCallbackRegistrar.add("Vol.updateCheckbox",	boost::bind(&LLPanelVolumePulldown::updateCheckbox, this, _1, _2));
 	mCommitCallbackRegistrar.add("Vol.GoAudioPrefs", boost::bind(&LLPanelVolumePulldown::onAdvancedButtonClick, this, _2));
 	buildFromFile( "panel_volume_pulldown.xml");
 }
@@ -90,19 +91,27 @@ void LLPanelVolumePulldown::setControlFalse(const LLSD& user_data)
 		control->set(LLSD(FALSE));
 }
 
-void LLPanelVolumePulldown::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl)
+void LLPanelVolumePulldown::updateCheckbox(LLUICtrl* ctrl, const LLSD& user_data)
 {
-	std::string name = ctrl->getName();
+    std::string control_name = user_data.asString();
+    if (control_name == "MediaAutoPlay")
+    {
+        std::string name = ctrl->getName();
 
-	// Disable "Allow Media to auto play" only when both
-	// "Streaming Music" and "Media" are unchecked. STORM-513.
-	if ((name == "enable_music") || (name == "enable_media"))
-	{
-		bool music_enabled = getChild<LLCheckBoxCtrl>("enable_music")->get();
-		bool media_enabled = getChild<LLCheckBoxCtrl>("enable_media")->get();
+        // Disable "Allow Media to auto play" only when both
+        // "Streaming Music" and "Media" are unchecked. STORM-513.
+        if ((name == "enable_music") || (name == "enable_media"))
+        {
+            bool music_enabled = getChild<LLCheckBoxCtrl>("enable_music")->get();
+            bool media_enabled = getChild<LLCheckBoxCtrl>("enable_media")->get();
 
-		getChild<LLCheckBoxCtrl>("media_auto_play_combo")->setEnabled(music_enabled || media_enabled);
-	}
+            getChild<LLCheckBoxCtrl>("media_auto_play_combo")->setEnabled(music_enabled || media_enabled);
+        }
+    }
+    else if (control_name == "VoiceChat")
+    {
+        LLVivoxVoiceClient::unmuteVoiceInstance();
+    }
 }
 
 void LLPanelVolumePulldown::onClickSetSounds()
diff --git a/indra/newview/llpanelvolumepulldown.h b/indra/newview/llpanelvolumepulldown.h
index e907bb0c78f..3243d2e968f 100644
--- a/indra/newview/llpanelvolumepulldown.h
+++ b/indra/newview/llpanelvolumepulldown.h
@@ -43,7 +43,7 @@ class LLPanelVolumePulldown : public LLPanelPulldown
 	void onClickSetSounds();
 	// Disables "Allow Media to auto play" check box only when both
 	// "Streaming Music" and "Media" are unchecked. Otherwise enables it.
-	void updateMediaAutoPlayCheckbox(LLUICtrl* ctrl);
+	void updateCheckbox(LLUICtrl* ctrl, const LLSD& user_data);
 	void onAdvancedButtonClick(const LLSD& user_data);
 };
 
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 150b556284f..fab6ec37550 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -555,6 +555,16 @@ void LLVoiceClient::setVoiceEnabled(bool enabled)
     }
 }
 
+void LLVoiceClient::unmuteVoiceInstance()
+{
+    LLVivoxVoiceClient::unmuteVoiceInstance();
+}
+
+bool LLVoiceClient::isMutedVoiceInstance()
+{
+    return LLVivoxVoiceClient::isMutedVoiceInstance();
+}
+
 void LLVoiceClient::updateMicMuteLogic()
 {
 	// If not configured to use PTT, the mic should be open (otherwise the user will be unable to speak).
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index aa67502908d..7788efb8e1e 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -403,6 +403,8 @@ class LLVoiceClient: public LLParamSingleton<LLVoiceClient>
 	void toggleUserPTTState(void);
 	void inputUserControlState(bool down);  // interpret any sort of up-down mic-open control input according to ptt-toggle prefs	
 	void setVoiceEnabled(bool enabled);
+    static void unmuteVoiceInstance();
+    static bool isMutedVoiceInstance();
 
 	void setUsePTT(bool usePTT);
 	void setPTTIsToggle(bool PTTIsToggle);
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 3725510b6a1..c89fe81a858 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -277,6 +277,7 @@ static void killGateway()
 
 bool LLVivoxVoiceClient::sShuttingDown = false;
 bool LLVivoxVoiceClient::sConnected = false;
+bool LLVivoxVoiceClient::sVoiceInstanceMuted = false;
 LLPumpIO *LLVivoxVoiceClient::sPump = nullptr;
 
 LLVivoxVoiceClient::LLVivoxVoiceClient() :
@@ -354,6 +355,7 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() :
     sShuttingDown = false;
     sConnected = false;
     sPump = nullptr;
+    sVoiceInstanceMuted = LLAppViewer::instance()->isSecondInstance();
 
 	mSpeakerVolume = scale_speaker_volume(0);
 
@@ -951,32 +953,52 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
             // cause SLVoice's bind() call to fail with EADDRINUSE. We expect
             // that eventually the OS will time out previous ports, which is
             // why we cycle instead of incrementing indefinitely.
-            U32 portbase = gSavedSettings.getU32("VivoxVoicePort");
-            static U32 portoffset = 0;
+
+            static LLCachedControl<U32> portbase(gSavedSettings, "VivoxVoicePort");
+            static LLCachedControl<std::string> host(gSavedSettings, "VivoxVoiceHost");
+            static LLCachedControl<std::string> loglevel(gSavedSettings, "VivoxDebugLevel");
+            static LLCachedControl<std::string> log_folder(gSavedSettings, "VivoxLogDirectory");
+            static LLCachedControl<std::string> shutdown_timeout(gSavedSettings, "VivoxShutdownTimeout");
             static const U32 portrange = 100;
-            std::string host(gSavedSettings.getString("VivoxVoiceHost"));
-            U32 port = portbase + portoffset;
+            static U32 portoffset = 0;
+            U32 port = 0;
+
+            if (LLAppViewer::instance()->isSecondInstance())
+            {
+                // Ideally need to know amount of instances and
+                // to increment instance_offset on EADDRINUSE.
+                // But for now just use rand
+                static U32 instance_offset = portrange * ll_rand(20);
+                port = portbase + portoffset + portrange;
+            }
+            else
+            {
+                // leave main thread with exclusive port set
+                port = portbase + portoffset;
+            }
             portoffset = (portoffset + 1) % portrange;
             params.args.add("-i");
-            params.args.add(STRINGIZE(host << ':' << port));
+            params.args.add(STRINGIZE(host() << ':' << port));
 
-            std::string loglevel = gSavedSettings.getString("VivoxDebugLevel");
-            if (loglevel.empty())
+            params.args.add("-ll");
+            if (loglevel().empty())
             {
-                loglevel = "0";
+                params.args.add("0");
             }
-            params.args.add("-ll");
-            params.args.add(loglevel);
-
-            std::string log_folder = gSavedSettings.getString("VivoxLogDirectory");
-
-            if (log_folder.empty())
+            else
             {
-                log_folder = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
+                params.args.add(loglevel);
             }
 
             params.args.add("-lf");
-            params.args.add(log_folder);
+            if (log_folder().empty())
+            {
+                params.args.add(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""));
+            }
+            else
+            {
+                params.args.add(log_folder);
+            }
 
             // set log file basename and .log
             params.args.add("-lp");
@@ -992,8 +1014,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
                 LLFile::rename(new_log, old_log);
             }
             
-            std::string shutdown_timeout = gSavedSettings.getString("VivoxShutdownTimeout");
-            if (!shutdown_timeout.empty())
+            if (!shutdown_timeout().empty())
             {
                 params.args.add("-st");
                 params.args.add(shutdown_timeout);
@@ -1016,7 +1037,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
 
             sGatewayPtr = LLProcess::create(params);
 
-            mDaemonHost = LLHost(host.c_str(), port);
+            mDaemonHost = LLHost(host().c_str(), port);
         }
         else
         {
@@ -5624,7 +5645,8 @@ bool LLVivoxVoiceClient::voiceEnabled()
 {
     return gSavedSettings.getBOOL("EnableVoiceChat") &&
           !gSavedSettings.getBOOL("CmdLineDisableVoice") &&
-          !gNonInteractive;
+          !gNonInteractive &&
+          !sVoiceInstanceMuted;
 }
 
 void LLVivoxVoiceClient::setLipSyncEnabled(BOOL enabled)
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index e3ab99c6754..9a4023422b8 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -172,6 +172,8 @@ class LLVivoxVoiceClient :	public LLSingleton<LLVivoxVoiceClient>,
 	//@{
 	virtual bool voiceEnabled();
 	virtual void setVoiceEnabled(bool enabled);
+    static void unmuteVoiceInstance() { sVoiceInstanceMuted = false; }
+    static bool isMutedVoiceInstance() { return sVoiceInstanceMuted; }
 	virtual BOOL lipSyncEnabled();	
 	virtual void setLipSyncEnabled(BOOL enabled);
 	virtual void setMuteMic(bool muted);		// Set the mute state of the local mic.
@@ -917,6 +919,7 @@ class LLVivoxVoiceClient :	public LLSingleton<LLVivoxVoiceClient>,
     // This variables can last longer than vivox in coroutines so we need them as static
     static bool sShuttingDown;
     static bool sConnected;
+    static bool sVoiceInstanceMuted; // Second+ instance of viewer starts muted
     static LLPumpIO* sPump;
 
     LLEventMailDrop mVivoxPump;
diff --git a/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml
index b4eb1ade947..c7be790406a 100644
--- a/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml
+++ b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml
@@ -199,7 +199,8 @@
         top_delta="2"
         width="350">
         <check_box.commit_callback
-            function="Vol.updateMediaAutoPlayCheckbox"/>
+            function="Vol.updateCheckbox"
+            parameter="MediaAutoPlay"/>
     </check_box>
     <slider
         control_name="AudioLevelMedia"
@@ -246,7 +247,8 @@
         name="enable_media"
         width="110">
         <check_box.commit_callback
-            function="Vol.updateMediaAutoPlayCheckbox"/>
+            function="Vol.updateCheckbox"
+            parameter="MediaAutoPlay"/>
     </check_box>
     <slider
         control_name="AudioLevelVoice"
@@ -292,5 +294,10 @@
         top_delta="2"
         left_pad="5"
         name="enable_voice_check"
-        width="110"/>
+        width="110"
+        >
+        <check_box.commit_callback
+            function="Vol.updateCheckbox"
+            parameter="VoiceChat"/>
+        </check_box>
 </panel>
-- 
GitLab