summaryrefslogtreecommitdiff
path: root/indra/newview/llvoicewebrtc.h
diff options
context:
space:
mode:
authorRoxanne Skelly <roxie@lindenlab.com>2024-03-13 11:33:13 -0700
committerGitHub <noreply@github.com>2024-03-13 11:33:13 -0700
commitb32364ba49ab58656fc6b146e5db499022dc9512 (patch)
tree20b774948f8592e0834b9b55af79180463b06e58 /indra/newview/llvoicewebrtc.h
parentb242d696ba03f66494dfca1f05a74ed1b15cd6e4 (diff)
parent76460e8c2c33af185ae8641775d5673fcdab0759 (diff)
Merge pull request #116 from secondlife/roxie/webrtc-voice
WebRTC-based voice for Second Life
Diffstat (limited to 'indra/newview/llvoicewebrtc.h')
-rw-r--r--indra/newview/llvoicewebrtc.h745
1 files changed, 745 insertions, 0 deletions
diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h
new file mode 100644
index 0000000000..03bbe00162
--- /dev/null
+++ b/indra/newview/llvoicewebrtc.h
@@ -0,0 +1,745 @@
+/**
+ * @file llvoicewebrtc.h
+ * @brief Declaration of LLWebRTCVoiceClient class which is the interface to the voice client process.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+#ifndef LL_VOICE_WEBRTC_H
+#define LL_VOICE_WEBRTC_H
+
+class LLWebRTCProtocolParser;
+
+#include "lliopipe.h"
+#include "llpumpio.h"
+#include "llchainio.h"
+#include "lliosocket.h"
+#include "v3math.h"
+#include "llframetimer.h"
+#include "llviewerregion.h"
+#include "llcallingcard.h" // for LLFriendObserver
+#include "lleventcoro.h"
+#include "llcoros.h"
+#include "llparcel.h"
+#include "llmutelist.h"
+#include <queue>
+#include "json/reader.h"
+
+#ifdef LL_USESYSTEMLIBS
+# include "expat.h"
+#else
+# include "expat/expat.h"
+#endif
+#include "llvoiceclient.h"
+
+// WebRTC Includes
+#include <llwebrtc.h>
+
+class LLAvatarName;
+class LLVoiceWebRTCConnection;
+typedef boost::shared_ptr<LLVoiceWebRTCConnection> connectionPtr_t;
+
+extern const std::string WEBRTC_VOICE_SERVER_TYPE;
+
+class LLWebRTCVoiceClient : public LLSingleton<LLWebRTCVoiceClient>,
+ virtual public LLVoiceModuleInterface,
+ public llwebrtc::LLWebRTCDevicesObserver,
+ public LLMuteListObserver
+{
+ LLSINGLETON_C11(LLWebRTCVoiceClient);
+ LOG_CLASS(LLWebRTCVoiceClient);
+ virtual ~LLWebRTCVoiceClient();
+
+public:
+ /// @name LLVoiceModuleInterface virtual implementations
+ /// @see LLVoiceModuleInterface
+ //@{
+ void init(LLPumpIO *pump) override; // Call this once at application startup (creates connector)
+ void terminate() override; // Call this to clean up during shutdown
+
+ static bool isShuttingDown() { return sShuttingDown; }
+
+ const LLVoiceVersionInfo& getVersion() override;
+
+ void updateSettings() override; // call after loading settings and whenever they change
+
+ // Returns true if WebRTC has successfully logged in and is not in error state
+ bool isVoiceWorking() const override;
+
+ std::string sipURIFromID(const LLUUID &id) override;
+
+ /////////////////////
+ /// @name Tuning
+ //@{
+ void tuningStart() override;
+ void tuningStop() override;
+ bool inTuningMode() override;
+
+ void tuningSetMicVolume(float volume) override;
+ void tuningSetSpeakerVolume(float volume) override;
+ float tuningGetEnergy(void) override;
+ //@}
+
+ /////////////////////
+ /// @name Devices
+ //@{
+ // This returns true when it's safe to bring up the "device settings" dialog in the prefs.
+ bool deviceSettingsAvailable() override;
+ bool deviceSettingsUpdated() override; //return if the list has been updated and never fetched, only to be called from the voicepanel.
+
+ // Requery the WebRTC daemon for the current list of input/output devices.
+ // If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed
+ // (use this if you want to know when it's done).
+ // If you pass false, you'll have no way to know when the query finishes, but the device lists will not appear empty in the interim.
+ void refreshDeviceLists(bool clearCurrentList = true) override;
+
+ void setCaptureDevice(const std::string& name) override;
+ void setRenderDevice(const std::string& name) override;
+
+ LLVoiceDeviceList& getCaptureDevices() override;
+ LLVoiceDeviceList& getRenderDevices() override;
+ //@}
+
+ void getParticipantList(std::set<LLUUID> &participants) override;
+ bool isParticipant(const LLUUID& speaker_id) override;
+
+ // Send a text message to the specified user, initiating the session if necessary.
+ // virtual BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message) const {return false;};
+
+ // Returns true if calling back the session URI after the session has closed is possible.
+ // Currently this will be false only for PSTN P2P calls.
+ // NOTE: this will return true if the session can't be found.
+ BOOL isSessionCallBackPossible(const LLUUID &session_id) override;
+
+ // WebRTC doesn't preclude text im
+ BOOL isSessionTextIMPossible(const LLUUID &session_id) override { return TRUE; }
+
+ ////////////////////////////
+ /// @name Channel stuff
+ //@{
+ // returns true iff the user is currently in a proximal (local spatial) channel.
+ // Note that gestures should only fire if this returns true.
+ bool inProximalChannel() override;
+
+ void setNonSpatialChannel(const LLSD& channelInfo, bool notify_on_first_join, bool hangup_on_last_leave) override
+ {
+ startAdHocSession(channelInfo, notify_on_first_join, hangup_on_last_leave);
+ }
+
+ bool setSpatialChannel(const LLSD &channelInfo) override
+ {
+ // we don't really have credentials for a spatial channel in webrtc,
+ // it's all handled by the sim.
+ return true;
+ }
+
+ void leaveNonSpatialChannel() override;
+
+ void processChannels(bool process) override;
+
+ void leaveChannel(bool stopTalking);
+
+ bool isCurrentChannel(const LLSD &channelInfo) override;
+ bool compareChannels(const LLSD &channelInfo1, const LLSD &channelInfo2) override;
+ //@}
+
+ LLVoiceP2POutgoingCallInterface *getOutgoingCallInterface() override { return nullptr; }
+
+ LLVoiceP2PIncomingCallInterfacePtr getIncomingCallInterface(const LLSD &voice_call_info) override { return nullptr; }
+
+ /////////////////////////
+ /// @name Volume/gain
+ //@{
+ void setVoiceVolume(F32 volume) override;
+ void setMicGain(F32 volume) override;
+ //@}
+
+ /////////////////////////
+ /// @name enable disable voice and features
+ //@{
+ void setVoiceEnabled(bool enabled) override;
+ void setMuteMic(bool muted) override; // Set the mute state of the local mic.
+ //@}
+
+ //////////////////////////
+ /// @name nearby speaker accessors
+ std::string getDisplayName(const LLUUID& id) override;
+ BOOL isParticipantAvatar(const LLUUID &id) override;
+ BOOL getIsSpeaking(const LLUUID& id) override;
+ BOOL getIsModeratorMuted(const LLUUID& id) override;
+ F32 getCurrentPower(const LLUUID& id) override; // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is...
+ F32 getUserVolume(const LLUUID& id) override;
+ void setUserVolume(const LLUUID& id, F32 volume) override; // set's volume for specified agent, from 0-1 (where .5 is nominal)
+ //@}
+
+ //////////////////
+ /// @name LLMuteListObserver
+ //@{
+ void onChange() override;
+ void onChangeDetailed(const LLMute& ) override;
+ //@}
+
+ // authorize the user
+ void userAuthorized(const std::string &user_id, const LLUUID &agentID) override {};
+
+
+ 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();
+
+ //////////////////////////////
+ /// @name Status notification
+ //@{
+ void addObserver(LLVoiceClientStatusObserver* observer) override;
+ void removeObserver(LLVoiceClientStatusObserver* observer) override;
+ void addObserver(LLFriendObserver* observer) override;
+ void removeObserver(LLFriendObserver* observer) override;
+ void addObserver(LLVoiceClientParticipantObserver* observer) override;
+ void removeObserver(LLVoiceClientParticipantObserver* observer) override;
+ //@}
+
+ //////////////////////////////
+ /// @name Devices change notification
+ // LLWebRTCDevicesObserver
+ //@{
+ void OnDevicesChanged(const llwebrtc::LLWebRTCVoiceDeviceList &render_devices,
+ const llwebrtc::LLWebRTCVoiceDeviceList &capture_devices) override;
+ //@}
+
+
+ struct participantState
+ {
+ public:
+ participantState(const LLUUID& agent_id);
+
+ bool isAvatar();
+
+ std::string mURI;
+ LLUUID mAvatarID;
+ std::string mDisplayName;
+ LLFrameTimer mSpeakingTimeout;
+ F32 mLevel; // the current audio level of the participant
+ F32 mVolume; // the gain applied to the participant
+ bool mIsSpeaking;
+ bool mIsModeratorMuted;
+ };
+ typedef boost::shared_ptr<participantState> participantStatePtr_t;
+
+ participantStatePtr_t findParticipantByID(const std::string &channelID, const LLUUID &id);
+ participantStatePtr_t addParticipantByID(const std::string& channelID, const LLUUID &id);
+ void removeParticipantByID(const std::string& channelID, const LLUUID &id);
+
+ protected:
+
+ typedef std::map<const LLUUID, participantStatePtr_t> participantUUIDMap;
+
+ class sessionState
+ {
+ public:
+ typedef boost::shared_ptr<sessionState> ptr_t;
+ typedef boost::weak_ptr<sessionState> wptr_t;
+
+ typedef boost::function<void(const ptr_t &)> sessionFunc_t;
+
+ static void addSession(const std::string &channelID, ptr_t& session);
+ virtual ~sessionState();
+
+ participantStatePtr_t addParticipant(const LLUUID& agent_id);
+ void removeParticipant(const participantStatePtr_t &participant);
+ void removeAllParticipants();
+
+ participantStatePtr_t findParticipantByID(const LLUUID& id);
+
+ static ptr_t matchSessionByChannelID(const std::string& channel_id);
+
+ void shutdownAllConnections();
+ void revive();
+
+ static void processSessionStates();
+
+ virtual bool processConnectionStates();
+
+ virtual void sendData(const std::string &data);
+
+ void setMuteMic(bool muted);
+ void setMicGain(F32 volume);
+ void setSpeakerVolume(F32 volume);
+ void setUserVolume(const LLUUID& id, F32 volume);
+
+ void setUserMute(const LLUUID& id, bool mute);
+
+ static void for_each(sessionFunc_t func);
+
+ static void reapEmptySessions();
+
+ bool isEmpty() { return mWebRTCConnections.empty(); }
+
+ virtual bool isSpatial() = 0;
+ virtual bool isEstate() = 0;
+ virtual bool isCallbackPossible() = 0;
+
+ std::string mHandle;
+ std::string mChannelID;
+ std::string mName;
+
+ bool mMuted; // this session is muted.
+ F32 mMicGain; // gain for this session.
+ F32 mSpeakerVolume; // volume for this session.
+
+ bool mShuttingDown;
+
+ participantUUIDMap mParticipantsByUUID;
+
+ static bool hasSession(const std::string &sessionID)
+ { return mSessions.find(sessionID) != mSessions.end(); }
+
+ bool mHangupOnLastLeave; // notify observers after the session becomes empty.
+ bool mNotifyOnFirstJoin; // notify observers when the first peer joins.
+
+ protected:
+ sessionState();
+ std::list<connectionPtr_t> mWebRTCConnections;
+
+ private:
+
+ static std::map<std::string, ptr_t> mSessions; // canonical list of outstanding sessions.
+
+ static void for_eachPredicate(const std::pair<std::string,
+ LLWebRTCVoiceClient::sessionState::wptr_t> &a,
+ sessionFunc_t func);
+ };
+
+ typedef boost::shared_ptr<sessionState> sessionStatePtr_t;
+ typedef std::map<std::string, sessionStatePtr_t> sessionMap;
+
+ class estateSessionState : public sessionState
+ {
+ public:
+ estateSessionState();
+ bool processConnectionStates() override;
+
+ bool isSpatial() override { return true; }
+ bool isEstate() override { return true; }
+ bool isCallbackPossible() override { return false; }
+ };
+
+ class parcelSessionState : public sessionState
+ {
+ public:
+ parcelSessionState(const std::string& channelID, S32 parcel_local_id);
+
+ bool isSpatial() override { return true; }
+ bool isEstate() override { return false; }
+ bool isCallbackPossible() override { return false; }
+ };
+
+ class adhocSessionState : public sessionState
+ {
+ public:
+ adhocSessionState(const std::string &channelID,
+ const std::string& credentials,
+ bool notify_on_first_join,
+ bool hangup_on_last_leave);
+
+ bool isSpatial() override { return false; }
+ bool isEstate() override { return false; }
+
+ // only p2p-type adhoc sessions allow callback
+ bool isCallbackPossible() override { return mNotifyOnFirstJoin && mHangupOnLastLeave; }
+
+ // don't send spatial data to adhoc sessions.
+ void sendData(const std::string &data) override { }
+
+ protected:
+ std::string mCredentials;
+ };
+
+
+ ///////////////////////////////////////////////////////
+ // Private Member Functions
+ //////////////////////////////////////////////////////
+
+ static void predSendData(const LLWebRTCVoiceClient::sessionStatePtr_t &session, const std::string& spatial_data);
+ static void predUpdateOwnVolume(const LLWebRTCVoiceClient::sessionStatePtr_t &session, F32 audio_level);
+ static void predSetMuteMic(const LLWebRTCVoiceClient::sessionStatePtr_t &session, bool mute);
+ static void predSetMicGain(const LLWebRTCVoiceClient::sessionStatePtr_t &session, F32 volume);
+ static void predSetSpeakerVolume(const LLWebRTCVoiceClient::sessionStatePtr_t &session, F32 volume);
+ static void predShutdownSession(const LLWebRTCVoiceClient::sessionStatePtr_t &session);
+ static void predSetUserMute(const LLWebRTCVoiceClient::sessionStatePtr_t &session, const LLUUID& id, bool mute);
+ static void predSetUserVolume(const LLWebRTCVoiceClient::sessionStatePtr_t &session, const LLUUID& id, F32 volume);
+
+ //----------------------------------
+ // devices
+ void clearCaptureDevices();
+ void addCaptureDevice(const LLVoiceDevice& device);
+
+ void clearRenderDevices();
+ void addRenderDevice(const LLVoiceDevice& device);
+ void setDevicesListUpdated(bool state);
+
+ /////////////////////////////
+ // Sending updates of current state
+ void updatePosition(void);
+ void setListenerPosition(const LLVector3d &position, const LLVector3 &velocity, const LLQuaternion &rot);
+ void setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLQuaternion &rot);
+
+ LLVector3d getListenerPosition() { return mListenerPosition; }
+ LLVector3d getSpeakerPosition() { return mAvatarPosition; }
+
+ void setEarLocation(S32 loc);
+
+
+ /////////////////////////////
+ // Accessors for data related to nearby speakers
+
+ /////////////////////////////
+ sessionStatePtr_t findP2PSession(const LLUUID &agent_id);
+
+ sessionStatePtr_t addSession(const std::string &channel_id, sessionState::ptr_t session);
+ void deleteSession(const sessionStatePtr_t &session);
+
+ // Does the actual work to get out of the audio session
+ void leaveAudioSession();
+
+ friend class LLWebRTCVoiceClientCapResponder;
+
+
+ void lookupName(const LLUUID &id);
+ void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
+ void avatarNameResolved(const LLUUID &id, const std::string &name);
+ static void predAvatarNameResolution(const LLWebRTCVoiceClient::sessionStatePtr_t &session, LLUUID id, std::string name);
+
+ boost::signals2::connection mAvatarNameCacheConnection;
+
+private:
+
+ // helper function to retrieve the audio level
+ // Used in multiple places.
+ float getAudioLevel();
+
+ // Coroutine support methods
+ //---
+ void voiceConnectionCoro();
+
+ //---
+ /// Clean up objects created during a voice session.
+ void cleanUp();
+
+ bool mTuningMode;
+ F32 mTuningMicGain;
+ int mTuningSpeakerVolume;
+ bool mDevicesListUpdated; // set to true when the device list has been updated
+ // and false when the panelvoicedevicesettings has queried for an update status.
+ std::string mSpatialSessionCredentials;
+
+ std::string mMainSessionGroupHandle; // handle of the "main" session group.
+
+ sessionStatePtr_t mSession; // Session state for the current session
+
+ sessionStatePtr_t mNextSession; // Session state for the session we're trying to join
+
+ llwebrtc::LLWebRTCDeviceInterface *mWebRTCDeviceInterface;
+
+ LLVoiceDeviceList mCaptureDevices;
+ LLVoiceDeviceList mRenderDevices;
+
+ bool startEstateSession();
+ bool startParcelSession(const std::string& channelID, S32 parcelID);
+ bool startAdHocSession(const LLSD &channelInfo, bool notify_on_first_join, bool hangup_on_last_leave);
+
+ bool inSpatialChannel();
+ bool inOrJoiningChannel(const std::string &channelID);
+ bool inEstateChannel();
+
+ LLSD getAudioSessionChannelInfo();
+
+ void setHidden(bool hidden) override; //virtual
+
+ void enforceTether();
+
+ void updateNeighboringRegions();
+ std::set<LLUUID> getNeighboringRegions() { return mNeighboringRegions; }
+
+ LLVoiceVersionInfo mVoiceVersion;
+
+ bool mSpatialCoordsDirty;
+
+ LLVector3d mListenerPosition;
+ LLVector3d mListenerRequestedPosition;
+ LLVector3 mListenerVelocity;
+ LLQuaternion mListenerRot;
+
+ LLVector3d mAvatarPosition;
+ LLVector3 mAvatarVelocity;
+ LLQuaternion mAvatarRot;
+
+ std::set<LLUUID> mNeighboringRegions; // includes current region
+
+ bool mMuteMic;
+ bool mHidden; //Set to true during teleport to hide the agent's position.
+
+ enum
+ {
+ earLocCamera = 0, // ear at camera
+ earLocAvatar, // ear at avatar
+ earLocMixed // ear at avatar location/camera direction
+ };
+
+ S32 mEarLocation;
+
+ float mSpeakerVolume;
+
+ F32 mMicGain;
+
+ bool mVoiceEnabled;
+ bool mProcessChannels;
+
+ typedef std::set<LLVoiceClientParticipantObserver*> observer_set_t;
+ observer_set_t mParticipantObservers;
+
+ void notifyParticipantObservers();
+
+ typedef std::set<LLVoiceClientStatusObserver*> status_observer_set_t;
+ status_observer_set_t mStatusObservers;
+
+ void notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status);
+
+ bool mIsInTuningMode;
+ bool mIsProcessingChannels;
+ bool mIsCoroutineActive;
+
+ // These variables can last longer than WebRTC in coroutines so we need them as static
+ static bool sShuttingDown;
+
+ LLEventMailDrop mWebRTCPump;
+};
+
+
+class LLVoiceWebRTCStats : public LLSingleton<LLVoiceWebRTCStats>
+{
+ LLSINGLETON(LLVoiceWebRTCStats);
+ LOG_CLASS(LLVoiceWebRTCStats);
+ virtual ~LLVoiceWebRTCStats();
+
+ private:
+ F64SecondsImplicit mStartTime;
+
+ U32 mConnectCycles;
+
+ F64 mConnectTime;
+ U32 mConnectAttempts;
+
+ F64 mProvisionTime;
+ U32 mProvisionAttempts;
+
+ F64 mEstablishTime;
+ U32 mEstablishAttempts;
+
+ public:
+
+ void reset();
+ void connectionAttemptStart();
+ void connectionAttemptEnd(bool success);
+ void provisionAttemptStart();
+ void provisionAttemptEnd(bool success);
+ void establishAttemptStart();
+ void establishAttemptEnd(bool success);
+ LLSD read();
+};
+
+class LLVoiceWebRTCConnection :
+ public llwebrtc::LLWebRTCSignalingObserver,
+ public llwebrtc::LLWebRTCDataObserver
+{
+ public:
+ LLVoiceWebRTCConnection(const LLUUID &regionID, const std::string &channelID);
+
+ virtual ~LLVoiceWebRTCConnection() = 0;
+
+ //////////////////////////////
+ /// @name Signaling notification
+ // LLWebRTCSignalingObserver
+ //@{
+ void OnIceGatheringState(EIceGatheringState 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 OnPeerConnectionShutdown() override;
+ //@}
+
+ /////////////////////////
+ /// @name Data Notification
+ /// LLWebRTCDataObserver
+ //@{
+ void OnDataReceived(const std::string &data, bool binary) override;
+ void OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface) override;
+ //@}
+
+ void sendJoin();
+ void sendData(const std::string &data);
+
+ 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);
+
+ virtual void setMuteMic(bool muted);
+ virtual void setMicGain(F32 volume);
+ virtual void setSpeakerVolume(F32 volume);
+
+ void setUserVolume(const LLUUID& id, F32 volume);
+ void setUserMute(const LLUUID& id, bool mute);
+
+ bool connectionStateMachine();
+
+ virtual bool isSpatial() = 0;
+
+ LLUUID getRegionID() { return mRegionID; }
+
+ void shutDown()
+ {
+ LLMutexLock lock(&mVoiceStateMutex);
+ mShutDown = true;
+ }
+
+ 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_WAIT_FOR_DATA_CHANNEL = 0x20,
+ VOICE_STATE_SESSION_UP = 0x40,
+ VOICE_STATE_SESSION_RETRY = 0x80,
+ VOICE_STATE_DISCONNECT = 0x100,
+ VOICE_STATE_WAIT_FOR_EXIT = 0x200,
+ VOICE_STATE_SESSION_EXIT = 0x400,
+ VOICE_STATE_SESSION_STOPPING = 0x780
+ } EVoiceConnectionState;
+
+ EVoiceConnectionState mVoiceConnectionState;
+ 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.
+ mVoiceConnectionState = new_voice_connection_state;
+ return;
+ }
+ if (mVoiceConnectionState & VOICE_STATE_SESSION_STOPPING)
+ {
+ // we're currently shutting down or restarting, so ignore any
+ // state changes.
+ return;
+ }
+
+ mVoiceConnectionState = new_voice_connection_state;
+ }
+ EVoiceConnectionState getVoiceConnectionState()
+ {
+ 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;
+
+ bool mMuted;
+ F32 mMicGain;
+ F32 mSpeakerVolume;
+
+ bool mShutDown;
+ S32 mOutstandingRequests;
+
+ std::vector<llwebrtc::LLWebRTCIceCandidate> mIceCandidates;
+ bool mIceCompleted;
+ bool mTrickling;
+
+ llwebrtc::LLWebRTCPeerConnectionInterface *mWebRTCPeerConnectionInterface;
+ llwebrtc::LLWebRTCAudioInterface *mWebRTCAudioInterface;
+ 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;
+
+ bool isSpatial() override { return true; }
+
+
+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();
+
+ bool isSpatial() override { return false; }
+
+ protected:
+ bool requestVoiceConnection() override;
+
+ std::string mCredentials;
+};
+
+#define VOICE_ELAPSED LLVoiceTimer(__FUNCTION__);
+
+#endif //LL_WebRTC_VOICE_CLIENT_H
+