summaryrefslogtreecommitdiff
path: root/indra/newview/llvoicevivox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llvoicevivox.cpp')
-rw-r--r--indra/newview/llvoicevivox.cpp345
1 files changed, 256 insertions, 89 deletions
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 739f7bd47c..7d8aa6fbbd 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -274,6 +274,8 @@ static void killGateway()
///////////////////////////////////////////////////////////////////////////////////////////////
+bool LLVivoxVoiceClient::sShuttingDown = false;
+
LLVivoxVoiceClient::LLVivoxVoiceClient() :
mSessionTerminateRequested(false),
mRelogRequested(false),
@@ -338,15 +340,15 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() :
mPlayRequestCount(0),
mAvatarNameCacheConnection(),
- mIsInTuningMode(false),
- mIsInChannel(false),
- mIsJoiningSession(false),
- mIsWaitingForFonts(false),
- mIsLoggingIn(false),
- mIsLoggedIn(false),
- mIsProcessingChannels(false),
- mIsCoroutineActive(false),
- mVivoxPump("vivoxClientPump")
+ mIsInTuningMode(false),
+ mIsInChannel(false),
+ mIsJoiningSession(false),
+ mIsWaitingForFonts(false),
+ mIsLoggingIn(false),
+ mIsLoggedIn(false),
+ mIsProcessingChannels(false),
+ mIsCoroutineActive(false),
+ mVivoxPump("vivoxClientPump")
{
mSpeakerVolume = scale_speaker_volume(0);
@@ -357,7 +359,7 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() :
// gMuteListp->addObserver(&mutelist_listener);
-#if LL_DARWIN || LL_LINUX || LL_SOLARIS
+#if LL_DARWIN || LL_LINUX
// HACK: THIS DOES NOT BELONG HERE
// When the vivox daemon dies, the next write attempt on our socket generates a SIGPIPE, which kills us.
// This should cause us to ignore SIGPIPE and handle the error through proper channels.
@@ -381,6 +383,7 @@ LLVivoxVoiceClient::~LLVivoxVoiceClient()
{
mAvatarNameCacheConnection.disconnect();
}
+ sShuttingDown = true;
}
//---------------------------------------------------
@@ -388,9 +391,9 @@ LLVivoxVoiceClient::~LLVivoxVoiceClient()
void LLVivoxVoiceClient::init(LLPumpIO *pump)
{
// constructor will set up LLVoiceClient::getInstance()
- LLVivoxVoiceClient::getInstance()->mPump = pump;
+ mPump = pump;
-// LLCoros::instance().launch("LLVivoxVoiceClient::voiceControlCoro();",
+// LLCoros::instance().launch("LLVivoxVoiceClient::voiceControlCoro",
// boost::bind(&LLVivoxVoiceClient::voiceControlCoro, LLVivoxVoiceClient::getInstance()));
}
@@ -411,8 +414,12 @@ void LLVivoxVoiceClient::terminate()
}
else
{
+ mRelogRequested = false;
killGateway();
}
+
+ sShuttingDown = true;
+ mPump = NULL;
}
//---------------------------------------------------
@@ -527,7 +534,7 @@ void LLVivoxVoiceClient::connectorCreate()
<< "<FileNameSuffix>.log</FileNameSuffix>"
<< "<LogLevel>" << vivoxLogLevel << "</LogLevel>"
<< "</Logging>"
- << "<Application>" << LLVersionInfo::getChannel().c_str() << " " << LLVersionInfo::getVersion().c_str() << "</Application>"
+ << "<Application>" << LLVersionInfo::instance().getChannel() << " " << LLVersionInfo::instance().getVersion() << "</Application>"
//<< "<Application></Application>" //Name can cause problems per vivox.
<< "<MaxCalls>12</MaxCalls>"
<< "</Request>\n\n\n";
@@ -660,17 +667,38 @@ void LLVivoxVoiceClient::voiceControlCoro()
U32 retry = 0;
- while (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE)
+ while (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE && !sShuttingDown)
{
LL_DEBUGS("Voice") << "Suspending voiceControlCoro() momentarily for teleport. Tuning: " << mTuningMode << ". Relog: " << mRelogRequested << LL_ENDL;
llcoro::suspendUntilTimeout(1.0);
}
+ if (sShuttingDown)
+ {
+ mIsCoroutineActive = false;
+ return;
+ }
+
do
{
bool success = startAndConnectSession();
if (success)
{
+ // enable/disable the automatic VAD and explicitly set the initial values of
+ // the VAD variables ourselves when it is off - see SL-15072 for more details
+ // note: we set the other parameters too even if the auto VAD is on which is ok
+ unsigned int vad_auto = gSavedSettings.getU32("VivoxVadAuto");
+ unsigned int vad_hangover = gSavedSettings.getU32("VivoxVadHangover");
+ unsigned int vad_noise_floor = gSavedSettings.getU32("VivoxVadNoiseFloor");
+ unsigned int vad_sensitivity = gSavedSettings.getU32("VivoxVadSensitivity");
+ setupVADParams(vad_auto, vad_hangover, vad_noise_floor, vad_sensitivity);
+
+ // watch for changes to the VAD settings via Debug Settings UI and act on them accordingly
+ gSavedSettings.getControl("VivoxVadAuto")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+ gSavedSettings.getControl("VivoxVadHangover")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+ gSavedSettings.getControl("VivoxVadNoiseFloor")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+ gSavedSettings.getControl("VivoxVadSensitivity")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+
if (mTuningMode)
{
performMicTuning();
@@ -691,7 +719,7 @@ void LLVivoxVoiceClient::voiceControlCoro()
<< "disconnected"
<< " RelogRequested=" << mRelogRequested
<< LL_ENDL;
- if (mRelogRequested)
+ if (mRelogRequested && !sShuttingDown)
{
if (!success)
{
@@ -706,14 +734,14 @@ void LLVivoxVoiceClient::voiceControlCoro()
LL_INFOS("Voice") << "will attempt to reconnect to voice" << LL_ENDL;
}
- while (isGatewayRunning() || gAgent.getTeleportState() != LLAgent::TELEPORT_NONE)
+ while (isGatewayRunning() || (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE && !sShuttingDown))
{
LL_INFOS("Voice") << "waiting for SLVoice to exit" << LL_ENDL;
llcoro::suspendUntilTimeout(1.0);
}
}
}
- while (mVoiceEnabled && mRelogRequested);
+ while (mVoiceEnabled && mRelogRequested && !sShuttingDown);
mIsCoroutineActive = false;
LL_INFOS("Voice") << "exiting" << LL_ENDL;
}
@@ -758,7 +786,7 @@ bool LLVivoxVoiceClient::endAndDisconnectSession()
bool LLVivoxVoiceClient::callbackEndDaemon(const LLSD& data)
{
- if (!LLAppViewer::isExiting() && mVoiceEnabled)
+ if (!sShuttingDown && mVoiceEnabled)
{
LL_WARNS("Voice") << "SLVoice terminated " << ll_stream_notation_sd(data) << LL_ENDL;
terminateAudioSession(false);
@@ -806,6 +834,21 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
LLProcess::Params params;
params.executable = exe_path;
+ // VOICE-88: Cycle through [portbase..portbase+portrange) on
+ // successive tries because attempting to relaunch (after manually
+ // disabling and then re-enabling voice) with the same port can
+ // 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 const U32 portrange = 100;
+ std::string host(gSavedSettings.getString("VivoxVoiceHost"));
+ U32 port = portbase + portoffset;
+ portoffset = (portoffset + 1) % portrange;
+ params.args.add("-i");
+ params.args.add(STRINGIZE(host << ':' << port));
+
std::string loglevel = gSavedSettings.getString("VivoxDebugLevel");
if (loglevel.empty())
{
@@ -862,7 +905,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
sGatewayPtr = LLProcess::create(params);
- mDaemonHost = LLHost(gSavedSettings.getString("VivoxVoiceHost").c_str(), gSavedSettings.getU32("VivoxVoicePort"));
+ mDaemonHost = LLHost(host.c_str(), port);
}
else
{
@@ -900,7 +943,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
LL_DEBUGS("Voice") << "Connecting to vivox daemon:" << mDaemonHost << LL_ENDL;
LLVoiceVivoxStats::getInstance()->reset();
- while (!mConnected)
+ while (!mConnected && !sShuttingDown)
{
LLVoiceVivoxStats::getInstance()->connectionAttemptStart();
LL_DEBUGS("Voice") << "Attempting to connect to vivox daemon: " << mDaemonHost << LL_ENDL;
@@ -919,12 +962,22 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
}
//---------------------------------------------------------------------
+ if (sShuttingDown && !mConnected)
+ {
+ return false;
+ }
+
llcoro::suspendUntilTimeout(UPDATE_THROTTLE_SECONDS);
- while (!mPump)
- { // Can't do this until we have the pump available.
+ while (!mPump && !sShuttingDown)
+ { // Can't use the pump until we have it available.
llcoro::suspend();
}
+
+ if (sShuttingDown)
+ {
+ return false;
+ }
// MBW -- Note to self: pumps and pipes examples in
// indra/test/io.cpp
@@ -937,8 +990,10 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
readChain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(mSocket)));
readChain.push_back(LLIOPipe::ptr_t(new LLVivoxProtocolParser()));
+
mPump->addChain(readChain, NEVER_CHAIN_EXPIRY_SECS);
+
//---------------------------------------------------------------------
llcoro::suspendUntilTimeout(UPDATE_THROTTLE_SECONDS);
@@ -955,12 +1010,17 @@ bool LLVivoxVoiceClient::provisionVoiceAccount()
{
LL_INFOS("Voice") << "Provisioning voice account." << LL_ENDL;
- while (!gAgent.getRegion() || !gAgent.getRegion()->capabilitiesReceived())
+ while ((!gAgent.getRegion() || !gAgent.getRegion()->capabilitiesReceived()) && !sShuttingDown)
{
LL_DEBUGS("Voice") << "no capabilities for voice provisioning; waiting " << LL_ENDL;
// *TODO* Pump a message for wake up.
llcoro::suspend();
}
+
+ if (sShuttingDown)
+ {
+ return false;
+ }
std::string url = gAgent.getRegionCapability("ProvisionVoiceAccountRequest");
@@ -999,10 +1059,15 @@ bool LLVivoxVoiceClient::provisionVoiceAccount()
{
provisioned = true;
}
- } while (!provisioned && retryCount <= PROVISION_RETRY_MAX);
+ } while (!provisioned && retryCount <= PROVISION_RETRY_MAX && !sShuttingDown);
+
+ if (sShuttingDown && !provisioned)
+ {
+ return false;
+ }
LLVoiceVivoxStats::getInstance()->provisionAttemptEnd(provisioned);
- if (! provisioned )
+ if (!provisioned)
{
LL_WARNS("Voice") << "Could not access voice provision cap after " << retryCount << " attempts." << LL_ENDL;
return false;
@@ -1038,13 +1103,16 @@ bool LLVivoxVoiceClient::provisionVoiceAccount()
bool LLVivoxVoiceClient::establishVoiceConnection()
{
- LLEventPump &voiceConnectPump = LLEventPumps::instance().obtain("vivoxClientPump");
-
if (!mVoiceEnabled && mIsInitialized)
{
LL_WARNS("Voice") << "cannot establish connection; enabled "<<mVoiceEnabled<<" initialized "<<mIsInitialized<<LL_ENDL;
return false;
}
+
+ if (sShuttingDown)
+ {
+ return false;
+ }
LLSD result;
bool connected(false);
@@ -1056,7 +1124,7 @@ bool LLVivoxVoiceClient::establishVoiceConnection()
connectorCreate();
do
{
- result = llcoro::suspendUntilEventOn(voiceConnectPump);
+ result = llcoro::suspendUntilEventOn(mVivoxPump);
LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
if (result.has("connector"))
@@ -1065,7 +1133,7 @@ bool LLVivoxVoiceClient::establishVoiceConnection()
connected = LLSD::Boolean(result["connector"]);
if (!connected)
{
- if (result.has("retry") && ++retries <= CONNECT_RETRY_MAX)
+ if (result.has("retry") && ++retries <= CONNECT_RETRY_MAX && !sShuttingDown)
{
F32 timeout = LLSD::Real(result["retry"]);
timeout *= retries;
@@ -1093,7 +1161,7 @@ bool LLVivoxVoiceClient::establishVoiceConnection()
LL_DEBUGS("Voice") << (connected ? "" : "not ") << "connected, "
<< (giving_up ? "" : "not ") << "giving up"
<< LL_ENDL;
- } while (!connected && !giving_up);
+ } while (!connected && !giving_up && !sShuttingDown);
if (giving_up)
{
@@ -1108,7 +1176,6 @@ bool LLVivoxVoiceClient::establishVoiceConnection()
bool LLVivoxVoiceClient::breakVoiceConnection(bool corowait)
{
LL_DEBUGS("Voice") << "( wait=" << corowait << ")" << LL_ENDL;
- LLEventPump &voicePump = LLEventPumps::instance().obtain("vivoxClientPump");
bool retval(true);
mShutdownComplete = false;
@@ -1118,7 +1185,7 @@ bool LLVivoxVoiceClient::breakVoiceConnection(bool corowait)
{
LLSD timeoutResult(LLSDMap("connector", "timeout"));
- LLSD result = llcoro::suspendUntilEventOnWithTimeout(voicePump, LOGOUT_ATTEMPT_TIMEOUT, timeoutResult);
+ LLSD result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, LOGOUT_ATTEMPT_TIMEOUT, timeoutResult);
LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
retval = result.has("connector");
@@ -1140,7 +1207,7 @@ bool LLVivoxVoiceClient::breakVoiceConnection(bool corowait)
{
mConnected = false;
LLSD vivoxevent(LLSDMap("connector", LLSD::Boolean(false)));
- LLEventPumps::instance().post("vivoxClientPump", vivoxevent);
+ mVivoxPump.post(vivoxevent);
}
mShutdownComplete = true;
}
@@ -1157,8 +1224,6 @@ bool LLVivoxVoiceClient::breakVoiceConnection(bool corowait)
bool LLVivoxVoiceClient::loginToVivox()
{
- LLEventPump &voicePump = LLEventPumps::instance().obtain("vivoxClientPump");
-
LLSD timeoutResult(LLSDMap("login", "timeout"));
int loginRetryCount(0);
@@ -1176,14 +1241,14 @@ bool LLVivoxVoiceClient::loginToVivox()
send_login = false;
}
- LLSD result = llcoro::suspendUntilEventOnWithTimeout(voicePump, LOGIN_ATTEMPT_TIMEOUT, timeoutResult);
+ LLSD result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, LOGIN_ATTEMPT_TIMEOUT, timeoutResult);
LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
if (result.has("login"))
{
std::string loginresp = result["login"];
- if ((loginresp == "retry") || (loginresp == "timeout"))
+ if (((loginresp == "retry") || (loginresp == "timeout")) && !sShuttingDown)
{
LL_WARNS("Voice") << "login failed with status '" << loginresp << "' "
<< " count " << loginRetryCount << "/" << LOGIN_RETRY_MAX
@@ -1225,9 +1290,14 @@ bool LLVivoxVoiceClient::loginToVivox()
{
account_login = true;
}
+ else if (sShuttingDown)
+ {
+ mIsLoggingIn = false;
+ return false;
+ }
}
- } while (!response_ok || !account_login);
+ } while ((!response_ok || !account_login) && !sShuttingDown);
mRelogRequested = false;
mIsLoggedIn = true;
@@ -1259,17 +1329,23 @@ void LLVivoxVoiceClient::logoutOfVivox(bool wait)
if (wait)
{
- LLEventPump &voicePump = LLEventPumps::instance().obtain("vivoxClientPump");
LLSD timeoutResult(LLSDMap("logout", "timeout"));
+ LLSD result;
- LL_DEBUGS("Voice")
- << "waiting for logout response on "
- << voicePump.getName()
- << LL_ENDL;
-
- LLSD result = llcoro::suspendUntilEventOnWithTimeout(voicePump, LOGOUT_ATTEMPT_TIMEOUT, timeoutResult);
-
- LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
+ do
+ {
+ LL_DEBUGS("Voice")
+ << "waiting for logout response on "
+ << mVivoxPump.getName()
+ << LL_ENDL;
+
+ result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, LOGOUT_ATTEMPT_TIMEOUT, timeoutResult);
+
+ LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
+ // Don't get confused by prior queued events -- note that it's
+ // very important that mVivoxPump is an LLEventMailDrop, which
+ // does queue events.
+ } while (! result["logout"]);
}
else
{
@@ -1283,8 +1359,6 @@ void LLVivoxVoiceClient::logoutOfVivox(bool wait)
bool LLVivoxVoiceClient::retrieveVoiceFonts()
{
- LLEventPump &voicePump = LLEventPumps::instance().obtain("vivoxClientPump");
-
// Request the set of available voice fonts.
refreshVoiceEffectLists(true);
@@ -1292,7 +1366,7 @@ bool LLVivoxVoiceClient::retrieveVoiceFonts()
LLSD result;
do
{
- result = llcoro::suspendUntilEventOn(voicePump);
+ result = llcoro::suspendUntilEventOn(mVivoxPump);
LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
if (result.has("voice_fonts"))
@@ -1408,7 +1482,6 @@ bool LLVivoxVoiceClient::requestParcelVoiceInfo()
bool LLVivoxVoiceClient::addAndJoinSession(const sessionStatePtr_t &nextSession)
{
- LLEventPump &voicePump = LLEventPumps::instance().obtain("vivoxClientPump");
mIsJoiningSession = true;
sessionStatePtr_t oldSession = mAudioSession;
@@ -1497,7 +1570,7 @@ bool LLVivoxVoiceClient::addAndJoinSession(const sessionStatePtr_t &nextSession)
// We are about to start a whole new session. Anything that MIGHT still be in our
// maildrop is going to be stale and cause us much wailing and gnashing of teeth.
// Just flush it all out and start new.
- voicePump.flush();
+ mVivoxPump.discard();
// It appears that I need to wait for BOTH the SessionGroup.AddSession response and the SessionStateChangeEvent with state 4
// before continuing from this state. They can happen in either order, and if I don't wait for both, things can get stuck.
@@ -1505,7 +1578,7 @@ bool LLVivoxVoiceClient::addAndJoinSession(const sessionStatePtr_t &nextSession)
// This is a cheap way to make sure both have happened before proceeding.
do
{
- result = llcoro::suspendUntilEventOnWithTimeout(voicePump, SESSION_JOIN_TIMEOUT, timeoutResult);
+ result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, SESSION_JOIN_TIMEOUT, timeoutResult);
LL_INFOS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
if (result.has("session"))
@@ -1619,13 +1692,12 @@ bool LLVivoxVoiceClient::terminateAudioSession(bool wait)
if (wait)
{
- LLEventPump &voicePump = LLEventPumps::instance().obtain("vivoxClientPump");
LLSD result;
do
{
LLSD timeoutResult(LLSDMap("session", "timeout"));
- result = llcoro::suspendUntilEventOnWithTimeout(voicePump, LOGOUT_ATTEMPT_TIMEOUT, timeoutResult);
+ result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, LOGOUT_ATTEMPT_TIMEOUT, timeoutResult);
LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
if (result.has("session"))
@@ -1678,12 +1750,12 @@ bool LLVivoxVoiceClient::terminateAudioSession(bool wait)
// the region chat.
mSessionTerminateRequested = false;
- bool status=((mVoiceEnabled || !mIsInitialized) && !mRelogRequested && !LLApp::isExiting());
+ bool status=((mVoiceEnabled || !mIsInitialized) && !mRelogRequested && !sShuttingDown);
LL_DEBUGS("Voice") << "exiting"
<< " VoiceEnabled " << mVoiceEnabled
<< " IsInitialized " << mIsInitialized
<< " RelogRequested " << mRelogRequested
- << " AppExiting " << LLApp::isExiting()
+ << " ShuttingDown " << (sShuttingDown ? "TRUE" : "FALSE")
<< " returning " << status
<< LL_ENDL;
return status;
@@ -1700,6 +1772,12 @@ bool LLVivoxVoiceClient::waitForChannel()
return false;
}
+ if (sShuttingDown)
+ {
+ logoutOfVivox(true);
+ return false;
+ }
+
if (LLVoiceClient::instance().getVoiceEffectEnabled())
{
retrieveVoiceFonts();
@@ -1721,6 +1799,12 @@ bool LLVivoxVoiceClient::waitForChannel()
mIsProcessingChannels = true;
llcoro::suspend();
+ if (sShuttingDown)
+ {
+ mRelogRequested = false;
+ break;
+ }
+
if (mTuningMode)
{
performMicTuning();
@@ -1765,7 +1849,14 @@ bool LLVivoxVoiceClient::waitForChannel()
{
llcoro::suspendUntilTimeout(1.0);
}
- } while (mVoiceEnabled && !mRelogRequested);
+
+ if (sShuttingDown)
+ {
+ mRelogRequested = false;
+ break;
+ }
+
+ } while (mVoiceEnabled && !mRelogRequested && !sShuttingDown);
LL_DEBUGS("Voice")
<< "leaving inner waitForChannel loop"
@@ -1787,14 +1878,14 @@ bool LLVivoxVoiceClient::waitForChannel()
return false;
}
}
- } while (mVoiceEnabled && mRelogRequested && isGatewayRunning());
+ } while (mVoiceEnabled && mRelogRequested && isGatewayRunning() && !sShuttingDown);
LL_DEBUGS("Voice")
<< "exiting"
<< " RelogRequested=" << mRelogRequested
<< " VoiceEnabled=" << mVoiceEnabled
<< LL_ENDL;
- return true;
+ return !sShuttingDown;
}
bool LLVivoxVoiceClient::runSession(const sessionStatePtr_t &session)
@@ -1822,7 +1913,6 @@ bool LLVivoxVoiceClient::runSession(const sessionStatePtr_t &session)
LLSD timeoutEvent(LLSDMap("timeout", LLSD::Boolean(true)));
- LLEventPump &voicePump = LLEventPumps::instance().obtain("vivoxClientPump");
mIsInChannel = true;
mMuteMicDirty = true;
@@ -1874,7 +1964,7 @@ bool LLVivoxVoiceClient::runSession(const sessionStatePtr_t &session)
sendLocalAudioUpdates();
mIsInitialized = true;
- LLSD result = llcoro::suspendUntilEventOnWithTimeout(voicePump, UPDATE_THROTTLE_SECONDS, timeoutEvent);
+ LLSD result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, UPDATE_THROTTLE_SECONDS, timeoutEvent);
if (!result.has("timeout")) // logging the timeout event spams the log
{
LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
@@ -1945,14 +2035,13 @@ void LLVivoxVoiceClient::sendCaptureAndRenderDevices()
void LLVivoxVoiceClient::recordingAndPlaybackMode()
{
LL_INFOS("Voice") << "In voice capture/playback mode." << LL_ENDL;
- LLEventPump &voicePump = LLEventPumps::instance().obtain("vivoxClientPump");
while (true)
{
LLSD command;
do
{
- command = llcoro::suspendUntilEventOn(voicePump);
+ command = llcoro::suspendUntilEventOn(mVivoxPump);
LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(command) << LL_ENDL;
} while (!command.has("recplay"));
@@ -1985,7 +2074,6 @@ int LLVivoxVoiceClient::voiceRecordBuffer()
LL_INFOS("Voice") << "Recording voice buffer" << LL_ENDL;
- LLEventPump &voicePump = LLEventPumps::instance().obtain("vivoxClientPump");
LLSD result;
captureBufferRecordStartSendMessage();
@@ -1993,7 +2081,7 @@ int LLVivoxVoiceClient::voiceRecordBuffer()
do
{
- result = llcoro::suspendUntilEventOnWithTimeout(voicePump, CAPTURE_BUFFER_MAX_TIME, timeoutResult);
+ result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, CAPTURE_BUFFER_MAX_TIME, timeoutResult);
LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
} while (!result.has("recplay"));
@@ -2015,7 +2103,6 @@ int LLVivoxVoiceClient::voicePlaybackBuffer()
LL_INFOS("Voice") << "Playing voice buffer" << LL_ENDL;
- LLEventPump &voicePump = LLEventPumps::instance().obtain("vivoxClientPump");
LLSD result;
do
@@ -2030,7 +2117,7 @@ int LLVivoxVoiceClient::voicePlaybackBuffer()
// Update UI, should really use a separate callback.
notifyVoiceFontObservers();
- result = llcoro::suspendUntilEventOnWithTimeout(voicePump, CAPTURE_BUFFER_MAX_TIME, timeoutResult);
+ result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, CAPTURE_BUFFER_MAX_TIME, timeoutResult);
LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
} while (!result.has("recplay"));
@@ -2551,7 +2638,7 @@ void LLVivoxVoiceClient::tuningStart()
mTuningMode = true;
if (!mIsCoroutineActive)
{
- LLCoros::instance().launch("LLVivoxVoiceClient::voiceControlCoro();",
+ LLCoros::instance().launch("LLVivoxVoiceClient::voiceControlCoro",
boost::bind(&LLVivoxVoiceClient::voiceControlCoro, LLVivoxVoiceClient::getInstance()));
}
else if (mIsInChannel)
@@ -3158,6 +3245,73 @@ void LLVivoxVoiceClient::sendLocalAudioUpdates()
}
}
+/**
+ * Because of the recurring voice cutout issues (SL-15072) we are going to try
+ * to disable the automatic VAD (Voice Activity Detection) and set the associated
+ * parameters directly. We will expose them via Debug Settings and that should
+ * let us iterate on a collection of values that work for us. Hopefully!
+ *
+ * From the VIVOX Docs:
+ *
+ * VadAuto: A flag indicating if the automatic VAD is enabled (1) or disabled (0)
+ *
+ * VadHangover: The time (in milliseconds) that it takes
+ * for the VAD to switch back to silence from speech mode after the last speech
+ * frame has been detected.
+ *
+ * VadNoiseFloor: A dimensionless value between 0 and
+ * 20000 (default 576) that controls the maximum level at which the noise floor
+ * may be set at by the VAD's noise tracking. Too low of a value will make noise
+ * tracking ineffective (A value of 0 disables noise tracking and the VAD then
+ * relies purely on the sensitivity property). Too high of a value will make
+ * long speech classifiable as noise.
+ *
+ * VadSensitivity: A dimensionless value between 0 and
+ * 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds
+ * to decreasing the sensitivity of the VAD (i.e. '0' is most sensitive,
+ * while 100 is 'least sensitive')
+ */
+void LLVivoxVoiceClient::setupVADParams(unsigned int vad_auto,
+ unsigned int vad_hangover,
+ unsigned int vad_noise_floor,
+ unsigned int vad_sensitivity)
+{
+ std::ostringstream stream;
+
+ LL_INFOS("Voice") << "Setting the automatic VAD to "
+ << (vad_auto ? "True" : "False")
+ << " and discrete values to"
+ << " VadHangover = " << vad_hangover
+ << ", VadSensitivity = " << vad_sensitivity
+ << ", VadNoiseFloor = " << vad_noise_floor
+ << LL_ENDL;
+
+ // Create a request to set the VAD parameters:
+ stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetVadProperties.1\">"
+ << "<VadAuto>" << vad_auto << "</VadAuto>"
+ << "<VadHangover>" << vad_hangover << "</VadHangover>"
+ << "<VadSensitivity>" << vad_sensitivity << "</VadSensitivity>"
+ << "<VadNoiseFloor>" << vad_noise_floor << "</VadNoiseFloor>"
+ << "</Request>\n\n\n";
+
+ if (!stream.str().empty())
+ {
+ writeString(stream.str());
+ }
+}
+
+void LLVivoxVoiceClient::onVADSettingsChange()
+{
+ // pick up the VAD variables (one of which was changed)
+ unsigned int vad_auto = gSavedSettings.getU32("VivoxVadAuto");
+ unsigned int vad_hangover = gSavedSettings.getU32("VivoxVadHangover");
+ unsigned int vad_noise_floor = gSavedSettings.getU32("VivoxVadNoiseFloor");
+ unsigned int vad_sensitivity = gSavedSettings.getU32("VivoxVadSensitivity");
+
+ // build a VAD params change request and send it to SLVoice
+ setupVADParams(vad_auto, vad_hangover, vad_noise_floor, vad_sensitivity);
+}
+
/////////////////////////////
// Response/Event handlers
@@ -3214,7 +3368,7 @@ void LLVivoxVoiceClient::connectorCreateResponse(int statusCode, std::string &st
result["connector"] = LLSD::Boolean(false);
}
- LLEventPumps::instance().post("vivoxClientPump", result);
+ mVivoxPump.post(result);
}
void LLVivoxVoiceClient::loginResponse(int statusCode, std::string &statusString, std::string &accountHandle, int numberOfAliases)
@@ -3244,7 +3398,7 @@ void LLVivoxVoiceClient::loginResponse(int statusCode, std::string &statusString
result["login"] = LLSD::String("response_ok");
}
- LLEventPumps::instance().post("vivoxClientPump", result);
+ mVivoxPump.post(result);
}
@@ -3270,7 +3424,7 @@ void LLVivoxVoiceClient::sessionCreateResponse(std::string &requestId, int statu
("session", "failed")
("reason", LLSD::Integer(statusCode)));
- LLEventPumps::instance().post("vivoxClientPump", vivoxevent);
+ mVivoxPump.post(vivoxevent);
}
else
{
@@ -3288,7 +3442,7 @@ void LLVivoxVoiceClient::sessionCreateResponse(std::string &requestId, int statu
LLSD vivoxevent(LLSDMap("handle", LLSD::String(sessionHandle))
("session", "created"));
- LLEventPumps::instance().post("vivoxClientPump", vivoxevent);
+ mVivoxPump.post(vivoxevent);
}
}
@@ -3313,7 +3467,7 @@ void LLVivoxVoiceClient::sessionGroupAddSessionResponse(std::string &requestId,
LLSD vivoxevent(LLSDMap("handle", LLSD::String(sessionHandle))
("session", "failed"));
- LLEventPumps::instance().post("vivoxClientPump", vivoxevent);
+ mVivoxPump.post(vivoxevent);
}
else
{
@@ -3332,7 +3486,7 @@ void LLVivoxVoiceClient::sessionGroupAddSessionResponse(std::string &requestId,
LLSD vivoxevent(LLSDMap("handle", LLSD::String(sessionHandle))
("session", "added"));
- LLEventPumps::instance().post("vivoxClientPump", vivoxevent);
+ mVivoxPump.post(vivoxevent);
}
}
@@ -3375,7 +3529,7 @@ void LLVivoxVoiceClient::logoutResponse(int statusCode, std::string &statusStrin
}
LLSD vivoxevent(LLSDMap("logout", LLSD::Boolean(true)));
- LLEventPumps::instance().post("vivoxClientPump", vivoxevent);
+ mVivoxPump.post(vivoxevent);
}
void LLVivoxVoiceClient::connectorShutdownResponse(int statusCode, std::string &statusString)
@@ -3391,7 +3545,7 @@ void LLVivoxVoiceClient::connectorShutdownResponse(int statusCode, std::string &
LLSD vivoxevent(LLSDMap("connector", LLSD::Boolean(false)));
- LLEventPumps::instance().post("vivoxClientPump", vivoxevent);
+ mVivoxPump.post(vivoxevent);
}
void LLVivoxVoiceClient::sessionAddedEvent(
@@ -3500,7 +3654,7 @@ void LLVivoxVoiceClient::joinedAudioSession(const sessionStatePtr_t &session)
LLSD vivoxevent(LLSDMap("handle", LLSD::String(session->mHandle))
("session", "joined"));
- LLEventPumps::instance().post("vivoxClientPump", vivoxevent);
+ mVivoxPump.post(vivoxevent);
// Add the current user as a participant here.
participantStatePtr_t participant(session->addParticipant(sipURIFromName(mAccountName)));
@@ -3644,7 +3798,7 @@ void LLVivoxVoiceClient::leftAudioSession(const sessionStatePtr_t &session)
LLSD vivoxevent(LLSDMap("handle", LLSD::String(session->mHandle))
("session", "removed"));
- LLEventPumps::instance().post("vivoxClientPump", vivoxevent);
+ mVivoxPump.post(vivoxevent);
}
}
@@ -3672,7 +3826,7 @@ void LLVivoxVoiceClient::accountLoginStateChangeEvent(
case 1:
levent["login"] = LLSD::String("account_login");
- LLEventPumps::instance().post("vivoxClientPump", levent);
+ mVivoxPump.post(levent);
break;
case 2:
break;
@@ -3680,7 +3834,7 @@ void LLVivoxVoiceClient::accountLoginStateChangeEvent(
case 3:
levent["login"] = LLSD::String("account_loggingOut");
- LLEventPumps::instance().post("vivoxClientPump", levent);
+ mVivoxPump.post(levent);
break;
case 4:
@@ -3693,7 +3847,7 @@ void LLVivoxVoiceClient::accountLoginStateChangeEvent(
case 0:
levent["login"] = LLSD::String("account_logout");
- LLEventPumps::instance().post("vivoxClientPump", levent);
+ mVivoxPump.post(levent);
break;
default:
@@ -3728,7 +3882,7 @@ void LLVivoxVoiceClient::mediaCompletionEvent(std::string &sessionGroupHandle, s
}
if (!result.isUndefined())
- LLEventPumps::instance().post("vivoxClientPump", result);
+ mVivoxPump.post(result);
}
void LLVivoxVoiceClient::mediaStreamUpdatedEvent(
@@ -5146,7 +5300,7 @@ void LLVivoxVoiceClient::setVoiceEnabled(bool enabled)
if (!mIsCoroutineActive)
{
- LLCoros::instance().launch("LLVivoxVoiceClient::voiceControlCoro();",
+ LLCoros::instance().launch("LLVivoxVoiceClient::voiceControlCoro",
boost::bind(&LLVivoxVoiceClient::voiceControlCoro, LLVivoxVoiceClient::getInstance()));
}
else
@@ -5158,6 +5312,7 @@ void LLVivoxVoiceClient::setVoiceEnabled(bool enabled)
{
// Turning voice off looses your current channel -- this makes sure the UI isn't out of sync when you re-enable it.
LLVoiceChannel::getCurrentVoiceChannel()->deactivate();
+ gAgent.setVoiceConnected(false);
status = LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED;
}
@@ -6540,7 +6695,7 @@ void LLVivoxVoiceClient::accountGetSessionFontsResponse(int statusCode, const st
// receiving the last one.
LLSD result(LLSDMap("voice_fonts", LLSD::Boolean(true)));
- LLEventPumps::instance().post("vivoxClientPump", result);
+ mVivoxPump.post(result);
}
notifyVoiceFontObservers();
mVoiceFontsReceived = true;
@@ -6691,7 +6846,7 @@ void LLVivoxVoiceClient::enablePreviewBuffer(bool enable)
else
result["recplay"] = "quit";
- LLEventPumps::instance().post("vivoxClientPump", result);
+ mVivoxPump.post(result);
if(mCaptureBufferMode && mIsInChannel)
{
@@ -6712,7 +6867,7 @@ void LLVivoxVoiceClient::recordPreviewBuffer()
mCaptureBufferRecording = true;
LLSD result(LLSDMap("recplay", "record"));
- LLEventPumps::instance().post("vivoxClientPump", result);
+ mVivoxPump.post(result);
}
void LLVivoxVoiceClient::playPreviewBuffer(const LLUUID& effect_id)
@@ -6735,7 +6890,7 @@ void LLVivoxVoiceClient::playPreviewBuffer(const LLUUID& effect_id)
mCaptureBufferPlaying = true;
LLSD result(LLSDMap("recplay", "playback"));
- LLEventPumps::instance().post("vivoxClientPump", result);
+ mVivoxPump.post(result);
}
void LLVivoxVoiceClient::stopPreviewBuffer()
@@ -6744,7 +6899,7 @@ void LLVivoxVoiceClient::stopPreviewBuffer()
mCaptureBufferPlaying = false;
LLSD result(LLSDMap("recplay", "quit"));
- LLEventPumps::instance().post("vivoxClientPump", result);
+ mVivoxPump.post(result);
}
bool LLVivoxVoiceClient::isPreviewRecording()
@@ -7509,6 +7664,18 @@ void LLVivoxProtocolParser::processResponse(std::string tag)
{
LLVivoxVoiceClient::getInstance()->accountGetTemplateFontsResponse(statusCode, statusString);
}
+ else if (!stricmp(actionCstr, "Aux.SetVadProperties.1"))
+ {
+ // both values of statusCode (old and more recent) indicate valid requests
+ if (statusCode != 0 && statusCode != 200)
+ {
+ LL_WARNS("Voice") << "Aux.SetVadProperties.1 request failed: "
+ << "statusCode: " << statusCode
+ << " and "
+ << "statusString: " << statusString
+ << LL_ENDL;
+ }
+ }
/*
else if (!stricmp(actionCstr, "Account.ChannelGetList.1"))
{