diff options
author | David Seikel | 2011-06-04 00:17:28 +1000 |
---|---|---|
committer | David Seikel | 2011-06-04 00:17:28 +1000 |
commit | 492eaaf4eec82327116f2605e3d8becf94bec1b3 (patch) | |
tree | dcddd674cb4861445c3ec5aaa59325b99a437614 /linden/indra/newview/llvoiceclient.cpp | |
parent | Set the real bare minimum prim size to 0.00001, as 0 sized objects cause bugs. (diff) | |
parent | Fixing the menu to actually use its color options reveals how broken the whol... (diff) | |
download | meta-impy-492eaaf4eec82327116f2605e3d8becf94bec1b3.zip meta-impy-492eaaf4eec82327116f2605e3d8becf94bec1b3.tar.gz meta-impy-492eaaf4eec82327116f2605e3d8becf94bec1b3.tar.bz2 meta-impy-492eaaf4eec82327116f2605e3d8becf94bec1b3.tar.xz |
Merge branch 'next' of git://github.com/jacek/imprudence into next
Conflicts (manually merged):
linden/indra/llcommon/llversionviewer.h
linden/indra/llvfs/lldir.cpp
linden/indra/llvfs/lldir_mac.cpp
linden/indra/newview/CMakeLists.txt
linden/indra/newview/English.lproj/InfoPlist.strings
linden/indra/newview/Info-Imprudence.plist
linden/indra/newview/Info-meta-impy.plist
linden/indra/newview/llappviewer.cpp
linden/indra/newview/llpanellogin.cpp
linden/indra/newview/packaging/mac/Info.plist.in
linden/indra/newview/res/viewerRes.rc
linden/indra/newview/skins/default/xui/en-us/floater_about.xml
linden/indra/newview/skins/default/xui/en-us/panel_preferences_advanced.xml
linden/indra/newview/skins/default/xui/en-us/panel_preferences_graphics1.xml
linden/indra/newview/skins/default/xui/en-us/panel_preferences_im.xml
linden/indra/newview/skins/default/xui/en-us/panel_preferences_skins.xml
linden/indra/newview/skins/default/xui/en-us/panel_preferences_web.xml
linden/indra/newview/skins/default/xui/zh/menu_viewer.xml
linden/indra/newview/skins/default/xui/zh/panel_group_general.xml
linden/indra/newview/viewer_manifest.py
linden/indra/newview/viewerversion.cpp
linden/indra/newview/viewerversion.h
linden/install.xml
Also some post merge tweaks.
Diffstat (limited to 'linden/indra/newview/llvoiceclient.cpp')
-rw-r--r-- | linden/indra/newview/llvoiceclient.cpp | 805 |
1 files changed, 484 insertions, 321 deletions
diff --git a/linden/indra/newview/llvoiceclient.cpp b/linden/indra/newview/llvoiceclient.cpp index 63362be..4b5d3ce 100644 --- a/linden/indra/newview/llvoiceclient.cpp +++ b/linden/indra/newview/llvoiceclient.cpp | |||
@@ -139,22 +139,23 @@ class LLViewerVoiceAccountProvisionResponder : | |||
139 | public LLHTTPClient::Responder | 139 | public LLHTTPClient::Responder |
140 | { | 140 | { |
141 | public: | 141 | public: |
142 | LLViewerVoiceAccountProvisionResponder(int retries) | 142 | LLViewerVoiceAccountProvisionResponder(int retries, LLUUID response_id) |
143 | { | 143 | { |
144 | mRetries = retries; | 144 | mRetries = retries; |
145 | mResponseID = response_id; | ||
145 | } | 146 | } |
146 | 147 | ||
147 | virtual void error(U32 status, const std::string& reason) | 148 | virtual void error(U32 status, const std::string& reason) |
148 | { | 149 | { |
149 | if ( mRetries > 0 ) | 150 | if ( mRetries > 0 ) |
150 | { | 151 | { |
151 | LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, retrying. status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL; | 152 | LL_DEBUGS("VoiceCaps") << "ProvisionVoiceAccountRequest returned an error, retrying. status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL; |
152 | if ( gVoiceClient ) gVoiceClient->requestVoiceAccountProvision( | 153 | if ( gVoiceClient ) gVoiceClient->requestVoiceAccountProvision( |
153 | mRetries - 1); | 154 | mRetries - 1); |
154 | } | 155 | } |
155 | else | 156 | else |
156 | { | 157 | { |
157 | LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, too many retries (giving up). status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL; | 158 | LL_DEBUGS("VoiceCaps") << "ProvisionVoiceAccountRequest returned an error, too many retries (giving up). status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL; |
158 | if ( gVoiceClient ) gVoiceClient->giveUp(); | 159 | if ( gVoiceClient ) gVoiceClient->giveUp(); |
159 | } | 160 | } |
160 | } | 161 | } |
@@ -166,7 +167,7 @@ public: | |||
166 | std::string voice_sip_uri_hostname; | 167 | std::string voice_sip_uri_hostname; |
167 | std::string voice_account_server_uri; | 168 | std::string voice_account_server_uri; |
168 | 169 | ||
169 | LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << ll_pretty_print_sd(content) << LL_ENDL; | 170 | LL_DEBUGS("VoiceCaps") << "ProvisionVoiceAccountRequest response:" << ll_pretty_print_sd(content) << LL_ENDL; |
170 | 171 | ||
171 | if(content.has("voice_sip_uri_hostname")) | 172 | if(content.has("voice_sip_uri_hostname")) |
172 | voice_sip_uri_hostname = content["voice_sip_uri_hostname"].asString(); | 173 | voice_sip_uri_hostname = content["voice_sip_uri_hostname"].asString(); |
@@ -179,12 +180,14 @@ public: | |||
179 | content["username"].asString(), | 180 | content["username"].asString(), |
180 | content["password"].asString(), | 181 | content["password"].asString(), |
181 | voice_sip_uri_hostname, | 182 | voice_sip_uri_hostname, |
182 | voice_account_server_uri); | 183 | voice_account_server_uri, |
184 | mResponseID); | ||
183 | } | 185 | } |
184 | } | 186 | } |
185 | 187 | ||
186 | private: | 188 | private: |
187 | int mRetries; | 189 | int mRetries; |
190 | LLUUID mResponseID; | ||
188 | }; | 191 | }; |
189 | 192 | ||
190 | /** | 193 | /** |
@@ -364,7 +367,7 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl( | |||
364 | // If this message isn't set to be squelched, output the raw XML received. | 367 | // If this message isn't set to be squelched, output the raw XML received. |
365 | if(!squelchDebugOutput) | 368 | if(!squelchDebugOutput) |
366 | { | 369 | { |
367 | LL_DEBUGS("Voice") << "parsing: " << mInput.substr(start, delim - start) << LL_ENDL; | 370 | LL_DEBUGS("VivoxProtocolParser") << "parsing: " << mInput.substr(start, delim - start) << LL_ENDL; |
368 | } | 371 | } |
369 | 372 | ||
370 | start = delim + 3; | 373 | start = delim + 3; |
@@ -378,7 +381,7 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl( | |||
378 | if(!gVoiceClient->mConnected) | 381 | if(!gVoiceClient->mConnected) |
379 | { | 382 | { |
380 | // If voice has been disabled, we just want to close the socket. This does so. | 383 | // If voice has been disabled, we just want to close the socket. This does so. |
381 | LL_INFOS("Voice") << "returning STATUS_STOP" << LL_ENDL; | 384 | LL_INFOS("VivoxProtocolParser") << "returning STATUS_STOP" << LL_ENDL; |
382 | return STATUS_STOP; | 385 | return STATUS_STOP; |
383 | } | 386 | } |
384 | 387 | ||
@@ -452,13 +455,13 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr) | |||
452 | } | 455 | } |
453 | } | 456 | } |
454 | } | 457 | } |
455 | LL_DEBUGS("VivoxProtocolParser") << tag << " (" << responseDepth << ")" << LL_ENDL; | 458 | LL_DEBUGS("VivoxProtocolParserTag") << tag << " (" << responseDepth << ")" << LL_ENDL; |
456 | } | 459 | } |
457 | else | 460 | else |
458 | { | 461 | { |
459 | if (ignoringTags) | 462 | if (ignoringTags) |
460 | { | 463 | { |
461 | LL_DEBUGS("VivoxProtocolParser") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL; | 464 | LL_DEBUGS("VivoxProtocolParserTag") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL; |
462 | } | 465 | } |
463 | else | 466 | else |
464 | { | 467 | { |
@@ -471,7 +474,7 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr) | |||
471 | ignoreDepth = responseDepth; | 474 | ignoreDepth = responseDepth; |
472 | accumulateText = false; | 475 | accumulateText = false; |
473 | 476 | ||
474 | LL_DEBUGS("VivoxProtocolParser") << "starting ignore, ignoreDepth is " << ignoreDepth << LL_ENDL; | 477 | LL_DEBUGS("VivoxProtocolParserTag") << "starting ignore, ignoreDepth is " << ignoreDepth << LL_ENDL; |
475 | } | 478 | } |
476 | else if (!stricmp("CaptureDevices", tag)) | 479 | else if (!stricmp("CaptureDevices", tag)) |
477 | { | 480 | { |
@@ -512,18 +515,18 @@ void LLVivoxProtocolParser::EndTag(const char *tag) | |||
512 | { | 515 | { |
513 | if (ignoreDepth == responseDepth) | 516 | if (ignoreDepth == responseDepth) |
514 | { | 517 | { |
515 | LL_DEBUGS("VivoxProtocolParser") << "end of ignore" << LL_ENDL; | 518 | LL_DEBUGS("VivoxProtocolParserTag") << "end of ignore" << LL_ENDL; |
516 | ignoringTags = false; | 519 | ignoringTags = false; |
517 | } | 520 | } |
518 | else | 521 | else |
519 | { | 522 | { |
520 | LL_DEBUGS("VivoxProtocolParser") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL; | 523 | LL_DEBUGS("VivoxProtocolParserTag") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL; |
521 | } | 524 | } |
522 | } | 525 | } |
523 | 526 | ||
524 | if (!ignoringTags) | 527 | if (!ignoringTags) |
525 | { | 528 | { |
526 | LL_DEBUGS("VivoxProtocolParser") << "processing tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL; | 529 | LL_DEBUGS("VivoxProtocolParserTag") << "processing tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL; |
527 | 530 | ||
528 | // Closing a tag. Finalize the text we've accumulated and reset | 531 | // Closing a tag. Finalize the text we've accumulated and reset |
529 | if (!stricmp("ReturnCode", tag)) | 532 | if (!stricmp("ReturnCode", tag)) |
@@ -1008,12 +1011,13 @@ static LLVoiceClientFriendsObserver *friendslist_listener = NULL; | |||
1008 | class LLVoiceClientCapResponder : public LLHTTPClient::Responder | 1011 | class LLVoiceClientCapResponder : public LLHTTPClient::Responder |
1009 | { | 1012 | { |
1010 | public: | 1013 | public: |
1011 | LLVoiceClientCapResponder(void){}; | 1014 | LLVoiceClientCapResponder(LLUUID response_id):mResponseID(response_id) {}; |
1012 | 1015 | ||
1013 | virtual void error(U32 status, const std::string& reason); // called with bad status codes | 1016 | virtual void error(U32 status, const std::string& reason); // called with bad status codes |
1014 | virtual void result(const LLSD& content); | 1017 | virtual void result(const LLSD& content); |
1015 | 1018 | ||
1016 | private: | 1019 | private: |
1020 | LLUUID mResponseID; | ||
1017 | }; | 1021 | }; |
1018 | 1022 | ||
1019 | void LLVoiceClientCapResponder::error(U32 status, const std::string& reason) | 1023 | void LLVoiceClientCapResponder::error(U32 status, const std::string& reason) |
@@ -1027,7 +1031,7 @@ void LLVoiceClientCapResponder::result(const LLSD& content) | |||
1027 | { | 1031 | { |
1028 | LLSD::map_const_iterator iter; | 1032 | LLSD::map_const_iterator iter; |
1029 | 1033 | ||
1030 | LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << ll_pretty_print_sd(content) << LL_ENDL; | 1034 | LL_DEBUGS("VoiceCaps") << "ParcelVoiceInfoRequest response:\n" << ll_pretty_print_sd(content) << LL_ENDL; |
1031 | 1035 | ||
1032 | if ( content.has("voice_credentials") ) | 1036 | if ( content.has("voice_credentials") ) |
1033 | { | 1037 | { |
@@ -1045,7 +1049,7 @@ void LLVoiceClientCapResponder::result(const LLSD& content) | |||
1045 | voice_credentials["channel_credentials"].asString(); | 1049 | voice_credentials["channel_credentials"].asString(); |
1046 | } | 1050 | } |
1047 | 1051 | ||
1048 | gVoiceClient->setSpatialChannel(uri, credentials); | 1052 | gVoiceClient->setSpatialChannel(uri, credentials, mResponseID); |
1049 | } | 1053 | } |
1050 | } | 1054 | } |
1051 | 1055 | ||
@@ -1126,6 +1130,8 @@ LLVoiceClient::LLVoiceClient() | |||
1126 | mAudioSessionChanged = false; | 1130 | mAudioSessionChanged = false; |
1127 | 1131 | ||
1128 | // Initial dirty state | 1132 | // Initial dirty state |
1133 | mAccountActive = false; | ||
1134 | mVAPRequested = false; | ||
1129 | mSpatialCoordsDirty = false; | 1135 | mSpatialCoordsDirty = false; |
1130 | mPTTDirty = true; | 1136 | mPTTDirty = true; |
1131 | mFriendsListDirty = true; | 1137 | mFriendsListDirty = true; |
@@ -1169,11 +1175,13 @@ LLVoiceClient::LLVoiceClient() | |||
1169 | // Ignoring SIGCHLD should prevent zombies from being created. Alternately, we could use wait(), but I'd rather not do that. | 1175 | // Ignoring SIGCHLD should prevent zombies from being created. Alternately, we could use wait(), but I'd rather not do that. |
1170 | signal(SIGCHLD, SIG_IGN); | 1176 | signal(SIGCHLD, SIG_IGN); |
1171 | #endif | 1177 | #endif |
1172 | 1178 | if(!gSavedSettings.getBOOL("CmdLineDisableVoice"))//no reason to lag non-voice users | |
1173 | // set up state machine | 1179 | { |
1174 | setState(stateDisabled); | 1180 | // set up state machine |
1175 | 1181 | setState(stateDisabled); | |
1176 | gIdleCallbacks.addFunction(idle, this); | 1182 | |
1183 | gIdleCallbacks.addFunction(idle, this); | ||
1184 | } | ||
1177 | } | 1185 | } |
1178 | 1186 | ||
1179 | //--------------------------------------------------- | 1187 | //--------------------------------------------------- |
@@ -1347,22 +1355,33 @@ void LLVoiceClient::userAuthorized(const std::string& firstName, const std::stri | |||
1347 | sConnectingToAgni = LLViewerLogin::getInstance()->isInProductionGrid(); | 1355 | sConnectingToAgni = LLViewerLogin::getInstance()->isInProductionGrid(); |
1348 | 1356 | ||
1349 | mAccountName = nameFromID(agentID); | 1357 | mAccountName = nameFromID(agentID); |
1358 | mAccountActive = true; | ||
1350 | } | 1359 | } |
1351 | 1360 | ||
1352 | void LLVoiceClient::requestVoiceAccountProvision(S32 retries) | 1361 | void LLVoiceClient::requestVoiceAccountProvision(S32 retries) |
1353 | { | 1362 | { |
1354 | if ( gAgent.getRegion() && mVoiceEnabled ) | 1363 | LLViewerRegion* region = gAgent.getRegion(); |
1364 | if ( mVoiceEnabled && region && region->capabilitiesReceived()) | ||
1355 | { | 1365 | { |
1356 | std::string url = | 1366 | std::string url = region->getCapability("ProvisionVoiceAccountRequest"); |
1357 | gAgent.getRegion()->getCapability( | 1367 | |
1358 | "ProvisionVoiceAccountRequest"); | 1368 | if ( url.empty() ) |
1369 | { | ||
1370 | mVAPRequested = false; | ||
1371 | mAccountActive = false; | ||
1372 | LL_DEBUGS("VoiceSession") << "Cancel Session: ProvisionVoiceAccountRequest capability empty." | ||
1373 | << llendl; | ||
1374 | setState(stateDisableCleanup); | ||
1375 | } | ||
1359 | 1376 | ||
1360 | if ( url == "" ) return; | 1377 | LL_DEBUGS("VoiceCaps") << "Got ProvisionVoiceAccountRequest capability: " |
1378 | << url << llendl; | ||
1361 | 1379 | ||
1380 | mVAPCapResponseID.generate(); | ||
1362 | LLHTTPClient::post( | 1381 | LLHTTPClient::post( |
1363 | url, | 1382 | url, |
1364 | LLSD(), | 1383 | LLSD(), |
1365 | new LLViewerVoiceAccountProvisionResponder(retries)); | 1384 | new LLViewerVoiceAccountProvisionResponder(retries, mVAPCapResponseID)); |
1366 | } | 1385 | } |
1367 | } | 1386 | } |
1368 | 1387 | ||
@@ -1370,11 +1389,46 @@ void LLVoiceClient::login( | |||
1370 | const std::string& account_name, | 1389 | const std::string& account_name, |
1371 | const std::string& password, | 1390 | const std::string& password, |
1372 | const std::string& voice_sip_uri_hostname, | 1391 | const std::string& voice_sip_uri_hostname, |
1373 | const std::string& voice_account_server_uri) | 1392 | const std::string& voice_account_server_uri, |
1393 | const LLUUID& response_id) | ||
1374 | { | 1394 | { |
1395 | if(response_id != mVAPCapResponseID) return; | ||
1396 | |||
1397 | std::string new_scheme; | ||
1398 | std::string old_scheme; | ||
1399 | if(!voice_account_server_uri.empty()) | ||
1400 | { | ||
1401 | new_scheme = voice_account_server_uri.substr(0, voice_account_server_uri.find("://")); | ||
1402 | } | ||
1403 | if(!mDaemonScheme.empty()) | ||
1404 | { | ||
1405 | old_scheme = mDaemonScheme; | ||
1406 | } | ||
1407 | else | ||
1408 | { | ||
1409 | old_scheme = new_scheme; | ||
1410 | } | ||
1411 | |||
1375 | mVoiceSIPURIHostName = voice_sip_uri_hostname; | 1412 | mVoiceSIPURIHostName = voice_sip_uri_hostname; |
1376 | mVoiceAccountServerURI = voice_account_server_uri; | 1413 | mVoiceAccountServerURI = voice_account_server_uri; |
1377 | 1414 | ||
1415 | |||
1416 | LL_DEBUGS("VoiceCaps") << "new_scheme: \"" << new_scheme << "\"" | ||
1417 | << "\nold_scheme: \"" << old_scheme << "\"" | ||
1418 | << "\ngateway running: " << ( isGatewayRunning() ? "true" : "false" ) << llendl; | ||
1419 | if(!isGatewayRunning() ) | ||
1420 | { | ||
1421 | loadDaemon(new_scheme); | ||
1422 | } | ||
1423 | else if(old_scheme != new_scheme) | ||
1424 | { | ||
1425 | mAccountActive = true; | ||
1426 | LL_DEBUGS("VoiceSession") << "Cancel Session: Protocol changed." | ||
1427 | << llendl; | ||
1428 | setState(stateDisableCleanup); | ||
1429 | } | ||
1430 | |||
1431 | |||
1378 | if(!mAccountHandle.empty()) | 1432 | if(!mAccountHandle.empty()) |
1379 | { | 1433 | { |
1380 | // Already logged in. | 1434 | // Already logged in. |
@@ -1432,6 +1486,185 @@ void LLVoiceClient::login( | |||
1432 | } | 1486 | } |
1433 | } | 1487 | } |
1434 | 1488 | ||
1489 | void LLVoiceClient::loadDaemon(const std::string& scheme) | ||
1490 | { | ||
1491 | |||
1492 | // Launch the voice daemon | ||
1493 | |||
1494 | |||
1495 | // *FIX:Mani - Using the executable dir instead | ||
1496 | // of mAppRODataDir, the working directory from which the app | ||
1497 | // is launched. | ||
1498 | //std::string exe_path = gDirUtilp->getAppRODataDir(); | ||
1499 | std::string exe_path = gDirUtilp->getExecutableDir(); | ||
1500 | exe_path += gDirUtilp->getDirDelimiter(); | ||
1501 | |||
1502 | #if LL_DARWIN | ||
1503 | exe_path += "../Resources/"; | ||
1504 | #endif | ||
1505 | |||
1506 | //exe_path += gSavedSettings.getString("VoiceModule"); | ||
1507 | llwarns << "Scheme: " << scheme << llendl; | ||
1508 | |||
1509 | std::string module; | ||
1510 | if (scheme == "tcp") | ||
1511 | { | ||
1512 | |||
1513 | module = gSavedSettings.getString("VoiceModuleMumble").empty() ? | ||
1514 | "mumble" : gSavedSettings.getString("VoiceModuleMumble"); | ||
1515 | } | ||
1516 | else | ||
1517 | { | ||
1518 | module = gSavedSettings.getString("VoiceModuleVivox").empty() ? | ||
1519 | "SLVoice" : gSavedSettings.getString("VoiceModuleVivox"); | ||
1520 | } | ||
1521 | |||
1522 | size_t pos_to_tst = module.find_last_of("/\\"); | ||
1523 | if( pos_to_tst != std::string::npos ) | ||
1524 | { | ||
1525 | module = module.substr(pos_to_tst+1); | ||
1526 | } | ||
1527 | |||
1528 | #if LL_WINDOWS | ||
1529 | std::string extension = ".exe"; | ||
1530 | if ( module.rfind(extension) != module.length()-extension.length()) | ||
1531 | { | ||
1532 | module.append(extension); | ||
1533 | } | ||
1534 | #endif | ||
1535 | |||
1536 | exe_path.append(module); | ||
1537 | |||
1538 | // See if the vivox executable exists | ||
1539 | llstat s; | ||
1540 | if(!LLFile::stat(exe_path, &s)) | ||
1541 | { | ||
1542 | // vivox executable exists. Build the command line and launch the daemon. | ||
1543 | // SLIM SDK: these arguments are no longer necessary. | ||
1544 | // std::string args = " -p tcp -h -c"; | ||
1545 | std::string args; | ||
1546 | std::string cmd; | ||
1547 | std::string loglevel = gSavedSettings.getString("VivoxDebugLevel"); | ||
1548 | |||
1549 | if(loglevel.empty()) | ||
1550 | { | ||
1551 | loglevel = "-1"; // turn logging off completely | ||
1552 | } | ||
1553 | |||
1554 | args += " -ll "; | ||
1555 | args += loglevel; | ||
1556 | |||
1557 | llwarns << "Voice loaded from: " << exe_path << " " << args << LL_ENDL; | ||
1558 | |||
1559 | #if LL_WINDOWS | ||
1560 | PROCESS_INFORMATION pinfo; | ||
1561 | STARTUPINFOA sinfo; | ||
1562 | memset(&sinfo, 0, sizeof(sinfo)); | ||
1563 | std::string exe_dir = gDirUtilp->getAppRODataDir(); | ||
1564 | |||
1565 | |||
1566 | // So retarded. Windows requires that the second parameter to CreateProcessA be a writable (non-const) string... | ||
1567 | char *args2 = new char[args.size() + 1]; | ||
1568 | strcpy(args2, args.c_str()); | ||
1569 | |||
1570 | if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, exe_dir.c_str(), &sinfo, &pinfo)) | ||
1571 | { | ||
1572 | // DWORD dwErr = GetLastError(); | ||
1573 | } | ||
1574 | else | ||
1575 | { | ||
1576 | // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on | ||
1577 | // CloseHandle(pinfo.hProcess); // stops leaks - nothing else | ||
1578 | sGatewayHandle = pinfo.hProcess; | ||
1579 | CloseHandle(pinfo.hThread); // stops leaks - nothing else | ||
1580 | } | ||
1581 | |||
1582 | delete[] args2; | ||
1583 | #else // LL_WINDOWS | ||
1584 | // This should be the same for mac and linux | ||
1585 | { | ||
1586 | std::vector<std::string> arglist; | ||
1587 | arglist.push_back(exe_path); | ||
1588 | |||
1589 | // Split the argument string into separate strings for each argument | ||
1590 | typedef boost::tokenizer<boost::char_separator<char> > tokenizer; | ||
1591 | boost::char_separator<char> sep(" "); | ||
1592 | tokenizer tokens(args, sep); | ||
1593 | tokenizer::iterator token_iter; | ||
1594 | |||
1595 | for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) | ||
1596 | { | ||
1597 | arglist.push_back(*token_iter); | ||
1598 | } | ||
1599 | |||
1600 | // create an argv vector for the child process | ||
1601 | char **fakeargv = new char*[arglist.size() + 1]; | ||
1602 | int i; | ||
1603 | for(i=0; i < arglist.size(); i++) | ||
1604 | fakeargv[i] = const_cast<char*>(arglist[i].c_str()); | ||
1605 | |||
1606 | fakeargv[i] = NULL; | ||
1607 | |||
1608 | fflush(NULL); // flush all buffers before the child inherits them | ||
1609 | pid_t id = vfork(); | ||
1610 | if(id == 0) | ||
1611 | { | ||
1612 | // child | ||
1613 | execv(exe_path.c_str(), fakeargv); | ||
1614 | |||
1615 | // If we reach this point, the exec failed. | ||
1616 | // Use _exit() instead of exit() per the vfork man page. | ||
1617 | _exit(0); | ||
1618 | } | ||
1619 | |||
1620 | // parent | ||
1621 | delete[] fakeargv; | ||
1622 | sGatewayPID = id; | ||
1623 | |||
1624 | } | ||
1625 | |||
1626 | #endif // LL_WINDOWS | ||
1627 | |||
1628 | mDaemonScheme = scheme; | ||
1629 | mDaemonHost = LLHost(gSavedSettings.getString("VoiceHost").c_str(), gSavedSettings.getU32("VoicePort")); | ||
1630 | |||
1631 | // Dirty the states we'll need to sync with the daemon when it comes up. | ||
1632 | mPTTDirty = true; | ||
1633 | mMicVolumeDirty = true; | ||
1634 | mSpeakerVolumeDirty = true; | ||
1635 | mSpeakerMuteDirty = true; | ||
1636 | // These only need to be set if they're not default (i.e. empty string). | ||
1637 | mCaptureDeviceDirty = !mCaptureDevice.empty(); | ||
1638 | mRenderDeviceDirty = !mRenderDevice.empty(); | ||
1639 | |||
1640 | mMainSessionGroupHandle.clear(); | ||
1641 | |||
1642 | // kick in | ||
1643 | |||
1644 | mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS); | ||
1645 | mUpdateTimer.start(); | ||
1646 | |||
1647 | setState(stateDaemonLaunched); | ||
1648 | |||
1649 | //trigger parcel changed in the state engine | ||
1650 | mCurrentRegionName.append("kick in"); | ||
1651 | |||
1652 | |||
1653 | } | ||
1654 | else | ||
1655 | { | ||
1656 | LL_WARNS("Voice") << exe_path << " not found." << LL_ENDL; | ||
1657 | mAccountActive = false; | ||
1658 | LL_DEBUGS("VoiceSession") << "Cancel Session: no module" | ||
1659 | << llendl; | ||
1660 | setState(stateDisableCleanup); | ||
1661 | } | ||
1662 | |||
1663 | // we are done, re-allow ProvisionVoiceAccountRequest | ||
1664 | mVAPRequested = false; | ||
1665 | } | ||
1666 | |||
1667 | |||
1435 | void LLVoiceClient::idle(void* user_data) | 1668 | void LLVoiceClient::idle(void* user_data) |
1436 | { | 1669 | { |
1437 | LLVoiceClient* self = (LLVoiceClient*)user_data; | 1670 | LLVoiceClient* self = (LLVoiceClient*)user_data; |
@@ -1527,6 +1760,8 @@ void LLVoiceClient::setState(state inState) | |||
1527 | } | 1760 | } |
1528 | void LLVoiceClient::close() | 1761 | void LLVoiceClient::close() |
1529 | { | 1762 | { |
1763 | LL_DEBUGS("VoiceSession") << "Cancel Session: LLVoiceClient::close() called." | ||
1764 | << llendl; | ||
1530 | setState(stateDisableCleanup); | 1765 | setState(stateDisableCleanup); |
1531 | } | 1766 | } |
1532 | 1767 | ||
@@ -1537,11 +1772,20 @@ void LLVoiceClient::start() | |||
1537 | 1772 | ||
1538 | void LLVoiceClient::stateMachine() | 1773 | void LLVoiceClient::stateMachine() |
1539 | { | 1774 | { |
1775 | if( stateJail == getState()) | ||
1776 | { | ||
1777 | return; | ||
1778 | } | ||
1779 | |||
1780 | if(gSavedSettings.getBOOL("CmdLineDisableVoice")) | ||
1781 | { | ||
1782 | // Voice is locked out, we must not launch the vivox daemon. | ||
1783 | setState(stateJail); | ||
1784 | } | ||
1540 | 1785 | ||
1541 | // Disable voice as long as the viewer is disconnected from the sim (login/relog) | 1786 | // Disable voice as long as the viewer is disconnected from the sim (login/relog) |
1542 | setVoiceEnabled(!gDisconnected | 1787 | setVoiceEnabled(!gDisconnected |
1543 | && gSavedSettings.getBOOL("EnableVoiceChat") | 1788 | && gSavedSettings.getBOOL("EnableVoiceChat") ); |
1544 | && !gSavedSettings.getBOOL("CmdLineDisableVoice") ); | ||
1545 | 1789 | ||
1546 | if(mVoiceEnabled) | 1790 | if(mVoiceEnabled) |
1547 | { | 1791 | { |
@@ -1560,12 +1804,10 @@ void LLVoiceClient::stateMachine() | |||
1560 | { | 1804 | { |
1561 | // if voice was turned off after the daemon was launched but before we could connect to it, we may need to issue a kill. | 1805 | // if voice was turned off after the daemon was launched but before we could connect to it, we may need to issue a kill. |
1562 | LL_WARNS("Voice") << "Disabling voice before connection to daemon, terminating." << LL_ENDL; | 1806 | LL_WARNS("Voice") << "Disabling voice before connection to daemon, terminating." << LL_ENDL; |
1563 | killGateway(); | ||
1564 | } | 1807 | } |
1565 | 1808 | LL_DEBUGS("VoiceSession") << "Cancel Session: User turned off voice or logs off." | |
1566 | logout(); | 1809 | << llendl; |
1567 | connectorShutdown(); | 1810 | mAccountActive = false; |
1568 | |||
1569 | setState(stateDisableCleanup); | 1811 | setState(stateDisableCleanup); |
1570 | } | 1812 | } |
1571 | } | 1813 | } |
@@ -1574,47 +1816,21 @@ void LLVoiceClient::stateMachine() | |||
1574 | if(mVoiceEnabled) | 1816 | if(mVoiceEnabled) |
1575 | { | 1817 | { |
1576 | LLViewerRegion *region = gAgent.getRegion(); | 1818 | LLViewerRegion *region = gAgent.getRegion(); |
1577 | LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); | 1819 | if(region && region->capabilitiesReceived()) |
1578 | |||
1579 | if(region && parcel) | ||
1580 | { | 1820 | { |
1581 | S32 parcelLocalID = parcel->getLocalID(); | 1821 | LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); |
1582 | std::string regionName = region->getName(); | 1822 | if(parcel) |
1583 | std::string capURI = region->getCapability("ParcelVoiceInfoRequest"); | ||
1584 | |||
1585 | // LL_DEBUGS("Voice") << "Region name = \"" << regionName << "\", parcel local ID = " << parcelLocalID << ", cap URI = \"" << capURI << "\"" << LL_ENDL; | ||
1586 | |||
1587 | // The region name starts out empty and gets filled in later. | ||
1588 | // Also, the cap gets filled in a short time after the region cross, but a little too late for our purposes. | ||
1589 | // If either is empty, wait for the next time around. | ||
1590 | if(!regionName.empty()) | ||
1591 | { | 1823 | { |
1592 | if(!capURI.empty()) | 1824 | S32 parcelLocalID = parcel->getLocalID(); |
1593 | { | 1825 | std::string regionName = region->getName(); |
1594 | if((parcelLocalID != mCurrentParcelLocalID) || (regionName != mCurrentRegionName)) | 1826 | |
1595 | { | 1827 | if((parcelLocalID != mCurrentParcelLocalID) || (regionName != mCurrentRegionName)) |
1596 | // We have changed parcels. Initiate a parcel channel lookup. | ||
1597 | mCurrentParcelLocalID = parcelLocalID; | ||
1598 | mCurrentRegionName = regionName; | ||
1599 | |||
1600 | parcelChanged(); | ||
1601 | } | ||
1602 | } | ||
1603 | else | ||
1604 | { | 1828 | { |
1605 | static int count = 0; | 1829 | // We have changed parcels. Initiate a parcel channel lookup. |
1606 | static int count2 = 0; | 1830 | mCurrentParcelLocalID = parcelLocalID; |
1607 | static int num = 1; | 1831 | mCurrentRegionName = regionName; |
1608 | ++count; | 1832 | |
1609 | if (count % num == 0) | 1833 | parcelChanged(); |
1610 | { | ||
1611 | LL_DEBUGS("Voice") << "region doesn't have ParcelVoiceInfoRequest capability. This is normal for a short time after teleporting, but bad if it persists for very long (" << count << ")." << LL_ENDL; | ||
1612 | if (num < 1000 && ++count2 == 10) | ||
1613 | { | ||
1614 | num *= 10; | ||
1615 | count2 = 0; | ||
1616 | } | ||
1617 | } | ||
1618 | } | 1834 | } |
1619 | } | 1835 | } |
1620 | } | 1836 | } |
@@ -1624,191 +1840,65 @@ void LLVoiceClient::stateMachine() | |||
1624 | { | 1840 | { |
1625 | //MARK: stateDisableCleanup | 1841 | //MARK: stateDisableCleanup |
1626 | case stateDisableCleanup: | 1842 | case stateDisableCleanup: |
1627 | // Clean up and reset everything. | 1843 | // Clean up and reset everything. |
1844 | |||
1845 | mVAPCapResponseID.setNull(); | ||
1846 | mPIRCapResponseID.setNull(); | ||
1847 | |||
1848 | if(isGatewayRunning()) | ||
1849 | { | ||
1850 | killGateway(); | ||
1851 | } | ||
1852 | logoutSendMessage(); | ||
1853 | mConnected = false; | ||
1854 | |||
1855 | |||
1628 | closeSocket(); | 1856 | closeSocket(); |
1629 | deleteAllSessions(); | 1857 | deleteAllSessions(); |
1630 | deleteAllBuddies(); | 1858 | deleteAllBuddies(); |
1631 | 1859 | ||
1632 | mConnectorHandle.clear(); | 1860 | mConnectorHandle.clear(); |
1633 | mAccountHandle.clear(); | 1861 | mAccountHandle.clear(); |
1634 | mAccountPassword.clear(); | 1862 | mAccountPassword.clear(); |
1635 | mVoiceAccountServerURI.clear(); | 1863 | mVoiceAccountServerURI.clear(); |
1636 | 1864 | mVAPRequested = false; | |
1637 | setState(stateDisabled); | 1865 | setState(stateDisabled); |
1638 | break; | 1866 | break; |
1639 | 1867 | ||
1640 | //MARK: stateDisabled | 1868 | //MARK: stateDisabled |
1641 | case stateDisabled: | 1869 | case stateDisabled: |
1642 | if(mTuningMode || (mVoiceEnabled && !mAccountName.empty())) | 1870 | if(mTuningMode || (mVoiceEnabled && mAccountActive && !mAccountName.empty())) |
1643 | { | 1871 | { |
1644 | setState(stateStart); | 1872 | setState(stateStart); |
1645 | } | 1873 | } |
1646 | break; | 1874 | break; |
1647 | 1875 | ||
1648 | //MARK: stateStart | 1876 | //MARK: stateStart |
1649 | case stateStart: | 1877 | case stateStart: |
1650 | if(gSavedSettings.getBOOL("CmdLineDisableVoice")) | 1878 | { |
1651 | { | 1879 | LLViewerRegion *region = gAgent.getRegion(); |
1652 | // Voice is locked out, we must not launch the vivox daemon. | 1880 | bool have_region = (NULL != region && region->capabilitiesReceived()); |
1653 | setState(stateJail); | 1881 | if(mVoiceEnabled && !mVAPRequested && !mAccountName.empty() && have_region) |
1654 | } | ||
1655 | else if(!isGatewayRunning()) | ||
1656 | { | 1882 | { |
1657 | if(true) | 1883 | mVAPRequested = true; |
1658 | { | 1884 | requestVoiceAccountProvision(); |
1659 | // Launch the voice daemon | ||
1660 | |||
1661 | // *FIX:Mani - Using the executable dir instead | ||
1662 | // of mAppRODataDir, the working directory from which the app | ||
1663 | // is launched. | ||
1664 | //std::string exe_path = gDirUtilp->getAppRODataDir(); | ||
1665 | std::string exe_path = gDirUtilp->getExecutableDir(); | ||
1666 | exe_path += gDirUtilp->getDirDelimiter(); | ||
1667 | #if LL_DARWIN | ||
1668 | exe_path += "../Resources/"; | ||
1669 | #endif | ||
1670 | exe_path += gSavedSettings.getString("VoiceModule"); | ||
1671 | #if LL_WINDOWS | ||
1672 | exe_path += ".exe"; | ||
1673 | #endif | ||
1674 | // See if the vivox executable exists | ||
1675 | llstat s; | ||
1676 | if(!LLFile::stat(exe_path, &s)) | ||
1677 | { | ||
1678 | // vivox executable exists. Build the command line and launch the daemon. | ||
1679 | // SLIM SDK: these arguments are no longer necessary. | ||
1680 | // std::string args = " -p tcp -h -c"; | ||
1681 | std::string args; | ||
1682 | std::string cmd; | ||
1683 | std::string loglevel = gSavedSettings.getString("VivoxDebugLevel"); | ||
1684 | |||
1685 | if(loglevel.empty()) | ||
1686 | { | ||
1687 | loglevel = "-1"; // turn logging off completely | ||
1688 | } | ||
1689 | |||
1690 | args += " -ll "; | ||
1691 | args += loglevel; | ||
1692 | |||
1693 | LL_DEBUGS("Voice") << "Args for SLVoice: " << args << LL_ENDL; | ||
1694 | |||
1695 | #if LL_WINDOWS | ||
1696 | PROCESS_INFORMATION pinfo; | ||
1697 | STARTUPINFOA sinfo; | ||
1698 | memset(&sinfo, 0, sizeof(sinfo)); | ||
1699 | std::string exe_dir = gDirUtilp->getAppRODataDir(); | ||
1700 | cmd = gSavedSettings.getString("VoiceModule"); | ||
1701 | cmd += ".exe"; | ||
1702 | cmd += args; | ||
1703 | |||
1704 | // So retarded. Windows requires that the second parameter to CreateProcessA be a writable (non-const) string... | ||
1705 | char *args2 = new char[args.size() + 1]; | ||
1706 | strcpy(args2, args.c_str()); | ||
1707 | |||
1708 | if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, exe_dir.c_str(), &sinfo, &pinfo)) | ||
1709 | { | ||
1710 | // DWORD dwErr = GetLastError(); | ||
1711 | } | ||
1712 | else | ||
1713 | { | ||
1714 | // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on | ||
1715 | // CloseHandle(pinfo.hProcess); // stops leaks - nothing else | ||
1716 | sGatewayHandle = pinfo.hProcess; | ||
1717 | CloseHandle(pinfo.hThread); // stops leaks - nothing else | ||
1718 | } | ||
1719 | |||
1720 | delete[] args2; | ||
1721 | #else // LL_WINDOWS | ||
1722 | // This should be the same for mac and linux | ||
1723 | { | ||
1724 | std::vector<std::string> arglist; | ||
1725 | arglist.push_back(exe_path); | ||
1726 | |||
1727 | // Split the argument string into separate strings for each argument | ||
1728 | typedef boost::tokenizer<boost::char_separator<char> > tokenizer; | ||
1729 | boost::char_separator<char> sep(" "); | ||
1730 | tokenizer tokens(args, sep); | ||
1731 | tokenizer::iterator token_iter; | ||
1732 | |||
1733 | for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) | ||
1734 | { | ||
1735 | arglist.push_back(*token_iter); | ||
1736 | } | ||
1737 | |||
1738 | // create an argv vector for the child process | ||
1739 | char **fakeargv = new char*[arglist.size() + 1]; | ||
1740 | int i; | ||
1741 | for(i=0; i < arglist.size(); i++) | ||
1742 | fakeargv[i] = const_cast<char*>(arglist[i].c_str()); | ||
1743 | |||
1744 | fakeargv[i] = NULL; | ||
1745 | |||
1746 | fflush(NULL); // flush all buffers before the child inherits them | ||
1747 | pid_t id = vfork(); | ||
1748 | if(id == 0) | ||
1749 | { | ||
1750 | // child | ||
1751 | execv(exe_path.c_str(), fakeargv); | ||
1752 | |||
1753 | // If we reach this point, the exec failed. | ||
1754 | // Use _exit() instead of exit() per the vfork man page. | ||
1755 | _exit(0); | ||
1756 | } | ||
1757 | |||
1758 | // parent | ||
1759 | delete[] fakeargv; | ||
1760 | sGatewayPID = id; | ||
1761 | } | ||
1762 | #endif // LL_WINDOWS | ||
1763 | mDaemonHost = LLHost(gSavedSettings.getString("VoiceHost").c_str(), gSavedSettings.getU32("VoicePort")); | ||
1764 | } | ||
1765 | else | ||
1766 | { | ||
1767 | LL_WARNS("Voice") << exe_path << " not found." << LL_ENDL; | ||
1768 | mVoiceEnabled = false; | ||
1769 | } | ||
1770 | } | ||
1771 | else | ||
1772 | { | ||
1773 | // SLIM SDK: port changed from 44124 to 44125. | ||
1774 | // We can connect to a client gateway running on another host. This is useful for testing. | ||
1775 | // To do this, launch the gateway on a nearby host like this: | ||
1776 | // vivox-gw.exe -p tcp -i 0.0.0.0:44125 | ||
1777 | // and put that host's IP address here. | ||
1778 | mDaemonHost = LLHost(gSavedSettings.getString("VoiceHost"), gSavedSettings.getU32("VoicePort")); | ||
1779 | } | ||
1780 | |||
1781 | mUpdateTimer.start(); | ||
1782 | mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS); | ||
1783 | |||
1784 | setState(stateDaemonLaunched); | ||
1785 | |||
1786 | // Dirty the states we'll need to sync with the daemon when it comes up. | ||
1787 | mPTTDirty = true; | ||
1788 | mMicVolumeDirty = true; | ||
1789 | mSpeakerVolumeDirty = true; | ||
1790 | mSpeakerMuteDirty = true; | ||
1791 | // These only need to be set if they're not default (i.e. empty string). | ||
1792 | mCaptureDeviceDirty = !mCaptureDevice.empty(); | ||
1793 | mRenderDeviceDirty = !mRenderDevice.empty(); | ||
1794 | |||
1795 | mMainSessionGroupHandle.clear(); | ||
1796 | } | 1885 | } |
1797 | break; | 1886 | } break; |
1798 | 1887 | ||
1799 | //MARK: stateDaemonLaunched | 1888 | //MARK: stateDaemonLaunched |
1800 | case stateDaemonLaunched: | 1889 | case stateDaemonLaunched: |
1801 | if(mUpdateTimer.hasExpired()) | 1890 | if(mUpdateTimer.hasExpired()) |
1802 | { | 1891 | { |
1803 | LL_DEBUGS("Voice") << "Connecting to vivox daemon" << LL_ENDL; | 1892 | |
1804 | |||
1805 | mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS); | 1893 | mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS); |
1806 | 1894 | ||
1807 | if(!mSocket) | 1895 | if(!mSocket) |
1808 | { | 1896 | { |
1897 | LL_DEBUGS("VoiceDaemon") << "Connecting to voice daemon. Protocol: " | ||
1898 | << mDaemonScheme << LL_ENDL; | ||
1809 | mSocket = LLSocket::create(LLSocket::STREAM_TCP); | 1899 | mSocket = LLSocket::create(LLSocket::STREAM_TCP); |
1810 | } | 1900 | } |
1811 | 1901 | ||
1812 | mConnected = mSocket->blockingConnect(mDaemonHost); | 1902 | mConnected = mSocket->blockingConnect(mDaemonHost); |
1813 | if(mConnected) | 1903 | if(mConnected) |
1814 | { | 1904 | { |
@@ -1817,6 +1907,7 @@ void LLVoiceClient::stateMachine() | |||
1817 | else | 1907 | else |
1818 | { | 1908 | { |
1819 | // If the connect failed, the socket may have been put into a bad state. Delete it. | 1909 | // If the connect failed, the socket may have been put into a bad state. Delete it. |
1910 | LL_DEBUGS("VoiceDaemon") << "voice daemon not ready yet, retrying" << LL_ENDL; | ||
1820 | closeSocket(); | 1911 | closeSocket(); |
1821 | } | 1912 | } |
1822 | } | 1913 | } |
@@ -1842,9 +1933,8 @@ void LLVoiceClient::stateMachine() | |||
1842 | 1933 | ||
1843 | setState(stateConnected); | 1934 | setState(stateConnected); |
1844 | } | 1935 | } |
1845 | |||
1846 | break; | 1936 | break; |
1847 | 1937 | ||
1848 | //MARK: stateConnected | 1938 | //MARK: stateConnected |
1849 | case stateConnected: | 1939 | case stateConnected: |
1850 | // Initial devices query | 1940 | // Initial devices query |
@@ -1871,24 +1961,16 @@ void LLVoiceClient::stateMachine() | |||
1871 | } | 1961 | } |
1872 | else if(!mAccountName.empty() && mVoiceEnabled) | 1962 | else if(!mAccountName.empty() && mVoiceEnabled) |
1873 | { | 1963 | { |
1874 | LLViewerRegion *region = gAgent.getRegion(); | 1964 | if ( mAccountPassword.empty() ) |
1875 | |||
1876 | if(region) | ||
1877 | { | 1965 | { |
1878 | if ( region->getCapability("ProvisionVoiceAccountRequest") != "" ) | 1966 | requestVoiceAccountProvision(); |
1879 | { | 1967 | } |
1880 | if ( mAccountPassword.empty() ) | 1968 | else |
1881 | { | 1969 | { |
1882 | requestVoiceAccountProvision(); | 1970 | setState(stateConnectorStart); |
1883 | } | ||
1884 | setState(stateConnectorStart); | ||
1885 | } | ||
1886 | else | ||
1887 | { | ||
1888 | LL_DEBUGS("Voice") << "region doesn't have ProvisionVoiceAccountRequest capability!" << LL_ENDL; | ||
1889 | } | ||
1890 | } | 1971 | } |
1891 | } | 1972 | } |
1973 | |||
1892 | break; | 1974 | break; |
1893 | 1975 | ||
1894 | //MARK: stateMicTuningStart | 1976 | //MARK: stateMicTuningStart |
@@ -2025,7 +2107,10 @@ void LLVoiceClient::stateMachine() | |||
2025 | if(mLoginRetryCount > MAX_LOGIN_RETRIES) | 2107 | if(mLoginRetryCount > MAX_LOGIN_RETRIES) |
2026 | { | 2108 | { |
2027 | LL_WARNS("Voice") << "too many login retries, giving up." << LL_ENDL; | 2109 | LL_WARNS("Voice") << "too many login retries, giving up." << LL_ENDL; |
2028 | setState(stateLoginFailed); | 2110 | LL_DEBUGS("VoiceSession") << "Cancel Session: too many login retries." |
2111 | << llendl; | ||
2112 | mAccountActive = false; | ||
2113 | setState(stateDisableCleanup); | ||
2029 | } | 2114 | } |
2030 | else | 2115 | else |
2031 | { | 2116 | { |
@@ -2385,7 +2470,11 @@ void LLVoiceClient::stateMachine() | |||
2385 | 2470 | ||
2386 | //MARK: stateConnectorStopped | 2471 | //MARK: stateConnectorStopped |
2387 | case stateConnectorStopped: // connector stop received | 2472 | case stateConnectorStopped: // connector stop received |
2473 | { | ||
2474 | LL_DEBUGS("VoiceSession") << "Cancel Session: entered stateConnectorStopped." | ||
2475 | << llendl; | ||
2388 | setState(stateDisableCleanup); | 2476 | setState(stateDisableCleanup); |
2477 | } | ||
2389 | break; | 2478 | break; |
2390 | 2479 | ||
2391 | //MARK: stateConnectorFailed | 2480 | //MARK: stateConnectorFailed |
@@ -2396,6 +2485,8 @@ void LLVoiceClient::stateMachine() | |||
2396 | case stateConnectorFailedWaiting: | 2485 | case stateConnectorFailedWaiting: |
2397 | if(!mVoiceEnabled) | 2486 | if(!mVoiceEnabled) |
2398 | { | 2487 | { |
2488 | LL_DEBUGS("VoiceSession") << "Cancel Session: entered stateConnectorFailedWaiting." | ||
2489 | << llendl; | ||
2399 | setState(stateDisableCleanup); | 2490 | setState(stateDisableCleanup); |
2400 | } | 2491 | } |
2401 | break; | 2492 | break; |
@@ -2408,6 +2499,8 @@ void LLVoiceClient::stateMachine() | |||
2408 | case stateLoginFailedWaiting: | 2499 | case stateLoginFailedWaiting: |
2409 | if(!mVoiceEnabled) | 2500 | if(!mVoiceEnabled) |
2410 | { | 2501 | { |
2502 | LL_DEBUGS("VoiceSession") << "Cancel Session: entered stateLoginFailedWaiting." | ||
2503 | << llendl; | ||
2411 | setState(stateDisableCleanup); | 2504 | setState(stateDisableCleanup); |
2412 | } | 2505 | } |
2413 | break; | 2506 | break; |
@@ -2569,7 +2662,7 @@ void LLVoiceClient::sessionGroupCreateSendMessage() | |||
2569 | 2662 | ||
2570 | void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAudio, bool startText) | 2663 | void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAudio, bool startText) |
2571 | { | 2664 | { |
2572 | LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL; | 2665 | LL_DEBUGS("VoiceSession") << "requesting create: " << session->mSIPURI << LL_ENDL; |
2573 | 2666 | ||
2574 | session->mCreateInProgress = true; | 2667 | session->mCreateInProgress = true; |
2575 | if(startAudio) | 2668 | if(startAudio) |
@@ -2605,7 +2698,7 @@ void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAu | |||
2605 | 2698 | ||
2606 | void LLVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio, bool startText) | 2699 | void LLVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio, bool startText) |
2607 | { | 2700 | { |
2608 | LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL; | 2701 | LL_DEBUGS("VoiceSession") << "requesting create: " << session->mSIPURI << LL_ENDL; |
2609 | 2702 | ||
2610 | session->mCreateInProgress = true; | 2703 | session->mCreateInProgress = true; |
2611 | if(startAudio) | 2704 | if(startAudio) |
@@ -2642,7 +2735,7 @@ void LLVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, boo | |||
2642 | 2735 | ||
2643 | void LLVoiceClient::sessionMediaConnectSendMessage(sessionState *session) | 2736 | void LLVoiceClient::sessionMediaConnectSendMessage(sessionState *session) |
2644 | { | 2737 | { |
2645 | LL_DEBUGS("Voice") << "connecting audio to session handle: " << session->mHandle << LL_ENDL; | 2738 | LL_DEBUGS("VoiceSession") << "connecting audio to session handle: " << session->mHandle << LL_ENDL; |
2646 | 2739 | ||
2647 | session->mMediaConnectInProgress = true; | 2740 | session->mMediaConnectInProgress = true; |
2648 | 2741 | ||
@@ -2660,7 +2753,7 @@ void LLVoiceClient::sessionMediaConnectSendMessage(sessionState *session) | |||
2660 | 2753 | ||
2661 | void LLVoiceClient::sessionTextConnectSendMessage(sessionState *session) | 2754 | void LLVoiceClient::sessionTextConnectSendMessage(sessionState *session) |
2662 | { | 2755 | { |
2663 | LL_DEBUGS("Voice") << "connecting text to session handle: " << session->mHandle << LL_ENDL; | 2756 | LL_DEBUGS("VoiceSession") << "connecting text to session handle: " << session->mHandle << LL_ENDL; |
2664 | 2757 | ||
2665 | std::ostringstream stream; | 2758 | std::ostringstream stream; |
2666 | 2759 | ||
@@ -2689,7 +2782,7 @@ void LLVoiceClient::leaveAudioSession() | |||
2689 | { | 2782 | { |
2690 | if(mAudioSession) | 2783 | if(mAudioSession) |
2691 | { | 2784 | { |
2692 | LL_DEBUGS("Voice") << "leaving session: " << mAudioSession->mSIPURI << LL_ENDL; | 2785 | LL_DEBUGS("VoiceSession") << "leaving session: " << mAudioSession->mSIPURI << LL_ENDL; |
2693 | 2786 | ||
2694 | switch(getState()) | 2787 | switch(getState()) |
2695 | { | 2788 | { |
@@ -2724,7 +2817,7 @@ void LLVoiceClient::leaveAudioSession() | |||
2724 | } | 2817 | } |
2725 | else | 2818 | else |
2726 | { | 2819 | { |
2727 | LL_WARNS("Voice") << "called with no session handle" << LL_ENDL; | 2820 | LL_WARNS("VoiceSession") << "called with no session handle" << LL_ENDL; |
2728 | setState(stateSessionTerminated); | 2821 | setState(stateSessionTerminated); |
2729 | } | 2822 | } |
2730 | break; | 2823 | break; |
@@ -2734,13 +2827,13 @@ void LLVoiceClient::leaveAudioSession() | |||
2734 | break; | 2827 | break; |
2735 | 2828 | ||
2736 | default: | 2829 | default: |
2737 | LL_WARNS("Voice") << "called from unknown state" << LL_ENDL; | 2830 | LL_WARNS("VoiceSession") << "called from unknown state" << LL_ENDL; |
2738 | break; | 2831 | break; |
2739 | } | 2832 | } |
2740 | } | 2833 | } |
2741 | else | 2834 | else |
2742 | { | 2835 | { |
2743 | LL_WARNS("Voice") << "called with no active session" << LL_ENDL; | 2836 | LL_WARNS("VoiceSession") << "called with no active session" << LL_ENDL; |
2744 | setState(stateSessionTerminated); | 2837 | setState(stateSessionTerminated); |
2745 | } | 2838 | } |
2746 | } | 2839 | } |
@@ -2749,7 +2842,7 @@ void LLVoiceClient::sessionTerminateSendMessage(sessionState *session) | |||
2749 | { | 2842 | { |
2750 | std::ostringstream stream; | 2843 | std::ostringstream stream; |
2751 | 2844 | ||
2752 | LL_DEBUGS("Voice") << "Sending Session.Terminate with handle " << session->mHandle << LL_ENDL; | 2845 | LL_DEBUGS("VoiceSession") << "Sending Session.Terminate with handle " << session->mHandle << LL_ENDL; |
2753 | stream | 2846 | stream |
2754 | << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.Terminate.1\">" | 2847 | << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.Terminate.1\">" |
2755 | << "<SessionHandle>" << session->mHandle << "</SessionHandle>" | 2848 | << "<SessionHandle>" << session->mHandle << "</SessionHandle>" |
@@ -2762,7 +2855,7 @@ void LLVoiceClient::sessionGroupTerminateSendMessage(sessionState *session) | |||
2762 | { | 2855 | { |
2763 | std::ostringstream stream; | 2856 | std::ostringstream stream; |
2764 | 2857 | ||
2765 | LL_DEBUGS("Voice") << "Sending SessionGroup.Terminate with handle " << session->mGroupHandle << LL_ENDL; | 2858 | LL_DEBUGS("VoiceSession") << "Sending SessionGroup.Terminate with handle " << session->mGroupHandle << LL_ENDL; |
2766 | stream | 2859 | stream |
2767 | << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.Terminate.1\">" | 2860 | << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.Terminate.1\">" |
2768 | << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>" | 2861 | << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>" |
@@ -2775,7 +2868,7 @@ void LLVoiceClient::sessionMediaDisconnectSendMessage(sessionState *session) | |||
2775 | { | 2868 | { |
2776 | std::ostringstream stream; | 2869 | std::ostringstream stream; |
2777 | 2870 | ||
2778 | LL_DEBUGS("Voice") << "Sending Session.MediaDisconnect with handle " << session->mHandle << LL_ENDL; | 2871 | LL_DEBUGS("VoiceSession") << "Sending Session.MediaDisconnect with handle " << session->mHandle << LL_ENDL; |
2779 | stream | 2872 | stream |
2780 | << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.MediaDisconnect.1\">" | 2873 | << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.MediaDisconnect.1\">" |
2781 | << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>" | 2874 | << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>" |
@@ -2791,7 +2884,7 @@ void LLVoiceClient::sessionTextDisconnectSendMessage(sessionState *session) | |||
2791 | { | 2884 | { |
2792 | std::ostringstream stream; | 2885 | std::ostringstream stream; |
2793 | 2886 | ||
2794 | LL_DEBUGS("Voice") << "Sending Session.TextDisconnect with handle " << session->mHandle << LL_ENDL; | 2887 | LL_DEBUGS("VoiceSession") << "Sending Session.TextDisconnect with handle " << session->mHandle << LL_ENDL; |
2795 | stream | 2888 | stream |
2796 | << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.TextDisconnect.1\">" | 2889 | << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.TextDisconnect.1\">" |
2797 | << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>" | 2890 | << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>" |
@@ -2823,13 +2916,13 @@ void LLVoiceClient::getRenderDevicesSendMessage() | |||
2823 | 2916 | ||
2824 | void LLVoiceClient::clearCaptureDevices() | 2917 | void LLVoiceClient::clearCaptureDevices() |
2825 | { | 2918 | { |
2826 | LL_DEBUGS("Voice") << "called" << LL_ENDL; | 2919 | LL_DEBUGS("VoiceDevice") << "called" << LL_ENDL; |
2827 | mCaptureDevices.clear(); | 2920 | mCaptureDevices.clear(); |
2828 | } | 2921 | } |
2829 | 2922 | ||
2830 | void LLVoiceClient::addCaptureDevice(const std::string& name) | 2923 | void LLVoiceClient::addCaptureDevice(const std::string& name) |
2831 | { | 2924 | { |
2832 | LL_DEBUGS("Voice") << name << LL_ENDL; | 2925 | LL_DEBUGS("VoiceDevice") << name << LL_ENDL; |
2833 | 2926 | ||
2834 | mCaptureDevices.push_back(name); | 2927 | mCaptureDevices.push_back(name); |
2835 | } | 2928 | } |
@@ -2861,13 +2954,13 @@ void LLVoiceClient::setCaptureDevice(const std::string& name) | |||
2861 | 2954 | ||
2862 | void LLVoiceClient::clearRenderDevices() | 2955 | void LLVoiceClient::clearRenderDevices() |
2863 | { | 2956 | { |
2864 | LL_DEBUGS("Voice") << "called" << LL_ENDL; | 2957 | LL_DEBUGS("VoiceDevice") << "called" << LL_ENDL; |
2865 | mRenderDevices.clear(); | 2958 | mRenderDevices.clear(); |
2866 | } | 2959 | } |
2867 | 2960 | ||
2868 | void LLVoiceClient::addRenderDevice(const std::string& name) | 2961 | void LLVoiceClient::addRenderDevice(const std::string& name) |
2869 | { | 2962 | { |
2870 | LL_DEBUGS("Voice") << name << LL_ENDL; | 2963 | LL_DEBUGS("VoiceDevice") << name << LL_ENDL; |
2871 | mRenderDevices.push_back(name); | 2964 | mRenderDevices.push_back(name); |
2872 | } | 2965 | } |
2873 | 2966 | ||
@@ -2951,7 +3044,7 @@ void LLVoiceClient::tuningRenderStopSendMessage() | |||
2951 | 3044 | ||
2952 | void LLVoiceClient::tuningCaptureStartSendMessage(int duration) | 3045 | void LLVoiceClient::tuningCaptureStartSendMessage(int duration) |
2953 | { | 3046 | { |
2954 | LL_DEBUGS("Voice") << "sending CaptureAudioStart" << LL_ENDL; | 3047 | LL_DEBUGS("VoiceDevice") << "sending CaptureAudioStart" << LL_ENDL; |
2955 | 3048 | ||
2956 | std::ostringstream stream; | 3049 | std::ostringstream stream; |
2957 | stream | 3050 | stream |
@@ -2964,7 +3057,7 @@ void LLVoiceClient::tuningCaptureStartSendMessage(int duration) | |||
2964 | 3057 | ||
2965 | void LLVoiceClient::tuningCaptureStopSendMessage() | 3058 | void LLVoiceClient::tuningCaptureStopSendMessage() |
2966 | { | 3059 | { |
2967 | LL_DEBUGS("Voice") << "sending CaptureAudioStop" << LL_ENDL; | 3060 | LL_DEBUGS("VoiceDevice") << "sending CaptureAudioStop" << LL_ENDL; |
2968 | 3061 | ||
2969 | std::ostringstream stream; | 3062 | std::ostringstream stream; |
2970 | stream | 3063 | stream |
@@ -3033,17 +3126,17 @@ void LLVoiceClient::daemonDied() | |||
3033 | LL_WARNS("Voice") << "Connection to vivox daemon lost. Resetting state."<< LL_ENDL; | 3126 | LL_WARNS("Voice") << "Connection to vivox daemon lost. Resetting state."<< LL_ENDL; |
3034 | 3127 | ||
3035 | // Try to relaunch the daemon | 3128 | // Try to relaunch the daemon |
3129 | LL_DEBUGS("VoiceSession") << "Cancel Session: voice daemon died." | ||
3130 | << llendl; | ||
3036 | setState(stateDisableCleanup); | 3131 | setState(stateDisableCleanup); |
3037 | } | 3132 | } |
3038 | 3133 | ||
3039 | void LLVoiceClient::giveUp() | 3134 | void LLVoiceClient::giveUp() |
3040 | { | 3135 | { |
3041 | // All has failed. Clean up and stop trying. | 3136 | mAccountActive = false; |
3042 | closeSocket(); | 3137 | LL_DEBUGS("VoiceSession") << "Cancel Session: giveUp() called." |
3043 | deleteAllSessions(); | 3138 | << llendl; |
3044 | deleteAllBuddies(); | 3139 | setState(stateDisableCleanup); |
3045 | |||
3046 | setState(stateJail); | ||
3047 | } | 3140 | } |
3048 | 3141 | ||
3049 | static void oldSDKTransform (LLVector3 &left, LLVector3 &up, LLVector3 &at, LLVector3d &pos, LLVector3 &vel) | 3142 | static void oldSDKTransform (LLVector3 &left, LLVector3 &up, LLVector3 &at, LLVector3d &pos, LLVector3 &vel) |
@@ -3378,7 +3471,7 @@ void LLVoiceClient::buildSetCaptureDevice(std::ostringstream &stream) | |||
3378 | { | 3471 | { |
3379 | if(mCaptureDeviceDirty) | 3472 | if(mCaptureDeviceDirty) |
3380 | { | 3473 | { |
3381 | LL_DEBUGS("Voice") << "Setting input device = \"" << mCaptureDevice << "\"" << LL_ENDL; | 3474 | LL_DEBUGS("VoiceDevice") << "Setting input device = \"" << mCaptureDevice << "\"" << LL_ENDL; |
3382 | 3475 | ||
3383 | stream | 3476 | stream |
3384 | << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetCaptureDevice.1\">" | 3477 | << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetCaptureDevice.1\">" |
@@ -4099,29 +4192,29 @@ void LLVoiceClient::reapSession(sessionState *session) | |||
4099 | { | 4192 | { |
4100 | if(!session->mHandle.empty()) | 4193 | if(!session->mHandle.empty()) |
4101 | { | 4194 | { |
4102 | LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (non-null session handle)" << LL_ENDL; | 4195 | LL_DEBUGS("VoiceSession") << "NOT deleting session " << session->mSIPURI << " (non-null session handle)" << LL_ENDL; |
4103 | } | 4196 | } |
4104 | else if(session->mCreateInProgress) | 4197 | else if(session->mCreateInProgress) |
4105 | { | 4198 | { |
4106 | LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (create in progress)" << LL_ENDL; | 4199 | LL_DEBUGS("VoiceSession") << "NOT deleting session " << session->mSIPURI << " (create in progress)" << LL_ENDL; |
4107 | } | 4200 | } |
4108 | else if(session->mMediaConnectInProgress) | 4201 | else if(session->mMediaConnectInProgress) |
4109 | { | 4202 | { |
4110 | LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (connect in progress)" << LL_ENDL; | 4203 | LL_DEBUGS("VoiceSession") << "NOT deleting session " << session->mSIPURI << " (connect in progress)" << LL_ENDL; |
4111 | } | 4204 | } |
4112 | else if(session == mAudioSession) | 4205 | else if(session == mAudioSession) |
4113 | { | 4206 | { |
4114 | LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the current session)" << LL_ENDL; | 4207 | LL_DEBUGS("VoiceSession") << "NOT deleting session " << session->mSIPURI << " (it's the current session)" << LL_ENDL; |
4115 | } | 4208 | } |
4116 | else if(session == mNextAudioSession) | 4209 | else if(session == mNextAudioSession) |
4117 | { | 4210 | { |
4118 | LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the next session)" << LL_ENDL; | 4211 | LL_DEBUGS("VoiceSession") << "NOT deleting session " << session->mSIPURI << " (it's the next session)" << LL_ENDL; |
4119 | } | 4212 | } |
4120 | else | 4213 | else |
4121 | { | 4214 | { |
4122 | // TODO: Question: Should we check for queued text messages here? | 4215 | // TODO: Question: Should we check for queued text messages here? |
4123 | // We don't have a reason to keep tracking this session, so just delete it. | 4216 | // We don't have a reason to keep tracking this session, so just delete it. |
4124 | LL_DEBUGS("Voice") << "deleting session " << session->mSIPURI << LL_ENDL; | 4217 | LL_DEBUGS("VoiceSession") << "deleting session " << session->mSIPURI << LL_ENDL; |
4125 | deleteSession(session); | 4218 | deleteSession(session); |
4126 | session = NULL; | 4219 | session = NULL; |
4127 | } | 4220 | } |
@@ -4179,17 +4272,17 @@ void LLVoiceClient::leftAudioSession( | |||
4179 | case stateJoinSessionFailed: | 4272 | case stateJoinSessionFailed: |
4180 | case stateJoinSessionFailedWaiting: | 4273 | case stateJoinSessionFailedWaiting: |
4181 | // normal transition | 4274 | // normal transition |
4182 | LL_DEBUGS("Voice") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL; | 4275 | LL_DEBUGS("VoiceSession") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL; |
4183 | setState(stateSessionTerminated); | 4276 | setState(stateSessionTerminated); |
4184 | break; | 4277 | break; |
4185 | 4278 | ||
4186 | case stateSessionTerminated: | 4279 | case stateSessionTerminated: |
4187 | // this will happen sometimes -- there are cases where we send the terminate and then go straight to this state. | 4280 | // this will happen sometimes -- there are cases where we send the terminate and then go straight to this state. |
4188 | LL_WARNS("Voice") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL; | 4281 | LL_WARNS("VoiceSession") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL; |
4189 | break; | 4282 | break; |
4190 | 4283 | ||
4191 | default: | 4284 | default: |
4192 | LL_WARNS("Voice") << "unexpected SessionStateChangeEvent (left session) in state " << state2string(getState()) << LL_ENDL; | 4285 | LL_WARNS("VoiceSession") << "unexpected SessionStateChangeEvent (left session) in state " << state2string(getState()) << LL_ENDL; |
4193 | setState(stateSessionTerminated); | 4286 | setState(stateSessionTerminated); |
4194 | break; | 4287 | break; |
4195 | } | 4288 | } |
@@ -4249,7 +4342,7 @@ void LLVoiceClient::mediaStreamUpdatedEvent( | |||
4249 | { | 4342 | { |
4250 | sessionState *session = findSession(sessionHandle); | 4343 | sessionState *session = findSession(sessionHandle); |
4251 | 4344 | ||
4252 | LL_DEBUGS("Voice") << "session " << sessionHandle << ", status code " << statusCode << ", string \"" << statusString << "\"" << LL_ENDL; | 4345 | LL_DEBUGS("VoiceSession") << "session " << sessionHandle << ", status code " << statusCode << ", string \"" << statusString << "\"" << LL_ENDL; |
4253 | 4346 | ||
4254 | if(session) | 4347 | if(session) |
4255 | { | 4348 | { |
@@ -4314,7 +4407,7 @@ void LLVoiceClient::mediaStreamUpdatedEvent( | |||
4314 | } | 4407 | } |
4315 | else | 4408 | else |
4316 | { | 4409 | { |
4317 | LL_WARNS("Voice") << "session " << sessionHandle << "not found"<< LL_ENDL; | 4410 | LL_WARNS("VoiceSession") << "session " << sessionHandle << "not found"<< LL_ENDL; |
4318 | } | 4411 | } |
4319 | } | 4412 | } |
4320 | 4413 | ||
@@ -4435,7 +4528,7 @@ void LLVoiceClient::participantRemovedEvent( | |||
4435 | } | 4528 | } |
4436 | else | 4529 | else |
4437 | { | 4530 | { |
4438 | LL_DEBUGS("Voice") << "unknown session " << sessionHandle << LL_ENDL; | 4531 | LL_DEBUGS("VoiceSession") << "unknown session " << sessionHandle << LL_ENDL; |
4439 | } | 4532 | } |
4440 | } | 4533 | } |
4441 | 4534 | ||
@@ -4479,7 +4572,7 @@ void LLVoiceClient::participantUpdatedEvent( | |||
4479 | } | 4572 | } |
4480 | else | 4573 | else |
4481 | { | 4574 | { |
4482 | LL_WARNS("Voice") << "unknown session " << sessionHandle << LL_ENDL; | 4575 | LL_WARNS("VoiceSession") << "unknown session " << sessionHandle << LL_ENDL; |
4483 | } | 4576 | } |
4484 | } | 4577 | } |
4485 | 4578 | ||
@@ -5058,22 +5151,44 @@ LLVoiceClient::participantState* LLVoiceClient::findParticipantByID(const LLUUID | |||
5058 | 5151 | ||
5059 | void LLVoiceClient::parcelChanged() | 5152 | void LLVoiceClient::parcelChanged() |
5060 | { | 5153 | { |
5061 | if(getState() >= stateNoChannel) | 5154 | mAccountActive = true; |
5155 | LLViewerRegion* region = gAgent.getRegion(); | ||
5156 | if( (getState() >= stateNoChannel) && region && region->capabilitiesReceived()) | ||
5062 | { | 5157 | { |
5063 | // If the user is logged in, start a channel lookup. | 5158 | // If the user is logged in, start a channel lookup, |
5064 | LL_DEBUGS("Voice") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << LL_ENDL; | 5159 | // but not if already in a private call/conference (then SL regions return an empty cap). |
5160 | // | ||
5065 | 5161 | ||
5066 | std::string url = gAgent.getRegion()->getCapability("ParcelVoiceInfoRequest"); | 5162 | std::string url = region->getCapability("ParcelVoiceInfoRequest"); |
5067 | LLSD data; | 5163 | LL_DEBUGS("VoiceCaps") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << " cap url:" << url << LL_ENDL; |
5068 | LLHTTPClient::post( | 5164 | if(! url.empty() ) |
5069 | url, | 5165 | { |
5070 | data, | 5166 | mPIRCapResponseID.generate(); |
5071 | new LLVoiceClientCapResponder); | 5167 | LLSD data; |
5168 | LLHTTPClient::post( | ||
5169 | url, | ||
5170 | data, | ||
5171 | new LLVoiceClientCapResponder(mPIRCapResponseID)); | ||
5172 | } | ||
5173 | else | ||
5174 | { | ||
5175 | |||
5176 | mAccountActive = false; | ||
5177 | LL_DEBUGS("VoiceSession") << "Cancel Session: ParcelVoiceInfoRequest cap empty." | ||
5178 | << llendl; | ||
5179 | setState(stateDisableCleanup); | ||
5180 | } | ||
5181 | } | ||
5182 | else if (region && !region->capabilitiesReceived()) | ||
5183 | { | ||
5184 | // We don't know yet where to get the cap so requesting it makes no sense | ||
5185 | mCurrentRegionName.append("retry"); | ||
5186 | return; | ||
5072 | } | 5187 | } |
5073 | else | 5188 | else |
5074 | { | 5189 | { |
5075 | // The transition to stateNoChannel needs to kick this off again. | 5190 | // The transition to stateNoChannel needs to kick this off again. |
5076 | LL_WARNS("Voice") << "not logged in yet, deferring" << LL_ENDL; | 5191 | LL_DEBUGS("Voice") << "not logged in yet, deferring" << LL_ENDL; |
5077 | } | 5192 | } |
5078 | } | 5193 | } |
5079 | 5194 | ||
@@ -5086,12 +5201,42 @@ void LLVoiceClient::switchChannel( | |||
5086 | { | 5201 | { |
5087 | bool needsSwitch = false; | 5202 | bool needsSwitch = false; |
5088 | 5203 | ||
5089 | LL_DEBUGS("Voice") | 5204 | LL_DEBUGS("VoiceSession") |
5090 | << "called in state " << state2string(getState()) | 5205 | << "Switch channel called in state " << state2string(getState()) |
5091 | << " with uri \"" << uri << "\"" | 5206 | << " with uri \"" << uri << "\"" |
5092 | << (spatial?", spatial is true":", spatial is false") | 5207 | << (spatial?", spatial is true":", spatial is false") |
5093 | << LL_ENDL; | 5208 | << LL_ENDL; |
5094 | 5209 | ||
5210 | size_t new_uri_find_sip = std::string::npos; | ||
5211 | size_t old_uri_find_sip = std::string::npos; | ||
5212 | if(!uri.empty()) | ||
5213 | { | ||
5214 | new_uri_find_sip = uri.find("sip:"); | ||
5215 | } | ||
5216 | |||
5217 | if( mNextAudioSession | ||
5218 | && !( mNextAudioSession->mSIPURI.empty() ) | ||
5219 | && (mNextAudioSession->mSIPURI != uri) ) | ||
5220 | { | ||
5221 | old_uri_find_sip = mNextAudioSession->mSIPURI.find("sip:"); | ||
5222 | } | ||
5223 | else | ||
5224 | { | ||
5225 | |||
5226 | // just logged in or voice disabled land in SL, | ||
5227 | // anyway right daemon is already up | ||
5228 | old_uri_find_sip = new_uri_find_sip; | ||
5229 | } | ||
5230 | |||
5231 | if(old_uri_find_sip != new_uri_find_sip) | ||
5232 | { | ||
5233 | mAccountActive = true; | ||
5234 | LL_DEBUGS("VoiceSession") << "Cancel Session: Session type changed" | ||
5235 | << llendl; | ||
5236 | setState(stateDisableCleanup); | ||
5237 | return; | ||
5238 | } | ||
5239 | |||
5095 | switch(getState()) | 5240 | switch(getState()) |
5096 | { | 5241 | { |
5097 | case stateJoinSessionFailed: | 5242 | case stateJoinSessionFailed: |
@@ -5148,7 +5293,7 @@ void LLVoiceClient::switchChannel( | |||
5148 | if(uri.empty()) | 5293 | if(uri.empty()) |
5149 | { | 5294 | { |
5150 | // Leave any channel we may be in | 5295 | // Leave any channel we may be in |
5151 | LL_DEBUGS("Voice") << "leaving channel" << LL_ENDL; | 5296 | LL_DEBUGS("VoiceSession") << "leaving channel" << LL_ENDL; |
5152 | 5297 | ||
5153 | sessionState *oldSession = mNextAudioSession; | 5298 | sessionState *oldSession = mNextAudioSession; |
5154 | mNextAudioSession = NULL; | 5299 | mNextAudioSession = NULL; |
@@ -5160,7 +5305,7 @@ void LLVoiceClient::switchChannel( | |||
5160 | } | 5305 | } |
5161 | else | 5306 | else |
5162 | { | 5307 | { |
5163 | LL_DEBUGS("Voice") << "switching to channel " << uri << LL_ENDL; | 5308 | LL_DEBUGS("VoiceSession") << "switching to channel " << uri << LL_ENDL; |
5164 | 5309 | ||
5165 | mNextAudioSession = addSession(uri); | 5310 | mNextAudioSession = addSession(uri); |
5166 | mNextAudioSession->mHash = hash; | 5311 | mNextAudioSession->mHash = hash; |
@@ -5205,8 +5350,14 @@ void LLVoiceClient::setNonSpatialChannel( | |||
5205 | 5350 | ||
5206 | void LLVoiceClient::setSpatialChannel( | 5351 | void LLVoiceClient::setSpatialChannel( |
5207 | const std::string &uri, | 5352 | const std::string &uri, |
5208 | const std::string &credentials) | 5353 | const std::string &credentials, |
5354 | const LLUUID& response_id) | ||
5209 | { | 5355 | { |
5356 | if (response_id != mPIRCapResponseID) | ||
5357 | { | ||
5358 | return; | ||
5359 | } | ||
5360 | |||
5210 | mSpatialSessionURI = uri; | 5361 | mSpatialSessionURI = uri; |
5211 | mSpatialSessionCredentials = credentials; | 5362 | mSpatialSessionCredentials = credentials; |
5212 | mAreaVoiceDisabled = mSpatialSessionURI.empty(); | 5363 | mAreaVoiceDisabled = mSpatialSessionURI.empty(); |
@@ -5282,7 +5433,7 @@ bool LLVoiceClient::sendTextMessage(const LLUUID& participant_id, const std::str | |||
5282 | } | 5433 | } |
5283 | else | 5434 | else |
5284 | { | 5435 | { |
5285 | LL_DEBUGS("Voice") << "Session not found for participant ID " << participant_id << LL_ENDL; | 5436 | LL_DEBUGS("VoiceSession") << "Session not found for participant ID " << participant_id << LL_ENDL; |
5286 | } | 5437 | } |
5287 | 5438 | ||
5288 | return result; | 5439 | return result; |
@@ -5331,7 +5482,7 @@ void LLVoiceClient::endUserIMSession(const LLUUID &uuid) | |||
5331 | } | 5482 | } |
5332 | else | 5483 | else |
5333 | { | 5484 | { |
5334 | LL_DEBUGS("Voice") << "Session not found for participant ID " << uuid << LL_ENDL; | 5485 | LL_DEBUGS("VoiceSession") << "Session not found for participant ID " << uuid << LL_ENDL; |
5335 | } | 5486 | } |
5336 | } | 5487 | } |
5337 | 5488 | ||
@@ -5452,7 +5603,7 @@ void LLVoiceClient::declineInvite(std::string &sessionHandle) | |||
5452 | 5603 | ||
5453 | void LLVoiceClient::leaveNonSpatialChannel() | 5604 | void LLVoiceClient::leaveNonSpatialChannel() |
5454 | { | 5605 | { |
5455 | LL_DEBUGS("Voice") | 5606 | LL_DEBUGS("VoiceSession") |
5456 | << "called in state " << state2string(getState()) | 5607 | << "called in state " << state2string(getState()) |
5457 | << LL_ENDL; | 5608 | << LL_ENDL; |
5458 | 5609 | ||
@@ -5640,7 +5791,9 @@ bool LLVoiceClient::inSpatialChannel(void) | |||
5640 | 5791 | ||
5641 | if(mAudioSession) | 5792 | if(mAudioSession) |
5642 | result = mAudioSession->mIsSpatial; | 5793 | result = mAudioSession->mIsSpatial; |
5643 | 5794 | if(mNextAudioSession) | |
5795 | result |= !(mNextAudioSession->mIsSpatial); | ||
5796 | |||
5644 | return result; | 5797 | return result; |
5645 | } | 5798 | } |
5646 | 5799 | ||
@@ -5821,11 +5974,13 @@ void LLVoiceClient::setVoiceEnabled(bool enabled) | |||
5821 | mVoiceEnabled = enabled; | 5974 | mVoiceEnabled = enabled; |
5822 | if (enabled) | 5975 | if (enabled) |
5823 | { | 5976 | { |
5977 | mAccountActive = true; | ||
5824 | LLVoiceChannel::getCurrentVoiceChannel()->activate(); | 5978 | LLVoiceChannel::getCurrentVoiceChannel()->activate(); |
5825 | } | 5979 | } |
5826 | else | 5980 | else |
5827 | { | 5981 | { |
5828 | // Turning voice off looses your current channel -- this makes sure the UI isn't out of sync when you re-enable it. | 5982 | // Turning voice off looses your current channel -- this makes sure the UI isn't out of sync when you re-enable it. |
5983 | mAccountActive = false; | ||
5829 | LLVoiceChannel::getCurrentVoiceChannel()->deactivate(); | 5984 | LLVoiceChannel::getCurrentVoiceChannel()->deactivate(); |
5830 | } | 5985 | } |
5831 | } | 5986 | } |
@@ -6397,7 +6552,7 @@ LLVoiceClient::sessionState *LLVoiceClient::addSession(const std::string &uri, c | |||
6397 | { | 6552 | { |
6398 | // No existing session found. | 6553 | // No existing session found. |
6399 | 6554 | ||
6400 | LL_DEBUGS("Voice") << "adding new session: handle " << handle << " URI " << uri << LL_ENDL; | 6555 | LL_DEBUGS("VoiceSession") << "adding new session: handle " << handle << " URI " << uri << LL_ENDL; |
6401 | result = new sessionState(); | 6556 | result = new sessionState(); |
6402 | result->mSIPURI = uri; | 6557 | result->mSIPURI = uri; |
6403 | result->mHandle = handle; | 6558 | result->mHandle = handle; |
@@ -6416,7 +6571,7 @@ LLVoiceClient::sessionState *LLVoiceClient::addSession(const std::string &uri, c | |||
6416 | if(uri != result->mSIPURI) | 6571 | if(uri != result->mSIPURI) |
6417 | { | 6572 | { |
6418 | // TODO: Should this be an internal error? | 6573 | // TODO: Should this be an internal error? |
6419 | LL_DEBUGS("Voice") << "changing uri from " << result->mSIPURI << " to " << uri << LL_ENDL; | 6574 | LL_DEBUGS("VoiceSession") << "changing uri from " << result->mSIPURI << " to " << uri << LL_ENDL; |
6420 | setSessionURI(result, uri); | 6575 | setSessionURI(result, uri); |
6421 | } | 6576 | } |
6422 | 6577 | ||
@@ -6425,17 +6580,17 @@ LLVoiceClient::sessionState *LLVoiceClient::addSession(const std::string &uri, c | |||
6425 | if(handle.empty()) | 6580 | if(handle.empty()) |
6426 | { | 6581 | { |
6427 | // There's at least one race condition where where addSession was clearing an existing session handle, which caused things to break. | 6582 | // There's at least one race condition where where addSession was clearing an existing session handle, which caused things to break. |
6428 | LL_DEBUGS("Voice") << "NOT clearing handle " << result->mHandle << LL_ENDL; | 6583 | LL_DEBUGS("VoiceSession") << "NOT clearing handle " << result->mHandle << LL_ENDL; |
6429 | } | 6584 | } |
6430 | else | 6585 | else |
6431 | { | 6586 | { |
6432 | // TODO: Should this be an internal error? | 6587 | // TODO: Should this be an internal error? |
6433 | LL_DEBUGS("Voice") << "changing handle from " << result->mHandle << " to " << handle << LL_ENDL; | 6588 | LL_DEBUGS("VoiceSession") << "changing handle from " << result->mHandle << " to " << handle << LL_ENDL; |
6434 | setSessionHandle(result, handle); | 6589 | setSessionHandle(result, handle); |
6435 | } | 6590 | } |
6436 | } | 6591 | } |
6437 | 6592 | ||
6438 | LL_DEBUGS("Voice") << "returning existing session: handle " << handle << " URI " << uri << LL_ENDL; | 6593 | LL_DEBUGS("VoiceSession") << "returning existing session: handle " << handle << " URI " << uri << LL_ENDL; |
6439 | } | 6594 | } |
6440 | 6595 | ||
6441 | verifySessionState(); | 6596 | verifySessionState(); |
@@ -6455,14 +6610,14 @@ void LLVoiceClient::setSessionHandle(sessionState *session, const std::string &h | |||
6455 | { | 6610 | { |
6456 | if(iter->second != session) | 6611 | if(iter->second != session) |
6457 | { | 6612 | { |
6458 | LL_ERRS("Voice") << "Internal error: session mismatch!" << LL_ENDL; | 6613 | LL_ERRS("VoiceSession") << "Internal error: session mismatch!" << LL_ENDL; |
6459 | } | 6614 | } |
6460 | 6615 | ||
6461 | mSessionsByHandle.erase(iter); | 6616 | mSessionsByHandle.erase(iter); |
6462 | } | 6617 | } |
6463 | else | 6618 | else |
6464 | { | 6619 | { |
6465 | LL_ERRS("Voice") << "Internal error: session handle not found in map!" << LL_ENDL; | 6620 | LL_ERRS("VoiceSession") << "Internal error: session handle not found in map!" << LL_ENDL; |
6466 | } | 6621 | } |
6467 | } | 6622 | } |
6468 | 6623 | ||
@@ -6494,7 +6649,7 @@ void LLVoiceClient::deleteSession(sessionState *session) | |||
6494 | { | 6649 | { |
6495 | if(iter->second != session) | 6650 | if(iter->second != session) |
6496 | { | 6651 | { |
6497 | LL_ERRS("Voice") << "Internal error: session mismatch" << LL_ENDL; | 6652 | LL_ERRS("VoiceSession") << "Internal error: session mismatch" << LL_ENDL; |
6498 | } | 6653 | } |
6499 | mSessionsByHandle.erase(iter); | 6654 | mSessionsByHandle.erase(iter); |
6500 | } | 6655 | } |
@@ -6525,7 +6680,7 @@ void LLVoiceClient::deleteSession(sessionState *session) | |||
6525 | 6680 | ||
6526 | void LLVoiceClient::deleteAllSessions() | 6681 | void LLVoiceClient::deleteAllSessions() |
6527 | { | 6682 | { |
6528 | LL_DEBUGS("Voice") << "called" << LL_ENDL; | 6683 | LL_DEBUGS("VoiceSession") << "called" << LL_ENDL; |
6529 | 6684 | ||
6530 | while(!mSessions.empty()) | 6685 | while(!mSessions.empty()) |
6531 | { | 6686 | { |
@@ -6534,20 +6689,20 @@ void LLVoiceClient::deleteAllSessions() | |||
6534 | 6689 | ||
6535 | if(!mSessionsByHandle.empty()) | 6690 | if(!mSessionsByHandle.empty()) |
6536 | { | 6691 | { |
6537 | LL_ERRS("Voice") << "Internal error: empty session map, non-empty handle map" << LL_ENDL; | 6692 | LL_ERRS("VoiceSession") << "Internal error: empty session map, non-empty handle map" << LL_ENDL; |
6538 | } | 6693 | } |
6539 | } | 6694 | } |
6540 | 6695 | ||
6541 | void LLVoiceClient::verifySessionState(void) | 6696 | void LLVoiceClient::verifySessionState(void) |
6542 | { | 6697 | { |
6543 | // This is mostly intended for debugging problems with session state management. | 6698 | // This is mostly intended for debugging problems with session state management. |
6544 | LL_DEBUGS("Voice") << "Total session count: " << mSessions.size() << " , session handle map size: " << mSessionsByHandle.size() << LL_ENDL; | 6699 | LL_DEBUGS("VoiceSession") << "Total session count: " << mSessions.size() << " , session handle map size: " << mSessionsByHandle.size() << LL_ENDL; |
6545 | 6700 | ||
6546 | for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++) | 6701 | for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++) |
6547 | { | 6702 | { |
6548 | sessionState *session = *iter; | 6703 | sessionState *session = *iter; |
6549 | 6704 | ||
6550 | LL_DEBUGS("Voice") << "session " << session << ": handle " << session->mHandle << ", URI " << session->mSIPURI << LL_ENDL; | 6705 | LL_DEBUGS("VoiceSession") << "session " << session << ": handle " << session->mHandle << ", URI " << session->mSIPURI << LL_ENDL; |
6551 | 6706 | ||
6552 | if(!session->mHandle.empty()) | 6707 | if(!session->mHandle.empty()) |
6553 | { | 6708 | { |
@@ -6555,13 +6710,13 @@ void LLVoiceClient::verifySessionState(void) | |||
6555 | sessionMap::iterator i2 = mSessionsByHandle.find(&(session->mHandle)); | 6710 | sessionMap::iterator i2 = mSessionsByHandle.find(&(session->mHandle)); |
6556 | if(i2 == mSessionsByHandle.end()) | 6711 | if(i2 == mSessionsByHandle.end()) |
6557 | { | 6712 | { |
6558 | LL_ERRS("Voice") << "internal error (handle " << session->mHandle << " not found in session map)" << LL_ENDL; | 6713 | LL_ERRS("VoiceSession") << "internal error (handle " << session->mHandle << " not found in session map)" << LL_ENDL; |
6559 | } | 6714 | } |
6560 | else | 6715 | else |
6561 | { | 6716 | { |
6562 | if(i2->second != session) | 6717 | if(i2->second != session) |
6563 | { | 6718 | { |
6564 | LL_ERRS("Voice") << "internal error (handle " << session->mHandle << " in session map points to another session)" << LL_ENDL; | 6719 | LL_ERRS("VoiceSession") << "internal error (handle " << session->mHandle << " in session map points to another session)" << LL_ENDL; |
6565 | } | 6720 | } |
6566 | } | 6721 | } |
6567 | } | 6722 | } |
@@ -6574,13 +6729,13 @@ void LLVoiceClient::verifySessionState(void) | |||
6574 | sessionIterator i2 = mSessions.find(session); | 6729 | sessionIterator i2 = mSessions.find(session); |
6575 | if(i2 == mSessions.end()) | 6730 | if(i2 == mSessions.end()) |
6576 | { | 6731 | { |
6577 | LL_ERRS("Voice") << "internal error (session for handle " << session->mHandle << " not found in session map)" << LL_ENDL; | 6732 | LL_ERRS("VoiceSession") << "internal error (session for handle " << session->mHandle << " not found in session map)" << LL_ENDL; |
6578 | } | 6733 | } |
6579 | else | 6734 | else |
6580 | { | 6735 | { |
6581 | if(session->mHandle != (*i2)->mHandle) | 6736 | if(session->mHandle != (*i2)->mHandle) |
6582 | { | 6737 | { |
6583 | LL_ERRS("Voice") << "internal error (session for handle " << session->mHandle << " points to session with different handle " << (*i2)->mHandle << ")" << LL_ENDL; | 6738 | LL_ERRS("VoiceSession") << "internal error (session for handle " << session->mHandle << " points to session with different handle " << (*i2)->mHandle << ")" << LL_ENDL; |
6584 | } | 6739 | } |
6585 | } | 6740 | } |
6586 | } | 6741 | } |
@@ -7010,6 +7165,8 @@ class LLViewerParcelVoiceInfo : public LLHTTPNode | |||
7010 | { | 7165 | { |
7011 | LLSD body = input["body"]; | 7166 | LLSD body = input["body"]; |
7012 | 7167 | ||
7168 | LL_DEBUGS("VoiceCaps") << "ParcelVoiceInfo response: " | ||
7169 | << ll_pretty_print_sd(input) << LL_ENDL; | ||
7013 | //body has "region_name" (str), "parcel_local_id"(int), | 7170 | //body has "region_name" (str), "parcel_local_id"(int), |
7014 | //"voice_credentials" (map). | 7171 | //"voice_credentials" (map). |
7015 | 7172 | ||
@@ -7036,7 +7193,10 @@ class LLViewerParcelVoiceInfo : public LLHTTPNode | |||
7036 | voice_credentials["channel_credentials"].asString(); | 7193 | voice_credentials["channel_credentials"].asString(); |
7037 | } | 7194 | } |
7038 | 7195 | ||
7039 | gVoiceClient->setSpatialChannel(uri, credentials); | 7196 | LLUUID response_id; |
7197 | response_id.generate(); | ||
7198 | gVoiceClient->setPIRCapResponseID(response_id); | ||
7199 | gVoiceClient->setSpatialChannel(uri, credentials, response_id); | ||
7040 | } | 7200 | } |
7041 | } | 7201 | } |
7042 | } | 7202 | } |
@@ -7050,10 +7210,13 @@ class LLViewerRequiredVoiceVersion : public LLHTTPNode | |||
7050 | const LLSD& context, | 7210 | const LLSD& context, |
7051 | const LLSD& input) const | 7211 | const LLSD& input) const |
7052 | { | 7212 | { |
7213 | |||
7053 | //You received this messsage (most likely on region cross or | 7214 | //You received this messsage (most likely on region cross or |
7054 | //teleport) | 7215 | //teleport) |
7055 | if ( input.has("body") && input["body"].has("major_version") ) | 7216 | if ( input.has("body") && input["body"].has("major_version") ) |
7056 | { | 7217 | { |
7218 | LL_DEBUGS("VoiceCaps") << "RequiredVoiceVersion response: " | ||
7219 | << ll_pretty_print_sd(input)<< LL_ENDL; | ||
7057 | int major_voice_version = | 7220 | int major_voice_version = |
7058 | input["body"]["major_version"].asInteger(); | 7221 | input["body"]["major_version"].asInteger(); |
7059 | // int minor_voice_version = | 7222 | // int minor_voice_version = |