summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorRoxie Linden <roxie@lindenlab.com>2024-01-25 20:53:19 -0800
committerRoxie Linden <roxie@lindenlab.com>2024-02-22 23:11:36 -0800
commitbb2994d9ba89f199c08d88d89257f7944117a234 (patch)
tree8851a608d63e69a95281ae13f00b59ba32500a9c /indra
parente8edfbf3d488e1981a876a40714f36dafad5414a (diff)
Checkpoint Ad-Hoc voice.
Unlike vivox, P2P uses the ad-hoc voice mechanism, which is also used by group voice.
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/llimview.cpp8
-rw-r--r--indra/newview/llvoicechannel.cpp1
-rw-r--r--indra/newview/llvoiceclient.cpp7
-rw-r--r--indra/newview/llvoiceclient.h2
-rw-r--r--indra/newview/llvoicewebrtc.cpp681
-rw-r--r--indra/newview/llvoicewebrtc.h229
6 files changed, 507 insertions, 421 deletions
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 61a01d7418..3e03dbef8f 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -665,8 +665,11 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
// set P2P type by default
mSessionType = P2P_SESSION;
- if (IM_NOTHING_SPECIAL == mType || IM_SESSION_P2P_INVITE == mType)
+ if ((IM_NOTHING_SPECIAL == mType || IM_SESSION_P2P_INVITE == mType) && LLVoiceClient::getInstance()->hasP2PInterface())
{
+ // 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);
}
else
@@ -2034,7 +2037,8 @@ bool LLIMModel::sendStartSession(
return true;
}
- else if ( dialog == IM_SESSION_CONFERENCE_START )
+ else if (( dialog == IM_SESSION_CONFERENCE_START ) ||
+ (((dialog == IM_SESSION_P2P_INVITE) || (dialog == IM_NOTHING_SPECIAL)) && !LLVoiceClient::getInstance()->hasP2PInterface()))
{
LLSD agents;
for (int i = 0; i < (S32) ids.size(); i++)
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index b0eb8d962c..afac9ed6f8 100644
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -654,6 +654,7 @@ void LLVoiceChannelGroup::voiceCallCapCoro(std::string url)
LL_DEBUGS("Voice") << "LLVoiceCallCapResponder::result got "
<< iter->first << LL_ENDL;
}
+ LL_INFOS("Voice") << "LLVoiceCallCapResponder::result got " << result << LL_ENDL;
channelp->setChannelInfo(
result["voice_credentials"]["channel_uri"].asString(),
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 294ae0c9ad..54840a1235 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -486,6 +486,13 @@ std::string LLVoiceClient::getCurrentChannel()
//---------------------------------------
// invitations
+bool LLVoiceClient::hasP2PInterface()
+{
+ if (mVoiceModule)
+ return mVoiceModule->hasP2PInterface();
+ return false;
+}
+
void LLVoiceClient::callUser(const LLUUID &uuid)
{
if (mVoiceModule) mVoiceModule->callUser(uuid);
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 1e8ff21b4b..1a20de6109 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -186,6 +186,7 @@ public:
/// @name invitations
//@{
// start a voice channel with the specified user
+ virtual bool hasP2PInterface()=0;
virtual void callUser(const LLUUID &uuid)=0;
virtual bool isValidChannel(std::string& channelHandle)=0;
virtual bool answerInvite(std::string &channelHandle)=0;
@@ -382,6 +383,7 @@ public:
// NOTE that it will return an empty string if it's in the process of joining a channel.
std::string getCurrentChannel();
// start a voice channel with the specified user
+ bool hasP2PInterface(); // true - can use the following. false - use conference/ad-hoc instead
void callUser(const LLUUID &uuid);
bool isValidChannel(std::string& channelHandle);
bool answerInvite(std::string &channelHandle);
diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp
index c9180b7e99..fcdd818757 100644
--- a/indra/newview/llvoicewebrtc.cpp
+++ b/indra/newview/llvoicewebrtc.cpp
@@ -419,15 +419,27 @@ void LLWebRTCVoiceClient::OnConnectionEstablished(const std::string& channelID,
}
mSession = mNextSession;
mNextSession.reset();
- LLWebRTCVoiceClient::getInstance()->notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN);
}
- else if (mSession && mSession->mChannelID == channelID)
+
+ if (mSession && mSession->mChannelID == channelID)
{
+ LLWebRTCVoiceClient::getInstance()->notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED);
LLWebRTCVoiceClient::getInstance()->notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN);
}
}
}
+void LLWebRTCVoiceClient::OnConnectionShutDown(const std::string &channelID, const LLUUID &regionID)
+{
+ if (gAgent.getRegion()->getRegionID() == regionID)
+ {
+ if (mSession && mSession->mChannelID == channelID)
+ {
+ LLWebRTCVoiceClient::getInstance()->notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL);
+ }
+ }
+}
+
void LLWebRTCVoiceClient::idle(void* user_data)
{
}
@@ -492,8 +504,12 @@ LLWebRTCVoiceClient::parcelSessionState::parcelSessionState(const std::string &c
mWebRTCConnections.emplace_back(new LLVoiceWebRTCSpatialConnection(region_id, parcel_local_id, channelID));
}
-LLWebRTCVoiceClient::adhocSessionState::adhocSessionState(const std::string &channelID)
+LLWebRTCVoiceClient::adhocSessionState::adhocSessionState(const std::string &channelID, const std::string& credentials) :
+ mCredentials(credentials)
{
+ LLUUID region_id = gAgent.getRegion()->getRegionID();
+ mChannelID = channelID;
+ mWebRTCConnections.emplace_back(new LLVoiceWebRTCAdHocConnection(region_id, channelID, credentials));
}
bool LLWebRTCVoiceClient::estateSessionState::processConnectionStates()
@@ -1112,7 +1128,6 @@ bool LLWebRTCVoiceClient::isParticipant(const LLUUID &speaker_id)
return false;
}
-
LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::sessionState::findParticipant(const std::string &uri)
{
participantStatePtr_t result;
@@ -1192,10 +1207,10 @@ bool LLWebRTCVoiceClient::startParcelSession(const std::string &channelID, S32 p
return true;
}
-bool LLWebRTCVoiceClient::startAdHocSession(const std::string &channelID)
+bool LLWebRTCVoiceClient::startAdHocSession(const std::string &channelID, const std::string &credentials)
{
leaveChannel(false);
- mNextSession = addSession(channelID, sessionState::ptr_t(new adhocSessionState(channelID)));
+ mNextSession = addSession(channelID, sessionState::ptr_t(new adhocSessionState(channelID, credentials)));
return true;
}
@@ -1211,9 +1226,8 @@ void LLWebRTCVoiceClient::joinSession(const sessionStatePtr_t &session)
}
}
-void LLWebRTCVoiceClient::callUser(const LLUUID &uuid)
-{
- startAdHocSession(uuid.asString());
+void LLWebRTCVoiceClient::callUser(const LLUUID &uuid)
+{
}
void LLWebRTCVoiceClient::endUserIMSession(const LLUUID &uuid)
@@ -1226,16 +1240,7 @@ bool LLWebRTCVoiceClient::isValidChannel(std::string &channelID)
}
bool LLWebRTCVoiceClient::answerInvite(std::string &channelID)
-{
- // this is only ever used to answer incoming p2p call invites.
-
- sessionStatePtr_t session(findP2PSession(LLUUID(channelID)));
- if(session)
- {
- startAdHocSession(channelID);
- return true;
- }
-
+{
return false;
}
@@ -1419,7 +1424,11 @@ bool LLWebRTCVoiceClient::inSpatialChannel()
{
bool result = true;
- if(mSession)
+ if (mNextSession)
+ {
+ result = mNextSession->isSpatial();
+ }
+ else if(mSession)
{
result = mSession->isSpatial();
}
@@ -2299,77 +2308,25 @@ std::string LLWebRTCVoiceClient::sipURIFromID(const LLUUID& id) { return id.asSt
/////////////////////////////
// LLVoiceWebRTCConnection
-LLVoiceWebRTCConnection::LLVoiceWebRTCConnection() :
- mWebRTCAudioInterface(nullptr),
- mWebRTCPeerConnection(nullptr),
- mMuted(true),
- mSpeakerVolume(0.0),
- mMicGain(0.0)
-{
-
-}
-
-LLVoiceWebRTCConnection::~LLVoiceWebRTCConnection()
-{
- if (LLWebRTCVoiceClient::isShuttingDown())
- {
- // peer connection and observers will be cleaned up
- // by llwebrtc::terminate() on shutdown.
- return;
- }
- llwebrtc::freePeerConnection(mWebRTCPeerConnection);
- mWebRTCPeerConnection = nullptr;
-}
-
-
-void LLVoiceWebRTCConnection::setMuteMic(bool muted)
-{
- mMuted = muted;
- if (mWebRTCAudioInterface)
- {
- mWebRTCAudioInterface->setMute(muted);
- }
-}
-
-void LLVoiceWebRTCConnection::setMicGain(F32 gain)
-{
- mMicGain = gain;
- if (mWebRTCAudioInterface)
- {
- mWebRTCAudioInterface->setSendVolume(gain);
- }
-}
-
-void LLVoiceWebRTCConnection::setSpeakerVolume(F32 volume)
-{
- mSpeakerVolume = volume;
- if (mWebRTCAudioInterface)
- {
- mWebRTCAudioInterface->setReceiveVolume(volume);
- }
-}
-
-/////////////////////////////
-// WebRTC Signaling Handlers
-
-LLVoiceWebRTCSpatialConnection::LLVoiceWebRTCSpatialConnection(const LLUUID &regionID, S32 parcelLocalID, const std::string &channelID) :
- mWebRTCPeerConnection(nullptr),
+LLVoiceWebRTCConnection::LLVoiceWebRTCConnection(const LLUUID &regionID, const std::string &channelID) :
mWebRTCAudioInterface(nullptr),
mWebRTCDataInterface(nullptr),
- mIceCompleted(false),
- mTrickling(false),
mVoiceConnectionState(VOICE_STATE_START_SESSION),
- mChannelID(channelID),
- mRegionID(regionID),
- mParcelLocalID(parcelLocalID),
+ mMuted(true),
mShutDown(false),
- mOutstandingRequests(0)
+ mTrickling(false),
+ mIceCompleted(false),
+ mSpeakerVolume(0.0),
+ mMicGain(0.0),
+ mOutstandingRequests(0),
+ mChannelID(channelID),
+ mRegionID(regionID)
{
mWebRTCPeerConnection = llwebrtc::newPeerConnection();
mWebRTCPeerConnection->setSignalingObserver(this);
}
-LLVoiceWebRTCSpatialConnection::~LLVoiceWebRTCSpatialConnection()
+LLVoiceWebRTCConnection::~LLVoiceWebRTCConnection()
{
if (LLWebRTCVoiceClient::isShuttingDown())
{
@@ -2377,11 +2334,11 @@ LLVoiceWebRTCSpatialConnection::~LLVoiceWebRTCSpatialConnection()
// by llwebrtc::terminate() on shutdown.
return;
}
- assert(mOutstandingRequests == 0);
- mWebRTCPeerConnection->unsetSignalingObserver(this);
+ llwebrtc::freePeerConnection(mWebRTCPeerConnection);
+ mWebRTCPeerConnection = nullptr;
}
-void LLVoiceWebRTCSpatialConnection::OnIceGatheringState(llwebrtc::LLWebRTCSignalingObserver::IceGatheringState state)
+void LLVoiceWebRTCConnection::OnIceGatheringState(llwebrtc::LLWebRTCSignalingObserver::IceGatheringState state)
{
LL_INFOS("Voice") << "Ice Gathering voice account. " << state << LL_ENDL;
@@ -2403,13 +2360,13 @@ void LLVoiceWebRTCSpatialConnection::OnIceGatheringState(llwebrtc::LLWebRTCSigna
}
}
-void LLVoiceWebRTCSpatialConnection::OnIceCandidate(const llwebrtc::LLWebRTCIceCandidate &candidate)
+void LLVoiceWebRTCConnection::OnIceCandidate(const llwebrtc::LLWebRTCIceCandidate &candidate)
{
LLMutexLock lock(&mVoiceStateMutex);
mIceCandidates.push_back(candidate);
}
-void LLVoiceWebRTCSpatialConnection::onIceUpdateComplete(bool ice_completed, const LLSD &result)
+void LLVoiceWebRTCConnection::onIceUpdateComplete(bool ice_completed, const LLSD &result)
{
if (LLWebRTCVoiceClient::isShuttingDown())
{
@@ -2419,7 +2376,7 @@ void LLVoiceWebRTCSpatialConnection::onIceUpdateComplete(bool ice_completed, con
mOutstandingRequests--;
}
-void LLVoiceWebRTCSpatialConnection::onIceUpdateError(int retries, std::string url, LLSD body, bool ice_completed, const LLSD &result)
+void LLVoiceWebRTCConnection::onIceUpdateError(int retries, std::string url, LLSD body, bool ice_completed, const LLSD &result)
{
if (LLWebRTCVoiceClient::isShuttingDown())
{
@@ -2435,8 +2392,8 @@ void LLVoiceWebRTCSpatialConnection::onIceUpdateError(int retries, std::string u
url,
LLCore::HttpRequest::DEFAULT_POLICY_ID,
body,
- boost::bind(&LLVoiceWebRTCSpatialConnection::onIceUpdateComplete, this, ice_completed, _1),
- boost::bind(&LLVoiceWebRTCSpatialConnection::onIceUpdateError, this, retries - 1, url, body, ice_completed, _1));
+ boost::bind(&LLVoiceWebRTCConnection::onIceUpdateComplete, this, ice_completed, _1),
+ boost::bind(&LLVoiceWebRTCConnection::onIceUpdateError, this, retries - 1, url, body, ice_completed, _1));
return;
}
@@ -2450,7 +2407,7 @@ void LLVoiceWebRTCSpatialConnection::onIceUpdateError(int retries, std::string u
mOutstandingRequests--;
}
-void LLVoiceWebRTCSpatialConnection::OnOfferAvailable(const std::string &sdp)
+void LLVoiceWebRTCConnection::OnOfferAvailable(const std::string &sdp)
{
LL_INFOS("Voice") << "On Offer Available." << LL_ENDL;
LLMutexLock lock(&mVoiceStateMutex);
@@ -2461,110 +2418,14 @@ void LLVoiceWebRTCSpatialConnection::OnOfferAvailable(const std::string &sdp)
}
}
-void LLVoiceWebRTCSpatialConnection::OnAudioEstablished(llwebrtc::LLWebRTCAudioInterface *audio_interface)
+void LLVoiceWebRTCConnection::OnAudioEstablished(llwebrtc::LLWebRTCAudioInterface *audio_interface)
{
LL_INFOS("Voice") << "On AudioEstablished." << LL_ENDL;
mWebRTCAudioInterface = audio_interface;
setVoiceConnectionState(VOICE_STATE_SESSION_ESTABLISHED);
}
-void LLVoiceWebRTCSpatialConnection::OnDataReceived(const std::string &data, bool binary)
-{
- // incoming data will be a json structure (if it's not binary.) We may pack
- // binary for size reasons. Most of the keys in the json objects are
- // single or double characters for size reasons.
- // The primary element is:
- // An object where each key is an agent id. (in the future, we may allow
- // integer indices into an agentid list, populated on join commands. For size.
- // Each key will point to a json object with keys identifying what's updated.
- // 'p' - audio source power (level/volume) (int8 as int)
- // 'j' - join - object of join data (TBD) (true for now)
- // 'l' - boolean, always true if exists.
-
- if (binary)
- {
- LL_WARNS("Voice") << "Binary data received from data channel." << LL_ENDL;
- return;
- }
-
- Json::Reader reader;
- Json::Value voice_data;
- if (reader.parse(data, voice_data, false)) // don't collect comments
- {
- if (!voice_data.isObject())
- {
- LL_WARNS("Voice") << "Expected object from data channel:" << data << LL_ENDL;
- return;
- }
- bool new_participant = false;
- for (auto &participant_id : voice_data.getMemberNames())
- {
- LLUUID agent_id(participant_id);
- if (agent_id.isNull())
- {
- LL_WARNS("Voice") << "Bad participant ID from data channel (" << participant_id << "):" << data << LL_ENDL;
- continue;
- }
-
- LLWebRTCVoiceClient::participantStatePtr_t participant = LLWebRTCVoiceClient::getInstance()->findParticipantByID(mChannelID, agent_id);
- bool joined = false;
- bool primary = false;
- if (voice_data[participant_id].isMember("j"))
- {
- joined = true;
- primary = voice_data[participant_id]["j"].get("p", Json::Value(false)).asBool();
- }
-
- new_participant |= joined;
- if (!participant && joined && primary)
- {
- participant = LLWebRTCVoiceClient::getInstance()->addParticipantByID(mChannelID, agent_id);
- }
- if (participant)
- {
- if (voice_data[participant_id].get("l", Json::Value(false)).asBool())
- {
- if (agent_id != gAgentID)
- {
- LLWebRTCVoiceClient::getInstance()->removeParticipantByID(mChannelID, agent_id);
- }
- }
- else
- {
- F32 level = (F32) (voice_data[participant_id].get("p", Json::Value(participant->mLevel)).asInt()) / 128;
- // convert to decibles
- participant->mLevel = level;
- /* WebRTC appears to have deprecated VAD, but it's still in the Audio Processing Module so maybe we
- can use it at some point when we actually process frames. */
- participant->mIsSpeaking = participant->mLevel > SPEAKING_AUDIO_LEVEL;
- }
- }
- }
- }
-}
-
-void LLVoiceWebRTCSpatialConnection::OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface)
-{
- if (data_interface)
- {
- mWebRTCDataInterface = data_interface;
- mWebRTCDataInterface->setDataObserver(this);
-
- Json::FastWriter writer;
- Json::Value root = Json::objectValue;
- Json::Value join_obj = Json::objectValue;
- LLUUID regionID = gAgent.getRegion()->getRegionID();
- if (regionID == mRegionID)
- {
- join_obj["p"] = true;
- }
- root["j"] = join_obj;
- std::string json_data = writer.write(root);
- mWebRTCDataInterface->sendData(json_data, false);
- }
-}
-
-void LLVoiceWebRTCSpatialConnection::OnRenegotiationNeeded()
+void LLVoiceWebRTCConnection::OnRenegotiationNeeded()
{
LL_INFOS("Voice") << "On Renegotiation Needed." << LL_ENDL;
if (!mShutDown)
@@ -2573,13 +2434,13 @@ void LLVoiceWebRTCSpatialConnection::OnRenegotiationNeeded()
}
}
-void LLVoiceWebRTCSpatialConnection::OnPeerShutDown()
+void LLVoiceWebRTCConnection::OnPeerShutDown()
{
setVoiceConnectionState(VOICE_STATE_SESSION_EXIT);
mOutstandingRequests--;
}
-void LLVoiceWebRTCSpatialConnection::processIceUpdates()
+void LLVoiceWebRTCConnection::processIceUpdates()
{
if (mShutDown || LLWebRTCVoiceClient::isShuttingDown())
{
@@ -2596,39 +2457,40 @@ void LLVoiceWebRTCSpatialConnection::processIceUpdates()
LLViewerRegion *regionp = LLWorld::instance().getRegionFromID(mRegionID);
if (!regionp || !regionp->capabilitiesReceived())
{
- LL_DEBUGS("Voice") << "no capabilities for ice gathering; waiting " << LL_ENDL;
- return;
+ LL_DEBUGS("Voice") << "no capabilities for ice gathering; waiting " << LL_ENDL;
+ return;
}
std::string url = regionp->getCapability("VoiceSignalingRequest");
if (url.empty())
{
- return;
+ return;
}
LL_DEBUGS("Voice") << "region ready to complete voice signaling; url=" << url << LL_ENDL;
- if (!mIceCandidates.empty()) {
- LLSD candidates = LLSD::emptyArray();
- for (auto &ice_candidate : mIceCandidates)
- {
+ if (!mIceCandidates.empty())
+ {
+ LLSD candidates = LLSD::emptyArray();
+ for (auto &ice_candidate : mIceCandidates)
+ {
LLSD body_candidate;
body_candidate["sdpMid"] = ice_candidate.sdp_mid;
body_candidate["sdpMLineIndex"] = ice_candidate.mline_index;
body_candidate["candidate"] = ice_candidate.candidate;
candidates.append(body_candidate);
- }
- body["candidates"] = candidates;
- mIceCandidates.clear();
+ }
+ body["candidates"] = candidates;
+ mIceCandidates.clear();
}
else if (mIceCompleted)
{
- LLSD body_candidate;
- body_candidate["completed"] = true;
- body["candidate"] = body_candidate;
- iceCompleted = mIceCompleted;
- mIceCompleted = false;
+ LLSD body_candidate;
+ body_candidate["completed"] = true;
+ body["candidate"] = body_candidate;
+ iceCompleted = mIceCompleted;
+ mIceCompleted = false;
}
-
+
body["viewer_session"] = mViewerSession;
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
@@ -2649,14 +2511,56 @@ void LLVoiceWebRTCSpatialConnection::processIceUpdates()
}
}
-bool LLVoiceWebRTCSpatialConnection::requestVoiceConnection()
+
+void LLVoiceWebRTCConnection::setMuteMic(bool muted)
{
- LLViewerRegion *regionp = LLWorld::instance().getRegionFromID(mRegionID);
+ mMuted = muted;
+ if (mWebRTCAudioInterface)
+ {
+ mWebRTCAudioInterface->setMute(muted);
+ }
+}
- LL_INFOS("Voice") << "Requesting voice connection." << LL_ENDL;
+void LLVoiceWebRTCConnection::setMicGain(F32 gain)
+{
+ mMicGain = gain;
+ if (mWebRTCAudioInterface)
+ {
+ mWebRTCAudioInterface->setSendVolume(gain);
+ }
+}
+
+void LLVoiceWebRTCConnection::setSpeakerVolume(F32 volume)
+{
+ mSpeakerVolume = volume;
+ if (mWebRTCAudioInterface)
+ {
+ mWebRTCAudioInterface->setReceiveVolume(volume);
+ }
+}
+
+void LLVoiceWebRTCConnection::sendData(const std::string &data)
+{
+ if (getVoiceConnectionState() == VOICE_STATE_SESSION_UP && mWebRTCDataInterface)
+ {
+ mWebRTCDataInterface->sendData(data, false);
+ }
+}
+
+bool LLVoiceWebRTCConnection::breakVoiceConnection(bool corowait)
+{
+ LL_INFOS("Voice") << "Disconnecting voice." << LL_ENDL;
+ if (mWebRTCDataInterface)
+ {
+ mWebRTCDataInterface->unsetDataObserver(this);
+ mWebRTCDataInterface = nullptr;
+ }
+ mWebRTCAudioInterface = nullptr;
+ LLViewerRegion *regionp = LLWorld::instance().getRegionFromID(mRegionID);
if (!regionp || !regionp->capabilitiesReceived())
{
LL_DEBUGS("Voice") << "no capabilities for voice provisioning; waiting " << LL_ENDL;
+ setVoiceConnectionState(VOICE_STATE_SESSION_EXIT);
return false;
}
@@ -2666,33 +2570,77 @@ bool LLVoiceWebRTCSpatialConnection::requestVoiceConnection()
return false;
}
- LL_DEBUGS("Voice") << "region ready for voice provisioning; url=" << url << LL_ENDL;
+ LL_DEBUGS("Voice") << "region ready for voice break; url=" << url << LL_ENDL;
+
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("parcelVoiceInfoRequest", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLVoiceWebRTCStats::getInstance()->provisionAttemptStart();
LLSD body;
- LLSD jsep;
- jsep["type"] = "offer";
- {
- LLMutexLock lock(&mVoiceStateMutex);
- jsep["sdp"] = mChannelSDP;
- }
- body["jsep"] = jsep;
- if (mParcelLocalID != INVALID_PARCEL_ID)
- {
- body["parcel_local_id"] = mParcelLocalID;
- }
+ body["logout"] = TRUE;
+ body["viewer_session"] = mViewerSession;
LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(
url,
LLCore::HttpRequest::DEFAULT_POLICY_ID,
body,
- boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceConnectionRequestSuccess, this, _1),
- boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceConnectionRequestFailure, this, url, 3, body, _1));
+ boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceDisconnectionRequestSuccess, this, _1),
+ boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceDisconnectionRequestFailure, this, url, 3, body, _1));
+ setVoiceConnectionState(VOICE_STATE_WAIT_FOR_EXIT);
mOutstandingRequests++;
return true;
}
-void LLVoiceWebRTCSpatialConnection::OnVoiceConnectionRequestSuccess(const LLSD &result)
+void LLVoiceWebRTCConnection::OnVoiceDisconnectionRequestSuccess(const LLSD &result)
+{
+ if (LLWebRTCVoiceClient::isShuttingDown())
+ {
+ return;
+ }
+
+ if (mWebRTCPeerConnection)
+ {
+ mOutstandingRequests++;
+ mWebRTCPeerConnection->shutdownConnection();
+ }
+ else
+ {
+ setVoiceConnectionState(VOICE_STATE_SESSION_EXIT);
+ }
+ mOutstandingRequests--;
+}
+
+void LLVoiceWebRTCConnection::OnVoiceDisconnectionRequestFailure(std::string url, int retries, LLSD body, const LLSD &result)
+{
+ if (LLWebRTCVoiceClient::isShuttingDown())
+ {
+ return;
+ }
+ if (retries >= 0)
+ {
+ LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(
+ url,
+ LLCore::HttpRequest::DEFAULT_POLICY_ID,
+ body,
+ boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceDisconnectionRequestSuccess, this, _1),
+ boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceDisconnectionRequestFailure, this, url, retries - 1, body, _1));
+ return;
+ }
+ if (mWebRTCPeerConnection)
+ {
+ mOutstandingRequests++;
+ mWebRTCPeerConnection->shutdownConnection();
+ }
+ else
+ {
+ setVoiceConnectionState(VOICE_STATE_SESSION_EXIT);
+ }
+ mOutstandingRequests--;
+}
+
+
+void LLVoiceWebRTCConnection::OnVoiceConnectionRequestSuccess(const LLSD &result)
{
if (LLWebRTCVoiceClient::isShuttingDown())
{
@@ -2700,10 +2648,11 @@ void LLVoiceWebRTCSpatialConnection::OnVoiceConnectionRequestSuccess(const LLSD
}
LLVoiceWebRTCStats::getInstance()->provisionAttemptEnd(true);
- if (result.has("viewer_session") && result.has("jsep") && result["jsep"].has("type") && result["jsep"]["type"] == "answer" && result["jsep"].has("sdp"))
+ if (result.has("viewer_session") && result.has("jsep") && result["jsep"].has("type") && result["jsep"]["type"] == "answer" &&
+ result["jsep"].has("sdp"))
{
mRemoteChannelSDP = result["jsep"]["sdp"].asString();
- mViewerSession = result["viewer_session"];
+ mViewerSession = result["viewer_session"];
}
else
{
@@ -2719,7 +2668,7 @@ void LLVoiceWebRTCSpatialConnection::OnVoiceConnectionRequestSuccess(const LLSD
mOutstandingRequests--;
}
-void LLVoiceWebRTCSpatialConnection::OnVoiceConnectionRequestFailure(std::string url, int retries, LLSD body, const LLSD &result)
+void LLVoiceWebRTCConnection::OnVoiceConnectionRequestFailure(std::string url, int retries, LLSD body, const LLSD &result)
{
if (LLWebRTCVoiceClient::isShuttingDown())
{
@@ -2731,17 +2680,17 @@ void LLVoiceWebRTCSpatialConnection::OnVoiceConnectionRequestFailure(std::string
url,
LLCore::HttpRequest::DEFAULT_POLICY_ID,
body,
- boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceConnectionRequestSuccess, this, _1),
- boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceConnectionRequestFailure, this, url, retries - 1, body, _1));
+ boost::bind(&LLVoiceWebRTCConnection::OnVoiceConnectionRequestSuccess, this, _1),
+ boost::bind(&LLVoiceWebRTCConnection::OnVoiceConnectionRequestFailure, this, url, retries - 1, body, _1));
return;
}
LL_WARNS("Voice") << "Unable to connect voice." << body << " RESULT: " << result << LL_ENDL;
- setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
+ setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
mOutstandingRequests--;
}
-bool LLVoiceWebRTCSpatialConnection::connectionStateMachine()
-{
+bool LLVoiceWebRTCConnection::connectionStateMachine()
+{
processIceUpdates();
switch (getVoiceConnectionState())
@@ -2819,7 +2768,6 @@ bool LLVoiceWebRTCSpatialConnection::connectionStateMachine()
LLWebRTCVoiceClient::getInstance()->OnConnectionFailure(mChannelID, mRegionID);
setVoiceConnectionState(VOICE_STATE_DISCONNECT);
break;
- break;
case VOICE_STATE_DISCONNECT:
breakVoiceConnection(true);
@@ -2831,13 +2779,17 @@ bool LLVoiceWebRTCSpatialConnection::connectionStateMachine()
{
{
LLMutexLock lock(&mVoiceStateMutex);
- if (!mShutDown)
+ if (!mShutDown)
{
mVoiceConnectionState = VOICE_STATE_START_SESSION;
}
else
{
- return mOutstandingRequests > 0;
+ if (mOutstandingRequests <= 0)
+ {
+ LLWebRTCVoiceClient::getInstance()->OnConnectionShutDown(mChannelID, mRegionID);
+ return false;
+ }
}
}
break;
@@ -2852,29 +2804,133 @@ bool LLVoiceWebRTCSpatialConnection::connectionStateMachine()
return true;
}
+void LLVoiceWebRTCConnection::OnDataReceived(const std::string &data, bool binary)
+{
+ // incoming data will be a json structure (if it's not binary.) We may pack
+ // binary for size reasons. Most of the keys in the json objects are
+ // single or double characters for size reasons.
+ // The primary element is:
+ // An object where each key is an agent id. (in the future, we may allow
+ // integer indices into an agentid list, populated on join commands. For size.
+ // Each key will point to a json object with keys identifying what's updated.
+ // 'p' - audio source power (level/volume) (int8 as int)
+ // 'j' - join - object of join data (TBD) (true for now)
+ // 'l' - boolean, always true if exists.
-void LLVoiceWebRTCSpatialConnection::sendData(const std::string& data) {
-
- if (getVoiceConnectionState() == VOICE_STATE_SESSION_UP && mWebRTCDataInterface)
+ if (binary)
{
- mWebRTCDataInterface->sendData(data, false);
+ LL_WARNS("Voice") << "Binary data received from data channel." << LL_ENDL;
+ return;
+ }
+
+ Json::Reader reader;
+ Json::Value voice_data;
+ if (reader.parse(data, voice_data, false)) // don't collect comments
+ {
+ if (!voice_data.isObject())
+ {
+ LL_WARNS("Voice") << "Expected object from data channel:" << data << LL_ENDL;
+ return;
+ }
+ bool new_participant = false;
+ for (auto &participant_id : voice_data.getMemberNames())
+ {
+ LLUUID agent_id(participant_id);
+ if (agent_id.isNull())
+ {
+ LL_WARNS("Voice") << "Bad participant ID from data channel (" << participant_id << "):" << data << LL_ENDL;
+ continue;
+ }
+
+ LLWebRTCVoiceClient::participantStatePtr_t participant =
+ LLWebRTCVoiceClient::getInstance()->findParticipantByID(mChannelID, agent_id);
+ bool joined = false;
+ bool primary = false;
+ if (voice_data[participant_id].isMember("j"))
+ {
+ joined = true;
+ primary = voice_data[participant_id]["j"].get("p", Json::Value(false)).asBool();
+ }
+
+ new_participant |= joined;
+ if (!participant && joined && primary)
+ {
+ participant = LLWebRTCVoiceClient::getInstance()->addParticipantByID(mChannelID, agent_id);
+ }
+ if (participant)
+ {
+ if (voice_data[participant_id].get("l", Json::Value(false)).asBool())
+ {
+ if (agent_id != gAgentID)
+ {
+ LLWebRTCVoiceClient::getInstance()->removeParticipantByID(mChannelID, agent_id);
+ }
+ }
+ else
+ {
+ F32 level = (F32) (voice_data[participant_id].get("p", Json::Value(participant->mLevel)).asInt()) / 128;
+ // convert to decibles
+ participant->mLevel = level;
+ /* WebRTC appears to have deprecated VAD, but it's still in the Audio Processing Module so maybe we
+ can use it at some point when we actually process frames. */
+ participant->mIsSpeaking = participant->mLevel > SPEAKING_AUDIO_LEVEL;
+ }
+ }
+ }
}
}
-bool LLVoiceWebRTCSpatialConnection::breakVoiceConnection(bool corowait)
+void LLVoiceWebRTCConnection::OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface)
{
- LL_INFOS("Voice") << "Disconnecting voice." << LL_ENDL;
- if (mWebRTCDataInterface)
+ if (data_interface)
{
- mWebRTCDataInterface->unsetDataObserver(this);
- mWebRTCDataInterface = nullptr;
+ mWebRTCDataInterface = data_interface;
+ mWebRTCDataInterface->setDataObserver(this);
+
+ Json::FastWriter writer;
+ Json::Value root = Json::objectValue;
+ Json::Value join_obj = Json::objectValue;
+ LLUUID regionID = gAgent.getRegion()->getRegionID();
+ if (regionID == mRegionID)
+ {
+ join_obj["p"] = true;
+ }
+ root["j"] = join_obj;
+ std::string json_data = writer.write(root);
+ mWebRTCDataInterface->sendData(json_data, false);
}
- mWebRTCAudioInterface = nullptr;
+}
+
+/////////////////////////////
+// WebRTC Spatial Connection
+
+LLVoiceWebRTCSpatialConnection::LLVoiceWebRTCSpatialConnection(const LLUUID &regionID, S32 parcelLocalID, const std::string &channelID) :
+ LLVoiceWebRTCConnection(regionID, channelID),
+ mParcelLocalID(parcelLocalID)
+{
+}
+
+LLVoiceWebRTCSpatialConnection::~LLVoiceWebRTCSpatialConnection()
+{
+ if (LLWebRTCVoiceClient::isShuttingDown())
+ {
+ // peer connection and observers will be cleaned up
+ // by llwebrtc::terminate() on shutdown.
+ return;
+ }
+ assert(mOutstandingRequests == 0);
+ mWebRTCPeerConnection->unsetSignalingObserver(this);
+}
+
+
+bool LLVoiceWebRTCSpatialConnection::requestVoiceConnection()
+{
LLViewerRegion *regionp = LLWorld::instance().getRegionFromID(mRegionID);
+
+ LL_INFOS("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_EXIT);
return false;
}
@@ -2884,89 +2940,110 @@ bool LLVoiceWebRTCSpatialConnection::breakVoiceConnection(bool corowait)
return false;
}
- LL_DEBUGS("Voice") << "region ready for voice break; url=" << url << LL_ENDL;
-
- LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("parcelVoiceInfoRequest", httpPolicy));
- LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LL_DEBUGS("Voice") << "region ready for voice provisioning; url=" << url << LL_ENDL;
LLVoiceWebRTCStats::getInstance()->provisionAttemptStart();
LLSD body;
- body["logout"] = TRUE;
- body["viewer_session"] = mViewerSession;
+ LLSD jsep;
+ jsep["type"] = "offer";
+ {
+ LLMutexLock lock(&mVoiceStateMutex);
+ jsep["sdp"] = mChannelSDP;
+ }
+ body["jsep"] = jsep;
+ if (mParcelLocalID != INVALID_PARCEL_ID)
+ {
+ body["parcel_local_id"] = mParcelLocalID;
+ }
LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(
url,
LLCore::HttpRequest::DEFAULT_POLICY_ID,
body,
- boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceDisconnectionRequestSuccess, this, _1),
- boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceDisconnectionRequestFailure, this, url, 3, body, _1));
- setVoiceConnectionState(VOICE_STATE_WAIT_FOR_EXIT);
+ boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceConnectionRequestSuccess, this, _1),
+ boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceConnectionRequestFailure, this, url, 3, body, _1));
mOutstandingRequests++;
return true;
}
-void LLVoiceWebRTCSpatialConnection::OnVoiceDisconnectionRequestSuccess(const LLSD &result)
+void LLVoiceWebRTCSpatialConnection::setMuteMic(bool muted)
{
- if (LLWebRTCVoiceClient::isShuttingDown())
+ mMuted = muted;
+ if (mWebRTCAudioInterface)
{
- return;
+ LLViewerRegion *regionp = gAgent.getRegion();
+ if (regionp && mRegionID == regionp->getRegionID())
+ {
+ mWebRTCAudioInterface->setMute(muted);
+ }
+ else
+ {
+ // always mute to regions the agent isn't on, to prevent echo.
+ mWebRTCAudioInterface->setMute(true);
+ }
}
+}
- if (mWebRTCPeerConnection)
- {
- mOutstandingRequests++;
- mWebRTCPeerConnection->shutdownConnection();
- }
- else
- {
- setVoiceConnectionState(VOICE_STATE_SESSION_EXIT);
- }
- mOutstandingRequests--;
+/////////////////////////////
+// WebRTC Spatial Connection
+
+LLVoiceWebRTCAdHocConnection::LLVoiceWebRTCAdHocConnection(const LLUUID &regionID, const std::string& channelID, const std::string& credentials) :
+ LLVoiceWebRTCConnection(regionID, channelID),
+ mCredentials(credentials)
+{
}
-void LLVoiceWebRTCSpatialConnection::OnVoiceDisconnectionRequestFailure(std::string url, int retries, LLSD body, const LLSD &result)
+LLVoiceWebRTCAdHocConnection::~LLVoiceWebRTCAdHocConnection()
{
if (LLWebRTCVoiceClient::isShuttingDown())
{
+ // peer connection and observers will be cleaned up
+ // by llwebrtc::terminate() on shutdown.
return;
}
- if (retries >= 0)
- {
- LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(
- url,
- LLCore::HttpRequest::DEFAULT_POLICY_ID,
- body,
- boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceDisconnectionRequestSuccess, this, _1),
- boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceDisconnectionRequestFailure, this, url, retries - 1, body, _1));
- return;
- }
- if (mWebRTCPeerConnection)
+ assert(mOutstandingRequests == 0);
+ mWebRTCPeerConnection->unsetSignalingObserver(this);
+}
+
+
+bool LLVoiceWebRTCAdHocConnection::requestVoiceConnection()
+{
+ LLViewerRegion *regionp = LLWorld::instance().getRegionFromID(mRegionID);
+
+ LL_INFOS("Voice") << "Requesting voice connection." << LL_ENDL;
+ if (!regionp || !regionp->capabilitiesReceived())
{
- mOutstandingRequests++;
- mWebRTCPeerConnection->shutdownConnection();
+ LL_DEBUGS("Voice") << "no capabilities for voice provisioning; waiting " << LL_ENDL;
+ return false;
}
- else
+
+ std::string url = regionp->getCapability("ProvisionVoiceAccountRequest");
+ if (url.empty())
{
- setVoiceConnectionState(VOICE_STATE_SESSION_EXIT);
+ return false;
}
- mOutstandingRequests--;
-}
-void LLVoiceWebRTCSpatialConnection::setMuteMic(bool muted)
-{
- mMuted = muted;
- if (mWebRTCAudioInterface)
+ LL_DEBUGS("Voice") << "region ready for voice provisioning; url=" << url << LL_ENDL;
+
+ LLVoiceWebRTCStats::getInstance()->provisionAttemptStart();
+ LLSD body;
+ LLSD jsep;
+ jsep["type"] = "offer";
{
- LLViewerRegion *regionp = gAgent.getRegion();
- if (regionp && mRegionID == regionp->getRegionID())
- {
- mWebRTCAudioInterface->setMute(muted);
- }
- else
- {
- // always mute to regions the agent isn't on, to prevent echo.
- mWebRTCAudioInterface->setMute(true);
- }
+ LLMutexLock lock(&mVoiceStateMutex);
+ jsep["sdp"] = mChannelSDP;
}
+ body["jsep"] = jsep;
+ body["credentials"] = mCredentials;
+ body["channel"] = mChannelID;
+ body["channel_type"] = "multiagent";
+
+ LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(
+ url,
+ LLCore::HttpRequest::DEFAULT_POLICY_ID,
+ body,
+ boost::bind(&LLVoiceWebRTCAdHocConnection::OnVoiceConnectionRequestSuccess, this, _1),
+ boost::bind(&LLVoiceWebRTCAdHocConnection::OnVoiceConnectionRequestFailure, this, url, 3, body, _1));
+ mOutstandingRequests++;
+ return true;
}
diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h
index b2672ac108..f81c8c556e 100644
--- a/indra/newview/llvoicewebrtc.h
+++ b/indra/newview/llvoicewebrtc.h
@@ -144,10 +144,8 @@ public:
// Note that gestures should only fire if this returns true.
bool inProximalChannel() override;
- void setNonSpatialChannel(const std::string& uri,
- const std::string& credentials) override
- {
-
+ void setNonSpatialChannel(const std::string& uri, const std::string& credentials) override {
+ startAdHocSession(uri, credentials);
}
bool setSpatialChannel(const std::string &uri, const std::string &credentials) override
@@ -172,6 +170,7 @@ public:
/// @name invitations
//@{
// start a voice channel with the specified user
+ bool hasP2PInterface() override { return false; }
void callUser(const LLUUID &uuid) override;
bool isValidChannel(std::string &channelID) override;
bool answerInvite(std::string &channelID) override;
@@ -247,6 +246,7 @@ public:
void OnConnectionEstablished(const std::string& channelID, const LLUUID& regionID);
+ void OnConnectionShutDown(const std::string &channelID, const LLUUID &regionID);
void OnConnectionFailure(const std::string &channelID, const LLUUID& regionID);
void sendPositionUpdate(bool force);
void updateOwnVolume();
@@ -338,7 +338,7 @@ public:
virtual bool processConnectionStates();
- void sendData(const std::string &data);
+ virtual void sendData(const std::string &data);
void setMuteMic(bool muted);
void setMicGain(F32 volume);
@@ -427,11 +427,17 @@ public:
class adhocSessionState : public sessionState
{
- public:
- adhocSessionState(const std::string &channelID);
+ public:
+ adhocSessionState(const std::string &channelID, const std::string& credentials);
bool isSpatial() override { return false; }
bool isEstate() override { return false; }
+
+ // don't send spatial data to adhoc sessions.
+ void sendData(const std::string &data) override { }
+
+ protected:
+ std::string mCredentials;
};
@@ -511,26 +517,6 @@ public:
// It contains logic for whether to delete the session or keep it around.
void reapSession(const sessionStatePtr_t &session);
- //////////////////////////////////////
- // buddy list stuff, needed for SLIM later
- struct buddyListEntry
- {
- buddyListEntry(const std::string &uri);
- std::string mURI;
- std::string mDisplayName;
- LLUUID mUUID;
- bool mOnlineSL;
- bool mOnlineSLim;
- bool mCanSeeMeOnline;
- bool mHasBlockListEntry;
- bool mHasAutoAcceptListEntry;
- bool mNameResolved;
- bool mInSLFriends;
- bool mInWebRTCBuddies;
- };
-
- typedef std::map<std::string, buddyListEntry*> buddyListMap;
-
// Pokes the state machine to leave the audio session next time around.
void sessionTerminate();
@@ -612,7 +598,6 @@ private:
bool mBuddyListMapPopulated;
bool mBlockRulesListReceived;
bool mAutoAcceptRulesListReceived;
- buddyListMap mBuddyListMap;
llwebrtc::LLWebRTCDeviceInterface *mWebRTCDeviceInterface;
@@ -624,8 +609,7 @@ private:
bool startEstateSession();
bool startParcelSession(const std::string& channelID, S32 parcelID);
- bool startAdHocSession(const std::string& channelID);
-
+ bool startAdHocSession(const std::string& channelID, const std::string& credentials);
void joinSession(const sessionStatePtr_t &session);
@@ -749,147 +733,126 @@ class LLVoiceWebRTCStats : public LLSingleton<LLVoiceWebRTCStats>
LLSD read();
};
-class LLVoiceWebRTCConnection
-{
- public:
- LLVoiceWebRTCConnection();
-
- virtual ~LLVoiceWebRTCConnection() = 0;
-
- virtual bool connectionStateMachine() = 0;
-
- virtual void sendData(const std::string &data) {};
- virtual void setMuteMic(bool muted);
- virtual void setMicGain(F32 volume);
- virtual void setSpeakerVolume(F32 volume);
-
- virtual void shutDown() = 0;
-
-protected:
-
- bool mMuted;
- F32 mMicGain;
- F32 mSpeakerVolume;
-
- llwebrtc::LLWebRTCPeerConnection *mWebRTCPeerConnection;
- llwebrtc::LLWebRTCAudioInterface *mWebRTCAudioInterface;
-};
-
-
-class LLVoiceWebRTCSpatialConnection :
- public LLVoiceWebRTCConnection,
- public llwebrtc::LLWebRTCSignalingObserver,
+class LLVoiceWebRTCConnection :
+ public llwebrtc::LLWebRTCSignalingObserver,
public llwebrtc::LLWebRTCDataObserver
{
public:
- LLVoiceWebRTCSpatialConnection(const LLUUID &regionID, S32 parcelLocalID, const std::string &channelID);
+ LLVoiceWebRTCConnection(const LLUUID &regionID, const std::string &channelID);
- virtual ~LLVoiceWebRTCSpatialConnection();
+ virtual ~LLVoiceWebRTCConnection() = 0;
//////////////////////////////
/// @name Signaling notification
// LLWebRTCSignalingObserver
//@{
- void OnIceGatheringState(IceGatheringState state) override;
- void OnIceCandidate(const llwebrtc::LLWebRTCIceCandidate &candidate) override;
- void OnOfferAvailable(const std::string &sdp) override;
- void OnRenegotiationNeeded() override;
- void OnAudioEstablished(llwebrtc::LLWebRTCAudioInterface *audio_interface) override;
- void OnPeerShutDown() override;
+ virtual void OnIceGatheringState(IceGatheringState state);
+ virtual void OnIceCandidate(const llwebrtc::LLWebRTCIceCandidate &candidate);
+ virtual void OnOfferAvailable(const std::string &sdp);
+ virtual void OnRenegotiationNeeded() override;
+ virtual void OnAudioEstablished(llwebrtc::LLWebRTCAudioInterface *audio_interface);
+ virtual void OnPeerShutDown();
//@}
/////////////////////////
/// @name Data Notification
/// LLWebRTCDataObserver
//@{
- void OnDataReceived(const std::string &data, bool binary) override;
- void OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface) override;
+ virtual void OnDataReceived(const std::string &data, bool binary);
+ virtual void OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface);
//@}
- void processIceUpdates();
- void onIceUpdateComplete(bool ice_completed, const LLSD &result);
- void onIceUpdateError(int retries, std::string url, LLSD body, bool ice_completed, const LLSD &result);
+ void sendData(const std::string &data);
- bool requestVoiceConnection();
- void OnVoiceConnectionRequestSuccess(const LLSD &body);
- void OnVoiceConnectionRequestFailure(std::string url, int retries, LLSD body, const LLSD &result);
+ virtual void processIceUpdates();
+ virtual void onIceUpdateComplete(bool ice_completed, const LLSD &result);
+ virtual void onIceUpdateError(int retries, std::string url, LLSD body, bool ice_completed, const LLSD &result);
- bool connectionStateMachine() override;
+ virtual void setMuteMic(bool muted);
+ virtual void setMicGain(F32 volume);
+ virtual void setSpeakerVolume(F32 volume);
- void sendData(const std::string &data) override;
- void setMuteMic(bool muted) override;
+
+ bool connectionStateMachine();
LLUUID getRegionID() { return mRegionID; }
- void shutDown() override
- {
- LLMutexLock lock(&mVoiceStateMutex);
- mShutDown = true;
- }
+ void shutDown()
+ {
+ LLMutexLock lock(&mVoiceStateMutex);
+ mShutDown = true;
+ }
-protected:
+ void OnVoiceConnectionRequestSuccess(const LLSD &body);
+ void OnVoiceConnectionRequestFailure(std::string url, int retries, LLSD body, const LLSD &result);
+
+ protected:
typedef enum e_voice_connection_state
{
- VOICE_STATE_ERROR = 0x0,
- VOICE_STATE_START_SESSION = 0x1,
- VOICE_STATE_WAIT_FOR_SESSION_START = 0x2,
- VOICE_STATE_REQUEST_CONNECTION = 0x4,
- VOICE_STATE_CONNECTION_WAIT = 0x8,
- VOICE_STATE_SESSION_ESTABLISHED = 0x10,
- VOICE_STATE_SESSION_UP = 0x20,
- VOICE_STATE_SESSION_RETRY = 0x40,
- VOICE_STATE_DISCONNECT = 0x80,
- VOICE_STATE_WAIT_FOR_EXIT = 0x100,
- VOICE_STATE_SESSION_EXIT = 0x200,
- VOICE_STATE_SESSION_STOPPING = 0x3c0,
- VOICE_STATE_SESSION_WAITING = 0x10a
+ VOICE_STATE_ERROR = 0x0,
+ VOICE_STATE_START_SESSION = 0x1,
+ VOICE_STATE_WAIT_FOR_SESSION_START = 0x2,
+ VOICE_STATE_REQUEST_CONNECTION = 0x4,
+ VOICE_STATE_CONNECTION_WAIT = 0x8,
+ VOICE_STATE_SESSION_ESTABLISHED = 0x10,
+ VOICE_STATE_SESSION_UP = 0x20,
+ VOICE_STATE_SESSION_RETRY = 0x40,
+ VOICE_STATE_DISCONNECT = 0x80,
+ VOICE_STATE_WAIT_FOR_EXIT = 0x100,
+ VOICE_STATE_SESSION_EXIT = 0x200,
+ VOICE_STATE_SESSION_STOPPING = 0x3c0,
+ VOICE_STATE_SESSION_WAITING = 0x10a
} EVoiceConnectionState;
EVoiceConnectionState mVoiceConnectionState;
- LLMutex mVoiceStateMutex;
- void setVoiceConnectionState(EVoiceConnectionState new_voice_connection_state)
+ LLMutex mVoiceStateMutex;
+ void setVoiceConnectionState(EVoiceConnectionState new_voice_connection_state)
{
LLMutexLock lock(&mVoiceStateMutex);
- if (new_voice_connection_state & VOICE_STATE_SESSION_STOPPING)
- {
- // the new state is shutdown or restart.
+ if (new_voice_connection_state & VOICE_STATE_SESSION_STOPPING)
+ {
+ // the new state is shutdown or restart.
mVoiceConnectionState = new_voice_connection_state;
return;
- }
+ }
if (mVoiceConnectionState & VOICE_STATE_SESSION_STOPPING)
- {
- // we're currently shutting down or restarting, so ignore any
- // state changes.
+ {
+ // we're currently shutting down or restarting, so ignore any
+ // state changes.
return;
- }
+ }
mVoiceConnectionState = new_voice_connection_state;
}
EVoiceConnectionState getVoiceConnectionState()
{
- if (mVoiceStateMutex.isLocked())
- {
+ if (mVoiceStateMutex.isLocked())
+ {
LL_WARNS("Voice") << "LOCKED." << LL_ENDL;
- }
+ }
LLMutexLock lock(&mVoiceStateMutex);
return mVoiceConnectionState;
}
+ virtual bool requestVoiceConnection() = 0;
+
bool breakVoiceConnection(bool wait);
void OnVoiceDisconnectionRequestSuccess(const LLSD &body);
void OnVoiceDisconnectionRequestFailure(std::string url, int retries, LLSD body, const LLSD &result);
+ LLUUID mRegionID;
+ LLUUID mViewerSession;
+ std::string mChannelID;
+
std::string mChannelSDP;
std::string mRemoteChannelSDP;
- LLUUID mViewerSession;
-
- std::string mChannelID;
- LLUUID mRegionID;
- S32 mParcelLocalID;
+ bool mMuted;
+ F32 mMicGain;
+ F32 mSpeakerVolume;
- bool mShutDown;
+ bool mShutDown;
S32 mOutstandingRequests;
std::vector<llwebrtc::LLWebRTCIceCandidate> mIceCandidates;
@@ -901,6 +864,38 @@ protected:
llwebrtc::LLWebRTCDataInterface *mWebRTCDataInterface;
};
+
+class LLVoiceWebRTCSpatialConnection :
+ public LLVoiceWebRTCConnection
+{
+ public:
+ LLVoiceWebRTCSpatialConnection(const LLUUID &regionID, S32 parcelLocalID, const std::string &channelID);
+
+ virtual ~LLVoiceWebRTCSpatialConnection();
+
+ void setMuteMic(bool muted) override;
+
+
+protected:
+
+ bool requestVoiceConnection() override;
+
+ S32 mParcelLocalID;
+};
+
+class LLVoiceWebRTCAdHocConnection : public LLVoiceWebRTCConnection
+{
+ public:
+ LLVoiceWebRTCAdHocConnection(const LLUUID &regionID, const std::string &channelID, const std::string& credentials);
+
+ virtual ~LLVoiceWebRTCAdHocConnection();
+
+ protected:
+ bool requestVoiceConnection() override;
+
+ std::string mCredentials;
+};
+
#define VOICE_ELAPSED LLVoiceTimer(__FUNCTION__);
#endif //LL_WebRTC_VOICE_CLIENT_H