From f5c5c5ec9497211010b5a4dd15bea44d4bbc8482 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Tue, 16 Apr 2024 23:11:44 -0700 Subject: Issue in WebRTC was disabling custom audio processing (level detection) There is a case where the custom audio processor, which is used to determine audio levels, was disabled on connection shutdown even when another connection was established. This issue has been patched in the webrtc library. --- autobuild.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index f9c99514a1..625fe72449 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -2901,11 +2901,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors creds github hash - a49fb3bb8aaf8325e7c6c4b6036db3da16afa2c9 + 21e31d2c2fffdb59d8f50b80db079f86f2df2483 hash_algorithm sha1 url - https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.53/webrtc-m114.5735.08.53.8337236647-darwin64-8337236647.tar.zst + https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.58/webrtc-m114.5735.08.58.8716173807-darwin64-8716173807.tar.zst name darwin64 @@ -2915,11 +2915,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 598baa054f63624a8e16883541c1f3dc7aa15a8a + 600cabb49a889db3a29f2910f5bda08f28dd04c8 hash_algorithm sha1 url - https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.53/webrtc-m114.5735.08.53.8337236647-linux64-8337236647.tar.zst + https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.58/webrtc-m114.5735.08.58.8716173807-linux64-8716173807.tar.zst name linux64 @@ -2931,11 +2931,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors creds github hash - 59d5f2e40612ab7b0b1a5da8ba288f48d5979216 + 915c9face95efcc6da240aa2c4f8e6c4aa803af8 hash_algorithm sha1 url - https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.53/webrtc-m114.5735.08.53.8337236647-windows64-8337236647.tar.zst + https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.58/webrtc-m114.5735.08.58.8716173807-windows64-8716173807.tar.zst name windows64 -- cgit v1.2.3 From 53c584e1ded5faf8e572ac7b849e53a91fed6206 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Tue, 16 Apr 2024 23:22:39 -0700 Subject: Fix cases where voice outstanding requests could be dropped, resulting in no voice --- indra/newview/llvoicewebrtc.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 710067c2bf..7743d6362a 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -2192,6 +2192,7 @@ void LLVoiceWebRTCConnection::processIceUpdatesCoro() if (LLWebRTCVoiceClient::isShuttingDown()) { + mOutstandingRequests--; return; } @@ -2281,6 +2282,7 @@ void LLVoiceWebRTCConnection::OnRenegotiationNeeded() { setVoiceConnectionState(VOICE_STATE_SESSION_RETRY); } + mCurrentStatus = LLVoiceClientStatusObserver::ERROR_UNKNOWN; }); } @@ -2369,6 +2371,7 @@ void LLVoiceWebRTCConnection::breakVoiceConnectionCoro() { LL_DEBUGS("Voice") << "no capabilities for voice provisioning; waiting " << LL_ENDL; setVoiceConnectionState(VOICE_STATE_SESSION_RETRY); + mOutstandingRequests--; return; } @@ -2376,6 +2379,7 @@ void LLVoiceWebRTCConnection::breakVoiceConnectionCoro() if (url.empty()) { setVoiceConnectionState(VOICE_STATE_SESSION_RETRY); + mOutstandingRequests--; return; } @@ -2405,6 +2409,7 @@ void LLVoiceWebRTCConnection::breakVoiceConnectionCoro() if (LLWebRTCVoiceClient::isShuttingDown()) { + mOutstandingRequests--; return; } -- cgit v1.2.3 From b59ff9edc085f74add1b228fe849ad7e7c31f65f Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Fri, 19 Apr 2024 18:52:32 -0700 Subject: For p2p/adhoc/group calls, prefer voice server type based on what's running on the region --- indra/newview/app_settings/settings.xml | 4 ++-- indra/newview/llimview.cpp | 18 ++++++++++++++++-- indra/newview/llvoicechannel.cpp | 9 ++++++++- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 0de6db0d65..3ac1844f8e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -15155,13 +15155,13 @@ VoiceServerType Comment - The type of voice server to connect to. + The type of voice server to use for group, conference, and p2p calls. Persist 0 Type String Value - webrtc + WLSkyDetail diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 9c8fcd3283..b590c462fa 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -425,7 +425,14 @@ void startConferenceCoro(std::string url, postData["session-id"] = tempSessionId; postData["params"] = agents; LLSD altParams; - altParams["voice_server_type"] = gSavedSettings.getString("VoiceServerType"); + std::string voice_server_type = gSavedSettings.getString("VoiceServerType"); + if (voice_server_type.empty()) + { + // default to the server type associated with the region we're on. + LLVoiceVersionInfo versionInfo = LLVoiceClient::getInstance()->getVersion(); + voice_server_type = versionInfo.internalVoiceServerType; + } + altParams["voice_server_type"] = voice_server_type; postData["alt_params"] = altParams; LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); @@ -467,7 +474,14 @@ void startP2PVoiceCoro(std::string url, LLUUID sessionID, LLUUID creatorId, LLUU postData["session-id"] = sessionID; postData["params"] = otherParticipantId; LLSD altParams; - altParams["voice_server_type"] = gSavedSettings.getString("VoiceServerType"); + std::string voice_server_type = gSavedSettings.getString("VoiceServerType"); + if (voice_server_type.empty()) + { + // default to the server type associated with the region we're on. + LLVoiceVersionInfo versionInfo = LLVoiceClient::getInstance()->getVersion(); + voice_server_type = versionInfo.internalVoiceServerType; + } + altParams["voice_server_type"] = voice_server_type; postData["alt_params"] = altParams; LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index f6658bbaab..92b00fe854 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -594,7 +594,14 @@ void LLVoiceChannelGroup::voiceCallCapCoro(std::string url) postData["method"] = "call"; postData["session-id"] = mSessionID; LLSD altParams; - altParams["preferred_voice_server_type"] = gSavedSettings.getString("VoiceServerType"); + std::string preferred_voice_server_type = gSavedSettings.getString("VoiceServerType"); + if (preferred_voice_server_type.empty()) + { + // default to the server type associated with the region we're on. + LLVoiceVersionInfo versionInfo = LLVoiceClient::getInstance()->getVersion(); + preferred_voice_server_type = versionInfo.internalVoiceServerType; + } + altParams["preferred_voice_server_type"] = preferred_voice_server_type; postData["alt_params"] = altParams; LL_INFOS("Voice", "voiceCallCapCoro") << "Generic POST for " << url << LL_ENDL; -- cgit v1.2.3 From 784dae7e6a085577df91845466c910b2bcbf7d81 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Sat, 20 Apr 2024 00:19:55 -0700 Subject: re-enabling vivox voice didn't bring it back as it thought it was still in the region and parcel. --- indra/newview/llvoicevivox.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index be9e055203..6ff81760b2 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -5456,6 +5456,8 @@ void LLVivoxVoiceClient::setVoiceEnabled(bool enabled) LLVoiceChannel::getCurrentVoiceChannel()->deactivate(); gAgent.setVoiceConnected(false); status = LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED; + mCurrentParcelLocalID = -1; + mCurrentRegionName.clear(); } notifyStatusObservers(status); -- cgit v1.2.3 From 1a1af1ce2989d384c5dabf4dce9bc150a69b02c1 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Sat, 20 Apr 2024 00:26:39 -0700 Subject: Adjust logic for determine what voice server type to use. --- indra/newview/llimview.cpp | 24 +----------------------- indra/newview/llvoiceclient.cpp | 12 +++++++++--- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index b590c462fa..efa8bd2109 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -424,17 +424,6 @@ void startConferenceCoro(std::string url, postData["method"] = "start conference"; postData["session-id"] = tempSessionId; postData["params"] = agents; - LLSD altParams; - std::string voice_server_type = gSavedSettings.getString("VoiceServerType"); - if (voice_server_type.empty()) - { - // default to the server type associated with the region we're on. - LLVoiceVersionInfo versionInfo = LLVoiceClient::getInstance()->getVersion(); - voice_server_type = versionInfo.internalVoiceServerType; - } - altParams["voice_server_type"] = voice_server_type; - postData["alt_params"] = altParams; - LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; @@ -473,17 +462,6 @@ void startP2PVoiceCoro(std::string url, LLUUID sessionID, LLUUID creatorId, LLUU postData["method"] = "start p2p voice"; postData["session-id"] = sessionID; postData["params"] = otherParticipantId; - LLSD altParams; - std::string voice_server_type = gSavedSettings.getString("VoiceServerType"); - if (voice_server_type.empty()) - { - // default to the server type associated with the region we're on. - LLVoiceVersionInfo versionInfo = LLVoiceClient::getInstance()->getVersion(); - voice_server_type = versionInfo.internalVoiceServerType; - } - altParams["voice_server_type"] = voice_server_type; - postData["alt_params"] = altParams; - LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; @@ -2133,7 +2111,7 @@ bool LLIMModel::sendStartSession( //we also need to wait for reply from the server in case of ad-hoc chat (we'll get new session id) return true; } - else if ((dialog == IM_SESSION_P2P_INVITE) || (dialog == IM_NOTHING_SPECIAL)) + else if (p2p_as_adhoc_call && ((dialog == IM_SESSION_P2P_INVITE) || (dialog == IM_NOTHING_SPECIAL))) { LLViewerRegion *region = gAgent.getRegion(); if (region) diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 9dbf469ca8..6eadc3892e 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -538,12 +538,18 @@ LLVoiceP2PIncomingCallInterfacePtr LLVoiceClient::getIncomingCallInterface(const // outgoing calls LLVoiceP2POutgoingCallInterface *LLVoiceClient::getOutgoingCallInterface(const LLSD& voiceChannelInfo) { - std::string voiceServerType = gSavedSettings.getString("VoiceServerType"); + std::string voice_server_type = gSavedSettings.getString("VoiceServerType"); + if (voice_server_type.empty()) + { + // default to the server type associated with the region we're on. + LLVoiceVersionInfo versionInfo = LLVoiceClient::getInstance()->getVersion(); + voice_server_type = versionInfo.internalVoiceServerType; + } if (voiceChannelInfo.has("voice_server_type")) { - voiceServerType = voiceChannelInfo["voice_server_type"].asString(); + voice_server_type = voiceChannelInfo["voice_server_type"].asString(); } - LLVoiceModuleInterface *module = getVoiceModule(voiceServerType); + LLVoiceModuleInterface *module = getVoiceModule(voice_server_type); return dynamic_cast(module); } -- cgit v1.2.3 From 07d7779d87552133e98df835bfdcb0a1fb5b10ca Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Sat, 20 Apr 2024 17:34:27 -0700 Subject: Vivox wasn't ren-enabling voice after ending a p2p call --- indra/newview/llvoicevivox.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 6ff81760b2..88fc40e565 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -4952,6 +4952,7 @@ bool LLVivoxVoiceClient::setSpatialChannel(const LLSD& channelInfo) void LLVivoxVoiceClient::callUser(const LLUUID &uuid) { std::string userURI = sipURIFromID(uuid); + mProcessChannels = true; switchChannel(userURI, false, true, true); } @@ -4974,7 +4975,7 @@ bool LLVivoxVoiceClient::answerInvite(const std::string &sessionHandle) session->mIsSpatial = false; session->mReconnect = false; session->mIsP2P = true; - + mProcessChannels = true; joinSession(session); return true; } @@ -5078,7 +5079,9 @@ void LLVivoxVoiceClient::leaveNonSpatialChannel() void LLVivoxVoiceClient::processChannels(bool process) { - mProcessChannels = process; + mCurrentParcelLocalID = -1; + mCurrentRegionName.clear(); + mProcessChannels = process; } bool LLVivoxVoiceClient::isCurrentChannel(const LLSD &channelInfo) -- cgit v1.2.3 From 98322d5f070b260f1e46eb5d9fcd54fa43151329 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Sun, 21 Apr 2024 21:12:06 -0700 Subject: Reconnect when parcel voice params change. When parcel voice permissions and region/parcel-only voice settings change, a callback will be made to the viewer with new voice credential information. For webrtc, this means either just the uuid of the voice channel, or nothing if voice is disabled. This change looks at that callback and the channel id, and sets the appropriate flags on the parcel/region as needed which will cause voice to be renegotiated. Also, there was a race condition if the voice connect attempt was made before caps were retrieved, which would have resulted in full renegotiate attempts. Now, just wait until the cap comes in and continue. --- indra/llwebrtc/llwebrtc.cpp | 4 ++++ indra/newview/llvoicewebrtc.cpp | 40 ++++++++++++++++++++++++++++++++++++---- indra/newview/llvoicewebrtc.h | 7 +------ 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index eb9bb65e67..e08ace12c5 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -735,6 +735,10 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection(const LLWebRTCPeerConnecti else { RTC_LOG(LS_ERROR) << __FUNCTION__ << "Error creating peer connection: " << error_or_peer_connection.error().message(); + for (auto &observer : mSignalingObserverList) + { + observer->OnRenegotiationNeeded(); + } return; } diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 7743d6362a..c6e9d3d1ec 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -1269,6 +1269,35 @@ BOOL LLWebRTCVoiceClient::isSessionCallBackPossible(const LLUUID &session_id) } // Channel Management + +bool LLWebRTCVoiceClient::setSpatialChannel(const LLSD &channelInfo) +{ + LL_INFOS("Voice") << "SetSpatialChannel " << channelInfo << LL_ENDL; + LLViewerRegion *regionp = gAgent.getRegion(); + if (!regionp) + { + return false; + } + LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + + // we don't really have credentials for a spatial channel in webrtc, + // it's all handled by the sim. + if (channelInfo.isMap() && channelInfo.has("channel_uri")) + { + bool allow_voice = !channelInfo["channel_uri"].asString().empty(); + if (parcel) + { + parcel->setParcelFlag(PF_ALLOW_VOICE_CHAT, allow_voice); + parcel->setParcelFlag(PF_USE_ESTATE_VOICE_CHAN, channelInfo["channel_uri"].asUUID() == regionp->getRegionID()); + } + else + { + regionp->setRegionFlag(REGION_FLAGS_ALLOW_VOICE, allow_voice); + } + } + return true; +} + void LLWebRTCVoiceClient::leaveNonSpatialChannel() { LL_DEBUGS("Voice") << "Request to leave non-spatial channel." << LL_ENDL; @@ -2116,7 +2145,7 @@ void LLVoiceWebRTCConnection::OnIceCandidate(const llwebrtc::LLWebRTCIceCandidat void LLVoiceWebRTCConnection::processIceUpdates() { mOutstandingRequests++; - LLCoros::getInstance()->launch("LLVoiceWebRTCConnection::requestVoiceConnectionCoro", + LLCoros::getInstance()->launch("LLVoiceWebRTCConnection::processIceUpdatesCoro", boost::bind(&LLVoiceWebRTCConnection::processIceUpdatesCoro, this)); } @@ -2436,7 +2465,9 @@ void LLVoiceWebRTCSpatialConnection::requestVoiceConnection() if (!regionp || !regionp->capabilitiesReceived()) { LL_DEBUGS("Voice") << "no capabilities for voice provisioning; waiting " << LL_ENDL; - setVoiceConnectionState(VOICE_STATE_SESSION_RETRY); + + // try again. + setVoiceConnectionState(VOICE_STATE_REQUEST_CONNECTION); return; } @@ -2988,8 +3019,9 @@ void LLVoiceWebRTCAdHocConnection::requestVoiceConnection() LL_DEBUGS("Voice") << "Requesting voice connection." << LL_ENDL; if (!regionp || !regionp->capabilitiesReceived()) { - LL_DEBUGS("Voice") << "no capabilities for voice provisioning; waiting " << LL_ENDL; - setVoiceConnectionState(VOICE_STATE_SESSION_RETRY); + LL_DEBUGS("Voice") << "no capabilities for voice provisioning; retrying " << LL_ENDL; + // try again. + setVoiceConnectionState(VOICE_STATE_REQUEST_CONNECTION); return; } diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h index aa3298ec1b..67e4a4ea6f 100644 --- a/indra/newview/llvoicewebrtc.h +++ b/indra/newview/llvoicewebrtc.h @@ -144,12 +144,7 @@ public: startAdHocSession(channelInfo, notify_on_first_join, hangup_on_last_leave); } - bool setSpatialChannel(const LLSD &channelInfo) override - { - // we don't really have credentials for a spatial channel in webrtc, - // it's all handled by the sim. - return true; - } + bool setSpatialChannel(const LLSD &channelInfo) override; void leaveNonSpatialChannel() override; -- cgit v1.2.3 From 534ddc52900261789416034a621b8b1d5617920e Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Tue, 23 Apr 2024 10:57:02 -0700 Subject: Before login, voice device preferences were not populated. Before login, when the user shows voice device preferences, the dropdowns were not populated. This is because WebRTC's view of the main queue was not configured. --- indra/newview/llvoicewebrtc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index c6e9d3d1ec..2f85189f45 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -254,6 +254,7 @@ void LLWebRTCVoiceClient::init(LLPumpIO* pump) mWebRTCDeviceInterface = llwebrtc::getDeviceInterface(); mWebRTCDeviceInterface->setDevicesObserver(this); + mMainQueue = LL::WorkQueue::getInstance("mainloop"); } void LLWebRTCVoiceClient::terminate() @@ -1486,7 +1487,6 @@ void LLWebRTCVoiceClient::setVoiceEnabled(bool enabled) updatePosition(); if (!mIsCoroutineActive) { - mMainQueue = LL::WorkQueue::getInstance("mainloop"); LLCoros::instance().launch("LLWebRTCVoiceClient::voiceConnectionCoro", boost::bind(&LLWebRTCVoiceClient::voiceConnectionCoro, LLWebRTCVoiceClient::getInstance())); } -- cgit v1.2.3 From 4c4d23acb00960d1bc812eab4656d3f4cdcd70e3 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Fri, 26 Apr 2024 21:31:06 -0700 Subject: Renegotiate voice if the voice server type has changed. The server will send an update with new voice credentials when another peer comes in requiring vivox, if the channel was initially webrtc. --- indra/newview/llimview.cpp | 190 +++++++++++++++------ indra/newview/llimview.h | 9 +- indra/newview/llspeakers.cpp | 2 +- indra/newview/llspeakers.h | 1 + indra/newview/llvoicechannel.cpp | 10 +- indra/newview/llvoiceclient.h | 2 +- indra/newview/llvoicevivox.cpp | 7 +- indra/newview/llvoicewebrtc.cpp | 8 +- .../skins/default/xui/en/floater_incoming_call.xml | 2 +- 9 files changed, 158 insertions(+), 73 deletions(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index efa8bd2109..58ac681ad8 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -104,7 +104,7 @@ void startConferenceCoro(std::string url, LLUUID tempSessionId, LLUUID creatorId void startP2PVoiceCoro(std::string url, LLUUID tempSessionId, LLUUID creatorId, LLUUID otherParticipantId); -void chatterBoxInvitationCoro(std::string url, LLUUID sessionId, LLIMMgr::EInvitationType invitationType); +void chatterBoxInvitationCoro(std::string url, LLUUID sessionId, LLIMMgr::EInvitationType invitationType, const LLSD& voiceChannelInfo); void chatterBoxHistoryCoro(std::string url, LLUUID sessionId, std::string from, std::string message, U32 timestamp); void start_deprecated_conference_chat(const LLUUID& temp_session_id, const LLUUID& creator_id, const LLUUID& other_participant_id, const LLSD& agents_to_invite); @@ -424,6 +424,17 @@ void startConferenceCoro(std::string url, postData["method"] = "start conference"; postData["session-id"] = tempSessionId; postData["params"] = agents; + LLSD altParams; + std::string voice_server_type = gSavedSettings.getString("VoiceServerType"); + if (voice_server_type.empty()) + { + // default to the server type associated with the region we're on. + LLVoiceVersionInfo versionInfo = LLVoiceClient::getInstance()->getVersion(); + voice_server_type = versionInfo.internalVoiceServerType; + } + altParams["voice_server_type"] = voice_server_type; + postData["alt_params"] = altParams; + LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; @@ -462,6 +473,17 @@ void startP2PVoiceCoro(std::string url, LLUUID sessionID, LLUUID creatorId, LLUU postData["method"] = "start p2p voice"; postData["session-id"] = sessionID; postData["params"] = otherParticipantId; + LLSD altParams; + std::string voice_server_type = gSavedSettings.getString("VoiceServerType"); + if (voice_server_type.empty()) + { + // default to the server type associated with the region we're on. + LLVoiceVersionInfo versionInfo = LLVoiceClient::getInstance()->getVersion(); + voice_server_type = versionInfo.internalVoiceServerType; + } + altParams["voice_server_type"] = voice_server_type; + postData["alt_params"] = altParams; + LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; @@ -480,7 +502,7 @@ void startP2PVoiceCoro(std::string url, LLUUID sessionID, LLUUID creatorId, LLUU } } -void chatterBoxInvitationCoro(std::string url, LLUUID sessionId, LLIMMgr::EInvitationType invitationType) +void chatterBoxInvitationCoro(std::string url, LLUUID sessionId, LLIMMgr::EInvitationType invitationType, const LLSD& voiceChannelInfo) { LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t @@ -546,7 +568,7 @@ void chatterBoxInvitationCoro(std::string url, LLUUID sessionId, LLIMMgr::EInvit if (LLIMMgr::INVITATION_TYPE_VOICE == invitationType) { - gIMMgr->startCall(sessionId, LLVoiceChannel::INCOMING_CALL); + gIMMgr->startCall(sessionId, LLVoiceChannel::INCOMING_CALL, voiceChannelInfo); } if ((invitationType == LLIMMgr::INVITATION_TYPE_VOICE @@ -690,8 +712,8 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, + const LLSD& voice_channel_info, const uuid_vec_t& ids, - const LLSD& voiceChannelInfo, bool has_offline_msg) : mSessionID(session_id), mName(name), @@ -702,56 +724,30 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, mOtherParticipantID(other_participant_id), mInitialTargetIDs(ids), mVoiceChannel(NULL), + mP2PAsAdhocCall(false), mSpeakers(NULL), mSessionInitialized(false), mCallBackEnabled(true), mTextIMPossible(true), mStartCallOnInitialize(false), - mStartedAsIMCall(!voiceChannelInfo.isUndefined()), + mStartedAsIMCall(!voice_channel_info.isUndefined()), mIsDNDsend(false), mAvatarNameCacheConnection() { // set P2P type by default mSessionType = P2P_SESSION; - bool p2pAsAdhocCall = false; if (IM_NOTHING_SPECIAL == mType || IM_SESSION_P2P_INVITE == mType) { - LLVoiceP2POutgoingCallInterface *outgoingInterface = - LLVoiceClient::getInstance()->getOutgoingCallInterface(voiceChannelInfo); - - if (outgoingInterface) - { - // only use LLVoiceChannelP2P if the provider can handle the special P2P interface, - // which uses the voice server to relay calls and invites. Otherwise, - // we use the group voice provider. - mVoiceChannel = new LLVoiceChannelP2P(session_id, name, other_participant_id, outgoingInterface); - } - else - { - p2pAsAdhocCall = true; - mVoiceChannel = new LLVoiceChannelGroup(session_id, name, true); - } - } - else - { - // determine whether it is group or conference session - if (gAgent.isInGroup(mSessionID)) - { - mSessionType = GROUP_SESSION; - mVoiceChannel = new LLVoiceChannelGroup(session_id, name, false); - } - else - { - mSessionType = ADHOC_SESSION; - mVoiceChannel = new LLVoiceChannelGroup(session_id, name, false); - } + mP2PAsAdhocCall = (LLVoiceClient::getInstance()->getOutgoingCallInterface(voice_channel_info) == NULL); } + else + { + // determine whether it is group or conference session + mSessionType = gAgent.isInGroup(mSessionID) ? GROUP_SESSION : ADHOC_SESSION; + } - mVoiceChannelStateChangeConnection = mVoiceChannel->setStateChangedCallback(boost::bind(&LLIMSession::onVoiceChannelStateChanged, this, _1, _2, _3)); - mVoiceChannel->setChannelInfo(voiceChannelInfo); - - mSpeakers = new LLIMSpeakerMgr(mVoiceChannel); + initVoiceChannel(voice_channel_info); // All participants will be added to the list of people we've recently interacted with. @@ -761,7 +757,7 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, //we need to wait for session initialization for outgoing ad-hoc and group chat session //correct session id for initiated ad-hoc chat will be received from the server - if (!LLIMModel::getInstance()->sendStartSession(mSessionID, mOtherParticipantID, mInitialTargetIDs, mType, p2pAsAdhocCall)) + if (!LLIMModel::getInstance()->sendStartSession(mSessionID, mOtherParticipantID, mInitialTargetIDs, mType, mP2PAsAdhocCall)) { //we don't need to wait for any responses //so we're already initialized @@ -791,6 +787,68 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, } } +void LLIMModel::LLIMSession::initVoiceChannel(const LLSD& voiceChannelInfo) +{ + mVoiceChannelStateChangeConnection.disconnect(); + + if (mVoiceChannel) + { + mVoiceChannel->deactivate(); + + delete mVoiceChannel; + mVoiceChannel = NULL; + } + mP2PAsAdhocCall = false; + if (IM_NOTHING_SPECIAL == mType || IM_SESSION_P2P_INVITE == mType) + { + LLVoiceP2POutgoingCallInterface *outgoingInterface = LLVoiceClient::getInstance()->getOutgoingCallInterface(voiceChannelInfo); + + if (outgoingInterface) + { + // only use LLVoiceChannelP2P if the provider can handle the special P2P interface, + // which uses the voice server to relay calls and invites. Otherwise, + // we use the group voice provider. + mVoiceChannel = new LLVoiceChannelP2P(mSessionID, mName, mOtherParticipantID, outgoingInterface); + } + else + { + mP2PAsAdhocCall = true; + mVoiceChannel = new LLVoiceChannelGroup(mSessionID, mName, true); + } + } + else + { + // determine whether it is group or conference session + if (mSessionType == GROUP_SESSION) + { + mSessionType = GROUP_SESSION; + mVoiceChannel = new LLVoiceChannelGroup(mSessionID, mName, false); + } + else if (mSessionType == ADHOC_SESSION) + { + mSessionType = ADHOC_SESSION; + mVoiceChannel = new LLVoiceChannelGroup(mSessionID, mName, false); + } + else + { + LL_WARNS("Voice") << "Invalid Session Type when initializing voice channel: " << mSessionType << LL_ENDL; + return; + } + } + + mVoiceChannelStateChangeConnection = + mVoiceChannel->setStateChangedCallback(boost::bind(&LLIMSession::onVoiceChannelStateChanged, this, _1, _2, _3)); + + if (!mSpeakers) + { + mSpeakers = new LLIMSpeakerMgr(mVoiceChannel); + } + else + { + mSpeakers->setVoiceChannel(mVoiceChannel); + } +} + void LLIMModel::LLIMSession::onAdHocNameCache(const LLAvatarName& av_name) { mAvatarNameCacheConnection.disconnect(); @@ -894,7 +952,7 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES break; } // Update speakers list when connected - if (LLVoiceChannel::STATE_CONNECTED == new_state) + if (mSpeakers && LLVoiceChannel::STATE_CONNECTED == new_state) { mSpeakers->update(true); } @@ -926,7 +984,10 @@ void LLIMModel::LLIMSession::sessionInitReplyReceived(const LLUUID& new_session_ if (new_session_id != mSessionID) { mSessionID = new_session_id; - mVoiceChannel->updateSessionID(new_session_id); + if (mVoiceChannel) + { + mVoiceChannel->updateSessionID(new_session_id); + } } } @@ -1498,7 +1559,7 @@ bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, co return false; } - LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids, voiceChannelInfo, has_offline_msg); + LLIMSession *session = new LLIMSession(session_id, name, type, other_participant_id, voiceChannelInfo, ids, has_offline_msg); mId2SessionMap[session_id] = session; // When notifying observer, name of session is used instead of "name", because they may not be the @@ -1762,7 +1823,7 @@ EInstantMessage LLIMModel::getType(const LLUUID& session_id) const return session->mType; } -LLVoiceChannel* LLIMModel::getVoiceChannel( const LLUUID& session_id ) const +LLVoiceChannel* LLIMModel::getVoiceChannel( const LLUUID& session_id, const LLSD& voice_channel_info ) const { LLIMSession* session = findIMSession(session_id); if (!session) @@ -1770,6 +1831,14 @@ LLVoiceChannel* LLIMModel::getVoiceChannel( const LLUUID& session_id ) const LL_WARNS() << "session " << session_id << "does not exist " << LL_ENDL; return NULL; } + if (IM_NOTHING_SPECIAL == session->mType || IM_SESSION_P2P_INVITE == session->mType) + { + LLVoiceP2POutgoingCallInterface *outgoingInterface = LLVoiceClient::getInstance()->getOutgoingCallInterface(voice_channel_info); + if ((outgoingInterface != NULL) != (dynamic_cast(session->mVoiceChannel) != NULL)) + { + session->initVoiceChannel(voice_channel_info); + } + } return session->mVoiceChannel; } @@ -2111,7 +2180,7 @@ bool LLIMModel::sendStartSession( //we also need to wait for reply from the server in case of ad-hoc chat (we'll get new session id) return true; } - else if (p2p_as_adhoc_call && ((dialog == IM_SESSION_P2P_INVITE) || (dialog == IM_NOTHING_SPECIAL))) + else if (p2p_as_adhoc_call && ((dialog == IM_SESSION_P2P_INVITE) || (dialog == IM_NOTHING_SPECIAL))) { LLViewerRegion *region = gAgent.getRegion(); if (region) @@ -2732,7 +2801,7 @@ void LLIncomingCallDialog::onLifetimeExpired() LLUUID session_id = mPayload["session_id"].asUUID(); gIMMgr->clearPendingAgentListUpdates(session_id); gIMMgr->clearPendingInvitation(session_id); - closeFloater(); + LLIncomingCallDialog::onReject(this); } } @@ -2921,7 +2990,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload if (voice) { - gIMMgr->startCall(session_id, LLVoiceChannel::INCOMING_CALL); + gIMMgr->startCall(session_id, LLVoiceChannel::INCOMING_CALL, payload["voice_channel_info"]); } else { @@ -2975,8 +3044,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload if (voice) { LLCoros::instance().launch("chatterBoxInvitationCoro", - boost::bind(&chatterBoxInvitationCoro, url, - session_id, inv_type)); + boost::bind(&chatterBoxInvitationCoro, url, session_id, inv_type, payload["voice_channel_info"])); // send notification message to the corresponding chat if (payload["notify_box_type"].asString() == "VoiceInviteGroup" || payload["notify_box_type"].asString() == "VoiceInviteAdHoc") @@ -3460,7 +3528,6 @@ void LLIMMgr::inviteToSession( payload["caller_name"] = caller_name; payload["type"] = type; payload["inv_type"] = inv_type; - payload["voice_channel_info"] = voice_channel_info; payload["notify_box_type"] = notify_box_type; payload["question_type"] = question_type; @@ -3490,7 +3557,6 @@ void LLIMMgr::inviteToSession( LLIncomingCallDialog::processCallResponse(0, payload); return; } - if (voice_invite) { bool isRejectGroupCall = (gSavedSettings.getBOOL("VoiceCallsRejectGroup") && (notify_box_type == "VoiceInviteGroup")); @@ -3529,6 +3595,9 @@ void LLIMMgr::inviteToSession( if ( !mPendingInvitations.has(session_id.asString()) ) { + // we're throwing up a dialogue, so we're using the voice channel passed to us, + // save it in the payload. + payload["voice_channel_info"] = voice_channel_info; if (caller_name.empty()) { LLAvatarNameCache::get(caller_id, @@ -3773,9 +3842,9 @@ void LLIMMgr::removeSessionObserver(LLIMSessionObserver *observer) mSessionObservers.remove(observer); } -bool LLIMMgr::startCall(const LLUUID& session_id, LLVoiceChannel::EDirection direction) +bool LLIMMgr::startCall(const LLUUID& session_id, LLVoiceChannel::EDirection direction, const LLSD& voice_channel_info) { - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id); + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id, voice_channel_info); if (!voice_channel) return false; voice_channel->setCallDirection(direction); voice_channel->activate(); @@ -3784,7 +3853,7 @@ bool LLIMMgr::startCall(const LLUUID& session_id, LLVoiceChannel::EDirection dir bool LLIMMgr::endCall(const LLUUID& session_id) { - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id); + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id, LLSD()); if (!voice_channel) return false; voice_channel->deactivate(); @@ -4078,6 +4147,15 @@ public: { im_mgr->processSessionUpdate(input["body"]["info"]); } + if (input["body"]["info"].has("voice_channel_info")) + { + LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); + if (session) + { + session->initVoiceChannel(input["body"]["info"]["voice_channel_info"]); + session->mVoiceChannel->activate(); + } + } } }; @@ -4162,7 +4240,7 @@ public: { LLCoros::instance().launch("chatterBoxInvitationCoro", boost::bind(&chatterBoxInvitationCoro, url, - session_id, LLIMMgr::INVITATION_TYPE_INSTANT_MESSAGE)); + session_id, LLIMMgr::INVITATION_TYPE_INSTANT_MESSAGE, LLSD())); } } //end if invitation has instant message else if ( input["body"].has("voice") ) @@ -4174,7 +4252,7 @@ public: } BOOL session_type_p2p = input["body"]["voice"].get("invitation_type").asInteger() == EMultiAgentChatSessionType::P2P_CHAT_SESSION; - LL_DEBUGS("Voice") << "Received P2P voice information from the server: " << input["body"]<< LL_ENDL; + LL_DEBUGS("Voice") << "Received voice information from the server: " << input["body"]<< LL_ENDL; gIMMgr->inviteToSession( input["body"]["session_id"].asUUID(), input["body"]["session_name"].asString(), diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 93a1a95b23..16444a6755 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -80,9 +80,11 @@ public: } SType; LLIMSession(const LLUUID& session_id, const std::string& name, - const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, const LLSD& voiceChannelInfo, bool has_offline_msg); + const EInstantMessage& type, const LLUUID& other_participant_id, const LLSD& voiceChannelInfo, const uuid_vec_t& ids, bool has_offline_msg); virtual ~LLIMSession(); + void initVoiceChannel(const LLSD &voiceChannelInfo = LLSD()); + void sessionInitReplyReceived(const LLUUID& new_session_id); void addMessagesFromHistoryCache(const std::list& history); // From local file void addMessagesFromServerHistory(const LLSD& history, const std::string& target_from, const std::string& target_message, U32 timestamp); // From chat server @@ -141,6 +143,7 @@ public: LLVoiceChannel* mVoiceChannel; LLIMSpeakerMgr* mSpeakers; + bool mP2PAsAdhocCall; bool mSessionInitialized; @@ -284,7 +287,7 @@ public: * Get voice channel for the session specified by session_id * Returns NULL if the session does not exist */ - LLVoiceChannel* getVoiceChannel(const LLUUID& session_id) const; + LLVoiceChannel* getVoiceChannel(const LLUUID& session_id, const LLSD& voice_channel_info = LLSD()) const; /** * Get im speaker manager for the session specified by session_id @@ -464,7 +467,7 @@ public: * Start call in a session * @return false if voice channel doesn't exist **/ - bool startCall(const LLUUID& session_id, LLVoiceChannel::EDirection direction = LLVoiceChannel::OUTGOING_CALL); + bool startCall(const LLUUID& session_id, LLVoiceChannel::EDirection direction = LLVoiceChannel::OUTGOING_CALL, const LLSD& voice_channel_info = LLSD()); /** * End call in a session diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 60bada8f58..00691d4382 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -618,7 +618,7 @@ void LLSpeakerMgr::getSpeakerList(speaker_list_t* speaker_list, BOOL include_tex const LLUUID LLSpeakerMgr::getSessionID() { - return mVoiceChannel->getSessionID(); + return mVoiceChannel ? mVoiceChannel->getSessionID() : LLUUID(); } bool LLSpeakerMgr::isSpeakerToBeRemoved(const LLUUID& speaker_id) diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 22c9481687..ba1dfec226 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -241,6 +241,7 @@ public: typedef std::vector > speaker_list_t; void getSpeakerList(speaker_list_t* speaker_list, BOOL include_text); LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; } + void setVoiceChannel(LLVoiceChannel *voiceChannel) { mVoiceChannel = voiceChannel; } const LLUUID getSessionID(); bool isSpeakerToBeRemoved(const LLUUID& speaker_id); diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 92b00fe854..7138a8b391 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -152,13 +152,16 @@ void LLVoiceChannel::handleStatusChange(EStatusType type) case STATUS_LOGGED_IN: break; case STATUS_LEFT_CHANNEL: - if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended) + if (callStarted() && !sSuspended) { // if forceably removed from channel // update the UI and revert to default channel + // deactivate will set the State to STATE_HUNG_UP + // so when handleStatusChange is called again during + // shutdown callStarted will return false and deactivate + // won't be called again. deactivate(); } - mIgnoreNextSessionLeave = FALSE; break; case STATUS_JOINING: if (callStarted()) @@ -433,7 +436,7 @@ void LLVoiceChannelGroup::activate() // Adding ad-hoc call participants to Recent People List. // If it's an outgoing ad-hoc, we can use mInitialTargetIDs that holds IDs of people we // called(both online and offline) as source to get people for recent (STORM-210). - if (session->isOutgoingAdHoc()) + if (session && session->isOutgoingAdHoc()) { for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin(); it != session->mInitialTargetIDs.end(); ++it) { @@ -471,6 +474,7 @@ void LLVoiceChannelGroup::requestChannelInfo() void LLVoiceChannelGroup::setChannelInfo(const LLSD& channelInfo) { mChannelInfo = channelInfo; + LL_INFOS("Voice") << "setChannelInfo: " << channelInfo << LL_ENDL; if (mState == STATE_NO_CHANNEL_INFO) { diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 3b1b3bd0c4..c1e0ab0c35 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -421,7 +421,7 @@ public: // initiate a call with a peer using the P2P interface, which only applies to some // voice server types. Otherwise, a group call should be used for P2P - LLVoiceP2POutgoingCallInterface* getOutgoingCallInterface(const LLSD& voiceChannelInfo); + LLVoiceP2POutgoingCallInterface* getOutgoingCallInterface(const LLSD& voiceChannelInfo = LLSD()); LLVoiceP2PIncomingCallInterfacePtr getIncomingCallInterface(const LLSD &voiceCallInfo); diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 88fc40e565..ccdd86dd87 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -1200,7 +1200,7 @@ bool LLVivoxVoiceClient::provisionVoiceAccount() LL_WARNS("Voice") << "Could not access voice provision cap after " << retryCount << " attempts." << LL_ENDL; return false; } - LL_WARNS("Voice") << "Voice Provision Result." << result << LL_ENDL; + LL_DEBUGS("Voice") << "Voice Provision Result." << result << LL_ENDL; std::string voiceSipUriHostname; std::string voiceAccountServerUri; std::string voiceUserName = result["username"].asString(); @@ -1749,7 +1749,7 @@ bool LLVivoxVoiceClient::addAndJoinSession(const sessionStatePtr_t &nextSession) } else if ((message == "failed") || (message == "removed") || (message == "timeout")) { // we will get a removed message if a voice call is declined. - + LL_INFOS("Voice") << "Result:" << result << LL_ENDL; if (message == "failed") { int reason = result["reason"].asInteger(); @@ -6344,8 +6344,7 @@ void LLVivoxVoiceClient::predAvatarNameResolution(const LLVivoxVoiceClient::sess session->mCallerID, session->mName, IM_SESSION_P2P_INVITE, - LLIMMgr::INVITATION_TYPE_VOICE, - session->getVoiceChannelInfo()); + LLIMMgr::INVITATION_TYPE_VOICE); } } } diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 2f85189f45..94cf617bad 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -1119,10 +1119,6 @@ void LLWebRTCVoiceClient::removeParticipantByID(const std::string &channelID, co if (participant) { session->removeParticipant(participant); - if (session->mHangupOnLastLeave && (id != gAgentID) && (session->mParticipantsByUUID.size() <= 1)) - { - notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL); - } } } } @@ -1214,6 +1210,10 @@ void LLWebRTCVoiceClient::sessionState::removeParticipant(const LLWebRTCVoiceCli LLWebRTCVoiceClient::getInstance()->notifyParticipantObservers(); } } + if (mHangupOnLastLeave && (participant->mAvatarID != gAgentID) && (mParticipantsByUUID.size() <= 1)) + { + LLWebRTCVoiceClient::getInstance()->notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL); + } } } diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml index a7864381a9..e576310160 100644 --- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml +++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml @@ -12,7 +12,7 @@ width="550"> - 5 + 30 -- cgit v1.2.3 From 62cd262ccafa000de1a155ccc171eabf9b90d5b3 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Fri, 26 Apr 2024 22:00:32 -0700 Subject: attempt to access participant after it's deleted --- indra/newview/llvoicewebrtc.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 94cf617bad..0edbe5abc2 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -1194,13 +1194,14 @@ void LLWebRTCVoiceClient::sessionState::removeParticipant(const LLWebRTCVoiceCli if (participant) { + LLUUID participantID = participant->mAvatarID; participantUUIDMap::iterator iter = mParticipantsByUUID.find(participant->mAvatarID); - LL_DEBUGS("Voice") << "participant \"" << participant->mURI << "\" (" << participant->mAvatarID << ") removed." << LL_ENDL; + LL_DEBUGS("Voice") << "participant \"" << participant->mURI << "\" (" << participantID << ") removed." << LL_ENDL; if (iter == mParticipantsByUUID.end()) { - LL_WARNS("Voice") << "Internal error: participant ID " << participant->mAvatarID << " not in UUID map" << LL_ENDL; + LL_WARNS("Voice") << "Internal error: participant ID " << participantID << " not in UUID map" << LL_ENDL; } else { @@ -1210,7 +1211,7 @@ void LLWebRTCVoiceClient::sessionState::removeParticipant(const LLWebRTCVoiceCli LLWebRTCVoiceClient::getInstance()->notifyParticipantObservers(); } } - if (mHangupOnLastLeave && (participant->mAvatarID != gAgentID) && (mParticipantsByUUID.size() <= 1)) + if (mHangupOnLastLeave && (participantID != gAgentID) && (mParticipantsByUUID.size() <= 1)) { LLWebRTCVoiceClient::getInstance()->notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL); } -- cgit v1.2.3 From d4fce4990ad0527430d2b3e70be360c26d6cb46b Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Sun, 28 Apr 2024 17:43:15 -0700 Subject: Reconnects to the voice server weren't happening. --- indra/llwebrtc/llwebrtc.cpp | 10 +++++++--- indra/llwebrtc/llwebrtc_impl.h | 2 +- indra/newview/llvoicewebrtc.cpp | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index e08ace12c5..b20d3cd4e0 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -652,6 +652,13 @@ LLWebRTCPeerConnectionImpl::LLWebRTCPeerConnectionImpl() : { } +LLWebRTCPeerConnectionImpl::~LLWebRTCPeerConnectionImpl() +{ + terminate(); + mSignalingObserverList.clear(); + mDataObserverList.clear(); +} + // // LLWebRTCPeerConnection interface // @@ -670,9 +677,6 @@ void LLWebRTCPeerConnectionImpl::terminate() rtc::scoped_refptr localStream; mLocalStream.swap(localStream); - mSignalingObserverList.clear(); - mDataObserverList.clear(); - mWebRTCImpl->PostSignalingTask( [=]() { diff --git a/indra/llwebrtc/llwebrtc_impl.h b/indra/llwebrtc/llwebrtc_impl.h index e1031099c7..984aaef734 100644 --- a/indra/llwebrtc/llwebrtc_impl.h +++ b/indra/llwebrtc/llwebrtc_impl.h @@ -276,7 +276,7 @@ class LLWebRTCPeerConnectionImpl : public LLWebRTCPeerConnectionInterface, { public: LLWebRTCPeerConnectionImpl(); - ~LLWebRTCPeerConnectionImpl() {} + ~LLWebRTCPeerConnectionImpl(); void init(LLWebRTCImpl * webrtc_impl); void terminate(); diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 0edbe5abc2..87106ba6d5 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -87,7 +87,7 @@ namespace { const F32 VOLUME_SCALE_WEBRTC = 0.01f; const F32 LEVEL_SCALE_WEBRTC = 0.008f; - const F32 SPEAKING_AUDIO_LEVEL = 0.40; + const F32 SPEAKING_AUDIO_LEVEL = 0.35; static const std::string REPORTED_VOICE_SERVER_TYPE = "Secondlife WebRTC Gateway"; -- cgit v1.2.3 From cf13866da951f8c7c7eedfd0ff0571c6951f42a4 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Sun, 28 Apr 2024 18:43:48 -0700 Subject: Don't default the tracks to unmuted --- indra/llwebrtc/llwebrtc.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index b20d3cd4e0..d07e6deea4 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -766,7 +766,7 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection(const LLWebRTCPeerConnecti rtc::scoped_refptr audio_track( mPeerConnectionFactory->CreateAudioTrack("SLAudio", mPeerConnectionFactory->CreateAudioSource(audioOptions).get())); - audio_track->set_enabled(true); + audio_track->set_enabled(false); mLocalStream->AddTrack(audio_track); mPeerConnection->AddTrack(audio_track, {"SLStream"}); @@ -999,8 +999,6 @@ void LLWebRTCPeerConnectionImpl::OnConnectionChange(webrtc::PeerConnectionInterf { case webrtc::PeerConnectionInterface::PeerConnectionState::kConnected: { - mWebRTCImpl->setRecording(true); - mWebRTCImpl->PostWorkerTask([this]() { for (auto &observer : mSignalingObserverList) { -- cgit v1.2.3 From 57182b2ac01007d3d5d11c98e811e05d2c50405c Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Sun, 28 Apr 2024 19:39:23 -0700 Subject: tabbing --- indra/newview/llimview.cpp | 156 +++++++++++++++++++-------------------- indra/newview/llspeakers.h | 2 +- indra/newview/llvoicechannel.cpp | 3 +- indra/newview/llvoiceclient.h | 2 +- 4 files changed, 81 insertions(+), 82 deletions(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 58ac681ad8..a1fb49c277 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -724,13 +724,13 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, mOtherParticipantID(other_participant_id), mInitialTargetIDs(ids), mVoiceChannel(NULL), - mP2PAsAdhocCall(false), + mP2PAsAdhocCall(false), mSpeakers(NULL), mSessionInitialized(false), mCallBackEnabled(true), mTextIMPossible(true), mStartCallOnInitialize(false), - mStartedAsIMCall(!voice_channel_info.isUndefined()), + mStartedAsIMCall(!voice_channel_info.isUndefined()), mIsDNDsend(false), mAvatarNameCacheConnection() { @@ -738,16 +738,16 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, mSessionType = P2P_SESSION; if (IM_NOTHING_SPECIAL == mType || IM_SESSION_P2P_INVITE == mType) - { - mP2PAsAdhocCall = (LLVoiceClient::getInstance()->getOutgoingCallInterface(voice_channel_info) == NULL); + { + mP2PAsAdhocCall = (LLVoiceClient::getInstance()->getOutgoingCallInterface(voice_channel_info) == NULL); + } + else + { + // determine whether it is group or conference session + mSessionType = gAgent.isInGroup(mSessionID) ? GROUP_SESSION : ADHOC_SESSION; } - else - { - // determine whether it is group or conference session - mSessionType = gAgent.isInGroup(mSessionID) ? GROUP_SESSION : ADHOC_SESSION; - } - initVoiceChannel(voice_channel_info); + initVoiceChannel(voice_channel_info); // All participants will be added to the list of people we've recently interacted with. @@ -789,64 +789,64 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, void LLIMModel::LLIMSession::initVoiceChannel(const LLSD& voiceChannelInfo) { - mVoiceChannelStateChangeConnection.disconnect(); + mVoiceChannelStateChangeConnection.disconnect(); if (mVoiceChannel) - { - mVoiceChannel->deactivate(); + { + mVoiceChannel->deactivate(); - delete mVoiceChannel; - mVoiceChannel = NULL; - } - mP2PAsAdhocCall = false; - if (IM_NOTHING_SPECIAL == mType || IM_SESSION_P2P_INVITE == mType) - { - LLVoiceP2POutgoingCallInterface *outgoingInterface = LLVoiceClient::getInstance()->getOutgoingCallInterface(voiceChannelInfo); + delete mVoiceChannel; + mVoiceChannel = NULL; + } + mP2PAsAdhocCall = false; + if (IM_NOTHING_SPECIAL == mType || IM_SESSION_P2P_INVITE == mType) + { + LLVoiceP2POutgoingCallInterface *outgoingInterface = LLVoiceClient::getInstance()->getOutgoingCallInterface(voiceChannelInfo); - if (outgoingInterface) - { - // only use LLVoiceChannelP2P if the provider can handle the special P2P interface, - // which uses the voice server to relay calls and invites. Otherwise, - // we use the group voice provider. - mVoiceChannel = new LLVoiceChannelP2P(mSessionID, mName, mOtherParticipantID, outgoingInterface); - } - else - { - mP2PAsAdhocCall = true; - mVoiceChannel = new LLVoiceChannelGroup(mSessionID, mName, true); - } - } - else - { - // determine whether it is group or conference session - if (mSessionType == GROUP_SESSION) - { - mSessionType = GROUP_SESSION; - mVoiceChannel = new LLVoiceChannelGroup(mSessionID, mName, false); - } - else if (mSessionType == ADHOC_SESSION) - { - mSessionType = ADHOC_SESSION; - mVoiceChannel = new LLVoiceChannelGroup(mSessionID, mName, false); - } + if (outgoingInterface) + { + // only use LLVoiceChannelP2P if the provider can handle the special P2P interface, + // which uses the voice server to relay calls and invites. Otherwise, + // we use the group voice provider. + mVoiceChannel = new LLVoiceChannelP2P(mSessionID, mName, mOtherParticipantID, outgoingInterface); + } else { - LL_WARNS("Voice") << "Invalid Session Type when initializing voice channel: " << mSessionType << LL_ENDL; - return; + mP2PAsAdhocCall = true; + mVoiceChannel = new LLVoiceChannelGroup(mSessionID, mName, true); } - } + } + else + { + // determine whether it is group or conference session + if (mSessionType == GROUP_SESSION) + { + mSessionType = GROUP_SESSION; + mVoiceChannel = new LLVoiceChannelGroup(mSessionID, mName, false); + } + else if (mSessionType == ADHOC_SESSION) + { + mSessionType = ADHOC_SESSION; + mVoiceChannel = new LLVoiceChannelGroup(mSessionID, mName, false); + } + else + { + LL_WARNS("Voice") << "Invalid Session Type when initializing voice channel: " << mSessionType << LL_ENDL; + return; + } + } - mVoiceChannelStateChangeConnection = - mVoiceChannel->setStateChangedCallback(boost::bind(&LLIMSession::onVoiceChannelStateChanged, this, _1, _2, _3)); + mVoiceChannelStateChangeConnection = + mVoiceChannel->setStateChangedCallback(boost::bind(&LLIMSession::onVoiceChannelStateChanged, this, _1, _2, _3)); if (!mSpeakers) { - mSpeakers = new LLIMSpeakerMgr(mVoiceChannel); + mSpeakers = new LLIMSpeakerMgr(mVoiceChannel); + } + else + { + mSpeakers->setVoiceChannel(mVoiceChannel); } - else - { - mSpeakers->setVoiceChannel(mVoiceChannel); - } } void LLIMModel::LLIMSession::onAdHocNameCache(const LLAvatarName& av_name) @@ -984,10 +984,10 @@ void LLIMModel::LLIMSession::sessionInitReplyReceived(const LLUUID& new_session_ if (new_session_id != mSessionID) { mSessionID = new_session_id; - if (mVoiceChannel) - { - mVoiceChannel->updateSessionID(new_session_id); - } + if (mVoiceChannel) + { + mVoiceChannel->updateSessionID(new_session_id); + } } } @@ -1831,14 +1831,14 @@ LLVoiceChannel* LLIMModel::getVoiceChannel( const LLUUID& session_id, const LLSD LL_WARNS() << "session " << session_id << "does not exist " << LL_ENDL; return NULL; } - if (IM_NOTHING_SPECIAL == session->mType || IM_SESSION_P2P_INVITE == session->mType) - { - LLVoiceP2POutgoingCallInterface *outgoingInterface = LLVoiceClient::getInstance()->getOutgoingCallInterface(voice_channel_info); - if ((outgoingInterface != NULL) != (dynamic_cast(session->mVoiceChannel) != NULL)) - { - session->initVoiceChannel(voice_channel_info); - } - } + if (IM_NOTHING_SPECIAL == session->mType || IM_SESSION_P2P_INVITE == session->mType) + { + LLVoiceP2POutgoingCallInterface *outgoingInterface = LLVoiceClient::getInstance()->getOutgoingCallInterface(voice_channel_info); + if ((outgoingInterface != NULL) != (dynamic_cast(session->mVoiceChannel) != NULL)) + { + session->initVoiceChannel(voice_channel_info); + } + } return session->mVoiceChannel; } @@ -2180,7 +2180,7 @@ bool LLIMModel::sendStartSession( //we also need to wait for reply from the server in case of ad-hoc chat (we'll get new session id) return true; } - else if (p2p_as_adhoc_call && ((dialog == IM_SESSION_P2P_INVITE) || (dialog == IM_NOTHING_SPECIAL))) + else if (p2p_as_adhoc_call && ((dialog == IM_SESSION_P2P_INVITE) || (dialog == IM_NOTHING_SPECIAL))) { LLViewerRegion *region = gAgent.getRegion(); if (region) @@ -2801,7 +2801,7 @@ void LLIncomingCallDialog::onLifetimeExpired() LLUUID session_id = mPayload["session_id"].asUUID(); gIMMgr->clearPendingAgentListUpdates(session_id); gIMMgr->clearPendingInvitation(session_id); - LLIncomingCallDialog::onReject(this); + LLIncomingCallDialog::onReject(this); } } @@ -2990,7 +2990,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload if (voice) { - gIMMgr->startCall(session_id, LLVoiceChannel::INCOMING_CALL, payload["voice_channel_info"]); + gIMMgr->startCall(session_id, LLVoiceChannel::INCOMING_CALL, payload["voice_channel_info"]); } else { @@ -3597,7 +3597,7 @@ void LLIMMgr::inviteToSession( { // we're throwing up a dialogue, so we're using the voice channel passed to us, // save it in the payload. - payload["voice_channel_info"] = voice_channel_info; + payload["voice_channel_info"] = voice_channel_info; if (caller_name.empty()) { LLAvatarNameCache::get(caller_id, @@ -4149,12 +4149,12 @@ public: } if (input["body"]["info"].has("voice_channel_info")) { - LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); - if (session) - { - session->initVoiceChannel(input["body"]["info"]["voice_channel_info"]); - session->mVoiceChannel->activate(); - } + LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); + if (session) + { + session->initVoiceChannel(input["body"]["info"]["voice_channel_info"]); + session->mVoiceChannel->activate(); + } } } }; diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index ba1dfec226..aa594d1e13 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -241,7 +241,7 @@ public: typedef std::vector > speaker_list_t; void getSpeakerList(speaker_list_t* speaker_list, BOOL include_text); LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; } - void setVoiceChannel(LLVoiceChannel *voiceChannel) { mVoiceChannel = voiceChannel; } + void setVoiceChannel(LLVoiceChannel *voiceChannel) { mVoiceChannel = voiceChannel; } const LLUUID getSessionID(); bool isSpeakerToBeRemoved(const LLUUID& speaker_id); diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 7138a8b391..f9d4a7e222 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -473,8 +473,7 @@ void LLVoiceChannelGroup::requestChannelInfo() void LLVoiceChannelGroup::setChannelInfo(const LLSD& channelInfo) { - mChannelInfo = channelInfo; - LL_INFOS("Voice") << "setChannelInfo: " << channelInfo << LL_ENDL; + mChannelInfo = channelInfo; if (mState == STATE_NO_CHANNEL_INFO) { diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index c1e0ab0c35..6b6cb452ee 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -421,7 +421,7 @@ public: // initiate a call with a peer using the P2P interface, which only applies to some // voice server types. Otherwise, a group call should be used for P2P - LLVoiceP2POutgoingCallInterface* getOutgoingCallInterface(const LLSD& voiceChannelInfo = LLSD()); + LLVoiceP2POutgoingCallInterface* getOutgoingCallInterface(const LLSD& voiceChannelInfo = LLSD()); LLVoiceP2PIncomingCallInterfacePtr getIncomingCallInterface(const LLSD &voiceCallInfo); -- cgit v1.2.3 From 2c503997204043fcd24d70854799509c0675d76d Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Tue, 30 Apr 2024 11:45:21 -0700 Subject: Remove voice participants for a connection when shutting it down. When teleporting or moving around, connections to regions are shut down. We need to track which participants are associated with the given connections and remove those participants when the connection is shut down. --- indra/newview/llvoicewebrtc.cpp | 68 +++++++++++++++++++++++++---------------- indra/newview/llvoicewebrtc.h | 11 ++++--- 2 files changed, 47 insertions(+), 32 deletions(-) diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 87106ba6d5..2bd6eee84d 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -810,9 +810,12 @@ void LLWebRTCVoiceClient::OnConnectionEstablished(const std::string &channelID, } mSession = mNextSession; mNextSession.reset(); + } + if (mSession) + { // Add ourselves as a participant. - mSession->addParticipant(gAgentID); + mSession->addParticipant(gAgentID, gAgent.getRegion()->getRegionID()); } // The current session was established. @@ -833,14 +836,19 @@ void LLWebRTCVoiceClient::OnConnectionEstablished(const std::string &channelID, void LLWebRTCVoiceClient::OnConnectionShutDown(const std::string &channelID, const LLUUID ®ionID) { - if (gAgent.getRegion()->getRegionID() == regionID) + if (mSession && (mSession->mChannelID == channelID)) { - if (mSession && mSession->mChannelID == channelID) + if (gAgent.getRegion()->getRegionID() == regionID) { - LL_DEBUGS("Voice") << "Main WebRTC Connection Shut Down." << LL_ENDL; + if (mSession && mSession->mChannelID == channelID) + { + LL_DEBUGS("Voice") << "Main WebRTC Connection Shut Down." << LL_ENDL; + } } + mSession->removeAllParticipants(regionID); } } + void LLWebRTCVoiceClient::OnConnectionFailure(const std::string &channelID, const LLUUID ®ionID, LLVoiceClientStatusObserver::EStatusType status_type) @@ -1092,13 +1100,13 @@ LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::findParticipantB return result; } -LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::addParticipantByID(const std::string &channelID, const LLUUID &id) +LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::addParticipantByID(const std::string &channelID, const LLUUID &id, const LLUUID& region) { participantStatePtr_t result; LLWebRTCVoiceClient::sessionState::ptr_t session = sessionState::matchSessionByChannelID(channelID); if (session) { - result = session->addParticipant(id); + result = session->addParticipant(id, region); if (session->mNotifyOnFirstJoin && (id != gAgentID)) { notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED); @@ -1107,7 +1115,7 @@ LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::addParticipantBy return result; } -void LLWebRTCVoiceClient::removeParticipantByID(const std::string &channelID, const LLUUID &id) +void LLWebRTCVoiceClient::removeParticipantByID(const std::string &channelID, const LLUUID &id, const LLUUID& region) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE @@ -1116,7 +1124,7 @@ void LLWebRTCVoiceClient::removeParticipantByID(const std::string &channelID, co if (session) { participantStatePtr_t participant = session->findParticipantByID(id); - if (participant) + if (participant && (participant->mRegion == region)) { session->removeParticipant(participant); } @@ -1125,17 +1133,18 @@ void LLWebRTCVoiceClient::removeParticipantByID(const std::string &channelID, co // participantState level participant management -LLWebRTCVoiceClient::participantState::participantState(const LLUUID& agent_id) : +LLWebRTCVoiceClient::participantState::participantState(const LLUUID& agent_id, const LLUUID& region) : mURI(agent_id.asString()), mAvatarID(agent_id), mIsSpeaking(false), mIsModeratorMuted(false), mLevel(0.f), - mVolume(LLVoiceClient::VOLUME_DEFAULT) + mVolume(LLVoiceClient::VOLUME_DEFAULT), + mRegion(region) { } -LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::sessionState::addParticipant(const LLUUID& agent_id) +LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::sessionState::addParticipant(const LLUUID& agent_id, const LLUUID& region) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE @@ -1147,26 +1156,27 @@ LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::sessionState::ad if (iter != mParticipantsByUUID.end()) { result = iter->second; + result->mRegion = region; } - if(!result) + if (!result) { // participant isn't already in one list or the other. - result.reset(new participantState(agent_id)); + result.reset(new participantState(agent_id, region)); mParticipantsByUUID.insert(participantUUIDMap::value_type(agent_id, result)); - result->mAvatarID = agent_id; - - LLWebRTCVoiceClient::getInstance()->lookupName(agent_id); + result->mAvatarID = agent_id; + } - LLSpeakerVolumeStorage::getInstance()->getSpeakerVolume(result->mAvatarID, result->mVolume); - if (!LLWebRTCVoiceClient::sShuttingDown) - { - LLWebRTCVoiceClient::getInstance()->notifyParticipantObservers(); - } + LLWebRTCVoiceClient::getInstance()->lookupName(agent_id); - LL_DEBUGS("Voice") << "Participant \"" << result->mURI << "\" added." << LL_ENDL; + LLSpeakerVolumeStorage::getInstance()->getSpeakerVolume(result->mAvatarID, result->mVolume); + if (!LLWebRTCVoiceClient::sShuttingDown) + { + LLWebRTCVoiceClient::getInstance()->notifyParticipantObservers(); } + LL_DEBUGS("Voice") << "Participant \"" << result->mURI << "\" added." << LL_ENDL; + return result; } @@ -1218,13 +1228,17 @@ void LLWebRTCVoiceClient::sessionState::removeParticipant(const LLWebRTCVoiceCli } } -void LLWebRTCVoiceClient::sessionState::removeAllParticipants() +void LLWebRTCVoiceClient::sessionState::removeAllParticipants(const LLUUID ®ion) { LL_DEBUGS("Voice") << "called" << LL_ENDL; - while (!mParticipantsByUUID.empty()) + + for (auto &&participant : mParticipantsByUUID) { - removeParticipant(mParticipantsByUUID.begin()->second); + if (region.isNull() || (participant.second->mRegion == region)) + { + removeParticipant(participant.second); + } } } @@ -2836,7 +2850,7 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b new_participant |= joined; if (!participant && joined && (primary || !isSpatial())) { - participant = LLWebRTCVoiceClient::getInstance()->addParticipantByID(mChannelID, agent_id); + participant = LLWebRTCVoiceClient::getInstance()->addParticipantByID(mChannelID, agent_id, mRegionID); } if (participant) @@ -2846,7 +2860,7 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b // an existing participant is leaving. if (agent_id != gAgentID) { - LLWebRTCVoiceClient::getInstance()->removeParticipantByID(mChannelID, agent_id); + LLWebRTCVoiceClient::getInstance()->removeParticipantByID(mChannelID, agent_id, mRegionID); } } else diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h index 67e4a4ea6f..af1efa5fe5 100644 --- a/indra/newview/llvoicewebrtc.h +++ b/indra/newview/llvoicewebrtc.h @@ -228,7 +228,7 @@ public: struct participantState { public: - participantState(const LLUUID& agent_id); + participantState(const LLUUID& agent_id, const LLUUID& region); bool isAvatar(); @@ -240,12 +240,13 @@ public: F32 mVolume; // the gain applied to the participant bool mIsSpeaking; bool mIsModeratorMuted; + LLUUID mRegion; }; typedef boost::shared_ptr participantStatePtr_t; participantStatePtr_t findParticipantByID(const std::string &channelID, const LLUUID &id); - participantStatePtr_t addParticipantByID(const std::string& channelID, const LLUUID &id); - void removeParticipantByID(const std::string& channelID, const LLUUID &id); + participantStatePtr_t addParticipantByID(const std::string& channelID, const LLUUID &id, const LLUUID& region); + void removeParticipantByID(const std::string& channelID, const LLUUID &id, const LLUUID& region); protected: @@ -262,9 +263,9 @@ public: static void addSession(const std::string &channelID, ptr_t& session); virtual ~sessionState(); - participantStatePtr_t addParticipant(const LLUUID& agent_id); + participantStatePtr_t addParticipant(const LLUUID& agent_id, const LLUUID& region); void removeParticipant(const participantStatePtr_t &participant); - void removeAllParticipants(); + void removeAllParticipants(const LLUUID& region = LLUUID()); participantStatePtr_t findParticipantByID(const LLUUID& id); -- cgit v1.2.3 From f9cb9a2b057b2ebc2e1f5cbf479e56595c0fdfb8 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Tue, 30 Apr 2024 12:58:07 -0700 Subject: Can't delete from a map while iterating over it. --- indra/newview/llvoicewebrtc.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 2bd6eee84d..0823358e03 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -1230,16 +1230,19 @@ void LLWebRTCVoiceClient::sessionState::removeParticipant(const LLWebRTCVoiceCli void LLWebRTCVoiceClient::sessionState::removeAllParticipants(const LLUUID ®ion) { - LL_DEBUGS("Voice") << "called" << LL_ENDL; - + std::vector participantsToRemove; - for (auto &&participant : mParticipantsByUUID) + for (auto& participantEntry : mParticipantsByUUID) { - if (region.isNull() || (participant.second->mRegion == region)) + if (region.isNull() || (participantEntry.second->mRegion == region)) { - removeParticipant(participant.second); + participantsToRemove.push_back(participantEntry.second); } } + for (auto& participant : participantsToRemove) + { + removeParticipant(participant); + } } // Initiated the various types of sessions. -- cgit v1.2.3 From 1bca2b20361c9723d4d8bb6d03684ed2dc729703 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Tue, 30 Apr 2024 15:35:48 -0700 Subject: don't register callbacks from the data channel twice. --- indra/llwebrtc/llwebrtc.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index d07e6deea4..97c04ae446 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -957,6 +957,10 @@ void LLWebRTCPeerConnectionImpl::OnRemoveTrack(rtc::scoped_refptr channel) { + if (mDataChannel) + { + mDataChannel->UnregisterObserver(); + } mDataChannel = channel; channel->RegisterObserver(this); } -- cgit v1.2.3 From 07c3095a785864b39b03d979d43b7d0d7a932a81 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Thu, 2 May 2024 11:07:36 -0700 Subject: Unregister requested data channel when using the negotiated one. When creating a new connection, the viewer builds a data channel interface. It then gets a new one, which is a proxy. The viewer uses the new one, and therefore must unregister the callbacks from the old one. Also, update the position data before sending it after the join is sent. --- indra/llwebrtc/llwebrtc.cpp | 4 ++++ indra/newview/llvoicewebrtc.cpp | 6 +++++- indra/newview/llvoicewebrtc.h | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index d07e6deea4..97c04ae446 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -957,6 +957,10 @@ void LLWebRTCPeerConnectionImpl::OnRemoveTrack(rtc::scoped_refptr channel) { + if (mDataChannel) + { + mDataChannel->UnregisterObserver(); + } mDataChannel = channel; channel->RegisterObserver(this); } diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 0823358e03..7c438dfa9a 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -2688,7 +2688,11 @@ bool LLVoiceWebRTCConnection::connectionStateMachine() { sendJoin(); // tell the Secondlife WebRTC server that we're here via the data channel. setVoiceConnectionState(VOICE_STATE_SESSION_UP); - LLWebRTCVoiceClient::getInstance()->sendPositionUpdate(true); + if (isSpatial()) + { + LLWebRTCVoiceClient::getInstance()->updatePosition(); + LLWebRTCVoiceClient::getInstance()->sendPositionUpdate(true); + } } break; } diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h index af1efa5fe5..c417dfe329 100644 --- a/indra/newview/llvoicewebrtc.h +++ b/indra/newview/llvoicewebrtc.h @@ -201,7 +201,8 @@ public: void OnConnectionFailure(const std::string &channelID, const LLUUID ®ionID, LLVoiceClientStatusObserver::EStatusType status_type = LLVoiceClientStatusObserver::ERROR_UNKNOWN); - void sendPositionUpdate(bool force); + void updatePosition(void); // update the internal position state + void sendPositionUpdate(bool force); // send the position to the voice server. void updateOwnVolume(); ////////////////////////////// @@ -398,7 +399,6 @@ public: ///////////////////////////// // Sending updates of current state - void updatePosition(void); void setListenerPosition(const LLVector3d &position, const LLVector3 &velocity, const LLQuaternion &rot); void setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLQuaternion &rot); -- cgit v1.2.3 From 05b2dd913fcb1c5485ce19885e4e60f26752e6b0 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Thu, 2 May 2024 13:15:44 -0700 Subject: Update the participant's region when crossing region boundaries. --- indra/newview/llvoicewebrtc.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 7c438dfa9a..ddbe2eb552 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -553,6 +553,7 @@ void LLWebRTCVoiceClient::updateNeighboringRegions() // Estate voice requires connection to neighboring regions. mNeighboringRegions.clear(); + // add current region. mNeighboringRegions.insert(gAgent.getRegion()->getRegionID()); // base off of speaker position as it'll move more slowly than camera position. @@ -924,6 +925,13 @@ void LLWebRTCVoiceClient::updatePosition(void) enforceTether(); updateNeighboringRegions(); + + // update own region id to be the region id avatar is currently in. + LLWebRTCVoiceClient::participantStatePtr_t participant = findParticipantByID("Estate", gAgentID); + if(participant) + { + participant->mRegion = gAgent.getRegion()->getRegionID(); + } } } -- cgit v1.2.3