diff options
| author | Roxie Linden <roxie@lindenlab.com> | 2024-01-25 20:53:19 -0800 | 
|---|---|---|
| committer | Roxie Linden <roxie@lindenlab.com> | 2024-02-08 18:35:21 -0800 | 
| commit | 0e6103e3a943c7f7726a93535048c634eb85eefc (patch) | |
| tree | ed6fc6c666efd6d2176819ade9a2a10b23a2c18c /indra | |
| parent | ef90eba410c9357f62c8e5eaf7a0447bcb51d72f (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.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/llvoicechannel.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/llvoiceclient.cpp | 7 | ||||
| -rw-r--r-- | indra/newview/llvoiceclient.h | 2 | ||||
| -rw-r--r-- | indra/newview/llvoicewebrtc.cpp | 681 | ||||
| -rw-r--r-- | indra/newview/llvoicewebrtc.h | 229 | 
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 ®ionID) +{ +    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 ®ionID, S32 parcelLocalID, const std::string &channelID) : -    mWebRTCPeerConnection(nullptr), +LLVoiceWebRTCConnection::LLVoiceWebRTCConnection(const LLUUID ®ionID, 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 ®ionID, 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 ®ionID, 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 ®ionID);      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 ®ionID, S32 parcelLocalID, const std::string &channelID); +    LLVoiceWebRTCConnection(const LLUUID ®ionID, 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 ®ionID, 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 ®ionID, 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 | 
