diff options
Diffstat (limited to 'indra/newview/llvoiceclient.h')
-rw-r--r-- | indra/newview/llvoiceclient.h | 1015 |
1 files changed, 347 insertions, 668 deletions
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index a96cf18e27..3fa82105a3 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -17,8 +17,7 @@ * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -33,7 +32,6 @@ #define LL_VOICE_CLIENT_H class LLVOAvatar; -class LLVivoxProtocolParser; #include "lliopipe.h" #include "llpumpio.h" @@ -42,9 +40,14 @@ class LLVivoxProtocolParser; #include "v3math.h" #include "llframetimer.h" #include "llviewerregion.h" -#include "m3math.h" // LLMatrix3 +#include "llcallingcard.h" // for LLFriendObserver +#include "llsecapi.h" + +// devices + +typedef std::vector<std::string> LLVoiceDeviceList; + -class LLFriendObserver; class LLVoiceClientParticipantObserver { public: @@ -52,6 +55,9 @@ public: virtual void onChange() = 0; }; + +/////////////////////////////////// +/// @class LLVoiceClientStatusObserver class LLVoiceClientStatusObserver { public: @@ -65,11 +71,7 @@ public: STATUS_JOINED, STATUS_LEFT_CHANNEL, STATUS_VOICE_DISABLED, - - // Adding STATUS_VOICE_ENABLED as pair status for STATUS_VOICE_DISABLED - // See LLVoiceClient::setVoiceEnabled() STATUS_VOICE_ENABLED, - BEGIN_ERROR_STATUS, ERROR_CHANNEL_FULL, ERROR_CHANNEL_LOCKED, @@ -83,690 +85,367 @@ public: static std::string status2string(EStatusType inStatus); }; -class LLVoiceClient: public LLSingleton<LLVoiceClient> +struct LLVoiceVersionInfo { - LOG_CLASS(LLVoiceClient); - public: - LLVoiceClient(); - ~LLVoiceClient(); - - public: - static void init(LLPumpIO *pump); // Call this once at application startup (creates connector) - static void terminate(); // Call this to clean up during shutdown - - protected: - bool writeString(const std::string &str); - - public: - - static F32 OVERDRIVEN_POWER_LEVEL; - - void updateSettings(); // call after loading settings and whenever they change - - void getCaptureDevicesSendMessage(); - void getRenderDevicesSendMessage(); - - void clearCaptureDevices(); - void addCaptureDevice(const std::string& name); - void setCaptureDevice(const std::string& name); - - void clearRenderDevices(); - void addRenderDevice(const std::string& name); - void setRenderDevice(const std::string& name); - - void tuningStart(); - void tuningStop(); - bool inTuningMode(); - bool inTuningStates(); - - void tuningRenderStartSendMessage(const std::string& name, bool loop); - void tuningRenderStopSendMessage(); - - void tuningCaptureStartSendMessage(int duration); - void tuningCaptureStopSendMessage(); - - void tuningSetMicVolume(float volume); - void tuningSetSpeakerVolume(float volume); - float tuningGetEnergy(void); - - // This returns true when it's safe to bring up the "device settings" dialog in the prefs. - // i.e. when the daemon is running and connected, and the device lists are populated. - bool deviceSettingsAvailable(); - - // Requery the vivox 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); - - // Call this if the connection to the daemon terminates unexpectedly. It will attempt to reset everything and relaunch. - void daemonDied(); - - // Call this if we're just giving up on voice (can't provision an account, etc.). It will clean up and go away. - void giveUp(); - - ///////////////////////////// - // Response/Event handlers - void connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID); - void loginResponse(int statusCode, std::string &statusString, std::string &accountHandle, int numberOfAliases); - void sessionCreateResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle); - void sessionGroupAddSessionResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle); - void sessionConnectResponse(std::string &requestId, int statusCode, std::string &statusString); - void logoutResponse(int statusCode, std::string &statusString); - void connectorShutdownResponse(int statusCode, std::string &statusString); - - void accountLoginStateChangeEvent(std::string &accountHandle, int statusCode, std::string &statusString, int state); - void mediaStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, int statusCode, std::string &statusString, int state, bool incoming); - void textStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, bool enabled, int state, bool incoming); - void sessionAddedEvent(std::string &uriString, std::string &alias, std::string &sessionHandle, std::string &sessionGroupHandle, bool isChannel, bool incoming, std::string &nameString, std::string &applicationString); - void sessionGroupAddedEvent(std::string &sessionGroupHandle); - void sessionRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle); - void participantAddedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString, std::string &displayNameString, int participantType); - void participantRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString); - void participantUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, bool isModeratorMuted, bool isSpeaking, int volume, F32 energy); - void auxAudioPropertiesEvent(F32 energy); - void buddyPresenceEvent(std::string &uriString, std::string &alias, std::string &statusString, std::string &applicationString); - void messageEvent(std::string &sessionHandle, std::string &uriString, std::string &alias, std::string &messageHeader, std::string &messageBody, std::string &applicationString); - void sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string ¬ificationType); - void subscriptionEvent(std::string &buddyURI, std::string &subscriptionHandle, std::string &alias, std::string &displayName, std::string &applicationString, std::string &subscriptionType); - - void buddyListChanged(); - void muteListChanged(); - void updateFriends(U32 mask); - - ///////////////////////////// - // Sending updates of current state -static void updatePosition(void); - void setCameraPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot); - void setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot); - bool channelFromRegion(LLViewerRegion *region, std::string &name); - void leaveChannel(void); // call this on logout or teleport begin - - - void setMuteMic(bool muted); // Use this to mute the local mic (for when the client is minimized, etc), ignoring user PTT state. - bool getMuteMic() const; - void setUserPTTState(bool ptt); - bool getUserPTTState(); - void toggleUserPTTState(void); - void inputUserControlState(bool down); // interpret any sort of up-down mic-open control input according to ptt-toggle prefs - void setVoiceEnabled(bool enabled); - static bool voiceEnabled(); - // Checks is voice working judging from mState - // Returns true if vivox has successfully logged in and is not in error state - bool voiceWorking(); - void setUsePTT(bool usePTT); - void setPTTIsToggle(bool PTTIsToggle); - bool getPTTIsToggle(); - void setPTTKey(std::string &key); - void setEarLocation(S32 loc); - void setVoiceVolume(F32 volume); - void setMicGain(F32 volume); - void setUserVolume(const LLUUID& id, F32 volume); // sets volume for specified agent, from 0-1 (where .5 is nominal) - void setLipSyncEnabled(BOOL enabled); - BOOL lipSyncEnabled(); - - // PTT key triggering - void keyDown(KEY key, MASK mask); - void keyUp(KEY key, MASK mask); - void middleMouseState(bool down); - - // Return the version of the Vivox library - std::string getAPIVersion() const { return mAPIVersion; } - - ///////////////////////////// - // Accessors for data related to nearby speakers - BOOL getVoiceEnabled(const LLUUID& id); // true if we've received data for this avatar - BOOL getIsSpeaking(const LLUUID& id); - BOOL getIsModeratorMuted(const LLUUID& id); - F32 getCurrentPower(const LLUUID& id); // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is... - BOOL getOnMuteList(const LLUUID& id); - F32 getUserVolume(const LLUUID& id); - std::string getDisplayName(const LLUUID& id); - - // MBW -- XXX -- Not sure how to get this data out of the TVC - BOOL getUsingPTT(const LLUUID& id); - std::string getGroupID(const LLUUID& id); // group ID if the user is in group chat (empty string if not applicable) + std::string serverType; + std::string serverVersion; +}; - ///////////////////////////// - BOOL getAreaVoiceDisabled(); // returns true if the area the avatar is in is speech-disabled. - // Use this to determine whether to show a "no speech" icon in the menu bar. - - ///////////////////////////// - // Recording controls - void recordingLoopStart(int seconds = 3600, int deltaFramesPerControlFrame = 200); - void recordingLoopSave(const std::string& filename); - void recordingStop(); - - // Playback controls - void filePlaybackStart(const std::string& filename); - void filePlaybackStop(); - void filePlaybackSetPaused(bool paused); - void filePlaybackSetMode(bool vox = false, float speed = 1.0f); - - - // This is used by the string-keyed maps below, to avoid storing the string twice. - // The 'const std::string *' in the key points to a string actually stored in the object referenced by the map. - // The add and delete operations for each map allocate and delete in the right order to avoid dangling references. - // The default compare operation would just compare pointers, which is incorrect, so they must use this comparitor instead. - struct stringMapComparitor - { - bool operator()(const std::string* a, const std::string * b) const - { - return a->compare(*b) < 0; - } - }; - - struct uuidMapComparitor - { - bool operator()(const LLUUID* a, const LLUUID * b) const - { - return *a < *b; - } - }; - - struct participantState - { - public: - participantState(const std::string &uri); - - bool updateMuteState(); - bool isAvatar(); - - std::string mURI; - LLUUID mAvatarID; - std::string mAccountName; - std::string mDisplayName; - LLFrameTimer mSpeakingTimeout; - F32 mLastSpokeTimestamp; - F32 mPower; - int mVolume; - std::string mGroupID; - int mUserVolume; - bool mPTT; - bool mIsSpeaking; - bool mIsModeratorMuted; - bool mOnMuteList; // true if this avatar is on the user's mute list (and should be muted) - bool mVolumeDirty; // true if this participant needs a volume command sent (either mOnMuteList or mUserVolume has changed) - bool mAvatarIDValid; - bool mIsSelf; - }; - typedef std::map<const std::string *, participantState*, stringMapComparitor> participantMap; - - typedef std::map<const LLUUID *, participantState*, uuidMapComparitor> participantUUIDMap; - - enum streamState - { - streamStateUnknown = 0, - streamStateIdle = 1, - streamStateConnected = 2, - streamStateRinging = 3, - }; - - struct sessionState - { - public: - sessionState(); - ~sessionState(); - - participantState *addParticipant(const std::string &uri); - // Note: after removeParticipant returns, the participant* that was passed to it will have been deleted. - // Take care not to use the pointer again after that. - void removeParticipant(participantState *participant); - void removeAllParticipants(); - - participantState *findParticipant(const std::string &uri); - participantState *findParticipantByID(const LLUUID& id); - - bool isCallBackPossible(); - bool isTextIMPossible(); - - std::string mHandle; - std::string mGroupHandle; - std::string mSIPURI; - std::string mAlias; - std::string mName; - std::string mAlternateSIPURI; - std::string mHash; // Channel password - std::string mErrorStatusString; - std::queue<std::string> mTextMsgQueue; - - LLUUID mIMSessionID; - LLUUID mCallerID; - int mErrorStatusCode; - int mMediaStreamState; - int mTextStreamState; - bool mCreateInProgress; // True if a Session.Create has been sent for this session and no response has been received yet. - bool mMediaConnectInProgress; // True if a Session.MediaConnect has been sent for this session and no response has been received yet. - bool mVoiceInvitePending; // True if a voice invite is pending for this session (usually waiting on a name lookup) - bool mTextInvitePending; // True if a text invite is pending for this session (usually waiting on a name lookup) - bool mSynthesizedCallerID; // True if the caller ID is a hash of the SIP URI -- this means we shouldn't do a name lookup. - bool mIsChannel; // True for both group and spatial channels (false for p2p, PSTN) - bool mIsSpatial; // True for spatial channels - bool mIsP2P; - bool mIncoming; - bool mVoiceEnabled; - bool mReconnect; // Whether we should try to reconnect to this session if it's dropped - // Set to true when the mute state of someone in the participant list changes. - // The code will have to walk the list to find the changed participant(s). - bool mVolumeDirty; - - bool mParticipantsChanged; - participantMap mParticipantsByURI; - participantUUIDMap mParticipantsByUUID; - }; - - participantState *findParticipantByID(const LLUUID& id); - participantMap *getParticipantList(void); - void getParticipantsUUIDSet(std::set<LLUUID>& participant_uuids); - - typedef std::map<const std::string*, sessionState*, stringMapComparitor> sessionMap; - typedef std::set<sessionState*> sessionSet; - - typedef sessionSet::iterator sessionIterator; - sessionIterator sessionsBegin(void); - sessionIterator sessionsEnd(void); - - sessionState *findSession(const std::string &handle); - sessionState *findSessionBeingCreatedByURI(const std::string &uri); - sessionState *findSession(const LLUUID &participant_id); - sessionState *findSessionByCreateID(const std::string &create_id); - - sessionState *addSession(const std::string &uri, const std::string &handle = LLStringUtil::null); - void setSessionHandle(sessionState *session, const std::string &handle = LLStringUtil::null); - void setSessionURI(sessionState *session, const std::string &uri); - void deleteSession(sessionState *session); - void deleteAllSessions(void); +////////////////////////////////// +/// @class LLVoiceModuleInterface +/// @brief Voice module interface +/// +/// Voice modules should provide an implementation for this interface. +///////////////////////////////// - void verifySessionState(void); +class LLVoiceModuleInterface +{ +public: + LLVoiceModuleInterface() {} + virtual ~LLVoiceModuleInterface() {} + + virtual void init(LLPumpIO *pump)=0; // Call this once at application startup (creates connector) + virtual void terminate()=0; // Call this to clean up during shutdown + + virtual void updateSettings()=0; // call after loading settings and whenever they change + + virtual bool isVoiceWorking()=0; // connected to a voice server and voice channel - void joinedAudioSession(sessionState *session); - void leftAudioSession(sessionState *session); + virtual const LLVoiceVersionInfo& getVersion()=0; + + ///////////////////// + /// @name Tuning + //@{ + virtual void tuningStart()=0; + virtual void tuningStop()=0; + virtual bool inTuningMode()=0; + + virtual void tuningSetMicVolume(float volume)=0; + virtual void tuningSetSpeakerVolume(float volume)=0; + virtual float tuningGetEnergy(void)=0; + //@} + + ///////////////////// + /// @name Devices + //@{ + // This returns true when it's safe to bring up the "device settings" dialog in the prefs. + // i.e. when the daemon is running and connected, and the device lists are populated. + virtual bool deviceSettingsAvailable()=0; + + // Requery the vivox 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. + virtual void refreshDeviceLists(bool clearCurrentList = true)=0; + + virtual void setCaptureDevice(const std::string& name)=0; + virtual void setRenderDevice(const std::string& name)=0; + + virtual LLVoiceDeviceList& getCaptureDevices()=0; + virtual LLVoiceDeviceList& getRenderDevices()=0; + + virtual void getParticipantList(std::set<LLUUID> &participants)=0; + virtual bool isParticipant(const LLUUID& speaker_id)=0; + //@} + + //////////////////////////// + /// @ 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. + virtual bool inProximalChannel()=0; + + virtual void setNonSpatialChannel(const std::string &uri, + const std::string &credentials)=0; + + virtual void setSpatialChannel(const std::string &uri, + const std::string &credentials)=0; + + virtual void leaveNonSpatialChannel()=0; + + virtual void leaveChannel(void)=0; + + // Returns the URI of the current channel, or an empty string if not currently in a channel. + // NOTE that it will return an empty string if it's in the process of joining a channel. + virtual std::string getCurrentChannel()=0; + //@} + + + ////////////////////////// + /// @name invitations + //@{ + // start a voice channel with the specified user + virtual void callUser(const LLUUID &uuid)=0; + virtual bool answerInvite(std::string &channelHandle)=0; + virtual void declineInvite(std::string &channelHandle)=0; + //@} + + ///////////////////////// + /// @name Volume/gain + //@{ + virtual void setVoiceVolume(F32 volume)=0; + virtual void setMicGain(F32 volume)=0; + //@} + + ///////////////////////// + /// @name enable disable voice and features + //@{ + virtual bool voiceEnabled()=0; + virtual void setVoiceEnabled(bool enabled)=0; + virtual void setLipSyncEnabled(BOOL enabled)=0; + virtual BOOL lipSyncEnabled()=0; + virtual void setMuteMic(bool muted)=0; // Use this to mute the local mic (for when the client is minimized, etc), ignoring user PTT state. + //@} + + //////////////////////// + /// @name PTT + //@{ + virtual void setUserPTTState(bool ptt)=0; + virtual bool getUserPTTState()=0; + virtual void setUsePTT(bool usePTT)=0; + virtual void setPTTIsToggle(bool PTTIsToggle)=0; + virtual bool getPTTIsToggle()=0; + virtual void toggleUserPTTState(void)=0; + virtual void inputUserControlState(bool down)=0; // interpret any sort of up-down mic-open control input according to ptt-toggle prefs + + virtual void keyDown(KEY key, MASK mask)=0; + virtual void keyUp(KEY key, MASK mask)=0; + virtual void middleMouseState(bool down)=0; + //@} + + ////////////////////////// + /// @name nearby speaker accessors + //@{ + + + virtual BOOL getVoiceEnabled(const LLUUID& id)=0; // true if we've received data for this avatar + virtual std::string getDisplayName(const LLUUID& id)=0; + virtual BOOL isOnlineSIP(const LLUUID &id)=0; + virtual BOOL isParticipantAvatar(const LLUUID &id)=0; + virtual BOOL getIsSpeaking(const LLUUID& id)=0; + virtual BOOL getIsModeratorMuted(const LLUUID& id)=0; + virtual F32 getCurrentPower(const LLUUID& id)=0; // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is... + virtual BOOL getOnMuteList(const LLUUID& id)=0; + virtual F32 getUserVolume(const LLUUID& id)=0; + virtual void setUserVolume(const LLUUID& id, F32 volume)=0; // set's volume for specified agent, from 0-1 (where .5 is nominal) + //@} + + ////////////////////////// + /// @name text chat + //@{ + virtual BOOL isSessionTextIMPossible(const LLUUID& id)=0; + virtual BOOL isSessionCallBackPossible(const LLUUID& id)=0; + virtual BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message)=0; + virtual void endUserIMSession(const LLUUID &uuid)=0; + //@} + + // authorize the user + virtual void userAuthorized(const std::string& user_id, + const LLUUID &agentID)=0; + + ////////////////////////////// + /// @name Status notification + //@{ + virtual void addObserver(LLVoiceClientStatusObserver* observer)=0; + virtual void removeObserver(LLVoiceClientStatusObserver* observer)=0; + virtual void addObserver(LLFriendObserver* observer)=0; + virtual void removeObserver(LLFriendObserver* observer)=0; + virtual void addObserver(LLVoiceClientParticipantObserver* observer)=0; + virtual void removeObserver(LLVoiceClientParticipantObserver* observer)=0; + //@} + + virtual std::string sipURIFromID(const LLUUID &id)=0; + //@} + +}; - // This is called in several places where the session _may_ need to be deleted. - // It contains logic for whether to delete the session or keep it around. - void reapSession(sessionState *session); - - // Returns true if the session seems to indicate we've moved to a region on a different voice server - bool sessionNeedsRelog(sessionState *session); - - 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 mInVivoxBuddies; - bool mNeedsNameUpdate; - }; - - typedef std::map<const std::string*, buddyListEntry*, stringMapComparitor> buddyListMap; - - // This should be called when parsing a buddy list entry sent by SLVoice. - void processBuddyListEntry(const std::string &uri, const std::string &displayName); - - buddyListEntry *addBuddy(const std::string &uri); - buddyListEntry *addBuddy(const std::string &uri, const std::string &displayName); - buddyListEntry *findBuddy(const std::string &uri); - buddyListEntry *findBuddy(const LLUUID &id); - buddyListEntry *findBuddyByDisplayName(const std::string &name); - void deleteBuddy(const std::string &uri); - void deleteAllBuddies(void); - - void deleteAllBlockRules(void); - void addBlockRule(const std::string &blockMask, const std::string &presenceOnly); - void deleteAllAutoAcceptRules(void); - void addAutoAcceptRule(const std::string &autoAcceptMask, const std::string &autoAddAsBuddy); - void accountListBlockRulesResponse(int statusCode, const std::string &statusString); - void accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString); - - ///////////////////////////// - // session control messages - void connectorCreate(); - void connectorShutdown(); - - void requestVoiceAccountProvision(S32 retries = 3); - void userAuthorized( - const std::string& firstName, - const std::string& lastName, - const LLUUID &agentID); - void login( - const std::string& account_name, - const std::string& password, - const std::string& voice_sip_uri_hostname, - const std::string& voice_account_server_uri); - void loginSendMessage(); - void logout(); - void logoutSendMessage(); - - void accountListBlockRulesSendMessage(); - void accountListAutoAcceptRulesSendMessage(); - - void sessionGroupCreateSendMessage(); - void sessionCreateSendMessage(sessionState *session, bool startAudio = true, bool startText = false); - void sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio = true, bool startText = false); - void sessionMediaConnectSendMessage(sessionState *session); // just joins the audio session - void sessionTextConnectSendMessage(sessionState *session); // just joins the text session - void sessionTerminateSendMessage(sessionState *session); - void sessionGroupTerminateSendMessage(sessionState *session); - void sessionMediaDisconnectSendMessage(sessionState *session); - void sessionTextDisconnectSendMessage(sessionState *session); - - // Pokes the state machine to leave the audio session next time around. - void sessionTerminate(); - - // Pokes the state machine to shut down the connector and restart it. - void requestRelog(); - - // Does the actual work to get out of the audio session - void leaveAudioSession(); - - void addObserver(LLVoiceClientParticipantObserver* observer); - void removeObserver(LLVoiceClientParticipantObserver* observer); - void addObserver(LLVoiceClientStatusObserver* observer); - void removeObserver(LLVoiceClientStatusObserver* observer); +class LLVoiceClient: public LLSingleton<LLVoiceClient> +{ + LOG_CLASS(LLVoiceClient); +public: + LLVoiceClient(); + ~LLVoiceClient(); - void addObserver(LLFriendObserver* observer); - void removeObserver(LLFriendObserver* observer); - - void lookupName(const LLUUID &id); - static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group); - void avatarNameResolved(const LLUUID &id, const std::string &name); - - typedef std::vector<std::string> deviceList; + void init(LLPumpIO *pump); // Call this once at application startup (creates connector) + void terminate(); // Call this to clean up during shutdown + + const LLVoiceVersionInfo getVersion(); + +static const F32 OVERDRIVEN_POWER_LEVEL; - deviceList *getCaptureDevices(); - deviceList *getRenderDevices(); - - void setNonSpatialChannel( - const std::string &uri, - const std::string &credentials); - void setSpatialChannel( - const std::string &uri, - const std::string &credentials); - // start a voice session with the specified user - void callUser(const LLUUID &uuid); - - // Send a text message to the specified user, initiating the session if necessary. - bool sendTextMessage(const LLUUID& participant_id, const std::string& message); - - // close any existing text IM session with the specified user - void endUserIMSession(const LLUUID &uuid); - - bool answerInvite(std::string &sessionHandle); - void declineInvite(std::string &sessionHandle); - void leaveNonSpatialChannel(); + void updateSettings(); // call after loading settings and whenever they change - // Returns the URI of the current channel, or an empty string if not currently in a channel. - // NOTE that it will return an empty string if it's in the process of joining a channel. - std::string getCurrentChannel(); - - // 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(); + bool isVoiceWorking(); // connected to a voice server and voice channel - std::string sipURIFromID(const LLUUID &id); - - // Returns true if the indicated user is online via SIP presence according to SLVoice. - // Note that we only get SIP presence data for other users that are in our vivox buddy list. - bool isOnlineSIP(const LLUUID &id); - - // Returns true if the indicated participant is really an SL avatar. - // This should be used to control the state of the "profile" button. - // Currently this will be false only for PSTN callers into group chats, and PSTN p2p calls. - bool isParticipantAvatar(const LLUUID &id); - - // 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); + // tuning + void tuningStart(); + void tuningStop(); + bool inTuningMode(); - // Returns true if the session can accepte text IM's. - // Currently this will be false only for PSTN P2P calls. - // NOTE: this will return true if the session can't be found. - bool isSessionTextIMPossible(const LLUUID &session_id); - - private: - - // internal state for a simple state machine. This is used to deal with the asynchronous nature of some of the messages. - // Note: if you change this list, please make corresponding changes to LLVoiceClient::state2string(). - enum state - { - stateDisableCleanup, - stateDisabled, // Voice is turned off. - stateStart, // Class is initialized, socket is created - stateDaemonLaunched, // Daemon has been launched - stateConnecting, // connect() call has been issued - stateConnected, // connection to the daemon has been made, send some initial setup commands. - stateIdle, // socket is connected, ready for messaging - stateMicTuningStart, - stateMicTuningRunning, - stateMicTuningStop, - stateConnectorStart, // connector needs to be started - stateConnectorStarting, // waiting for connector handle - stateConnectorStarted, // connector handle received - stateLoginRetry, // need to retry login (failed due to changing password) - stateLoginRetryWait, // waiting for retry timer - stateNeedsLogin, // send login request - stateLoggingIn, // waiting for account handle - stateLoggedIn, // account handle received - stateCreatingSessionGroup, // Creating the main session group - stateNoChannel, // - stateJoiningSession, // waiting for session handle - stateSessionJoined, // session handle received - stateRunning, // in session, steady state - stateLeavingSession, // waiting for terminate session response - stateSessionTerminated, // waiting for terminate session response - - stateLoggingOut, // waiting for logout response - stateLoggedOut, // logout response received - stateConnectorStopping, // waiting for connector stop - stateConnectorStopped, // connector stop received - - // We go to this state if the login fails because the account needs to be provisioned. - - // error states. No way to recover from these yet. - stateConnectorFailed, - stateConnectorFailedWaiting, - stateLoginFailed, - stateLoginFailedWaiting, - stateJoinSessionFailed, - stateJoinSessionFailedWaiting, - - stateJail // Go here when all else has failed. Nothing will be retried, we're done. - }; - - state mState; - bool mSessionTerminateRequested; - bool mRelogRequested; - - void setState(state inState); - state getState(void) { return mState; }; - static std::string state2string(state inState); - - void stateMachine(); - static void idle(void *user_data); - - LLHost mDaemonHost; - LLSocket::ptr_t mSocket; - bool mConnected; - - void closeSocket(void); - - LLPumpIO *mPump; - friend class LLVivoxProtocolParser; - - std::string mAccountName; - std::string mAccountPassword; - std::string mAccountDisplayName; - std::string mAccountFirstName; - std::string mAccountLastName; + void tuningSetMicVolume(float volume); + void tuningSetSpeakerVolume(float volume); + float tuningGetEnergy(void); - bool mTuningMode; - float mTuningEnergy; - std::string mTuningAudioFile; - int mTuningMicVolume; - bool mTuningMicVolumeDirty; - int mTuningSpeakerVolume; - bool mTuningSpeakerVolumeDirty; - state mTuningExitState; // state to return to when we leave tuning mode. + // devices + + // This returns true when it's safe to bring up the "device settings" dialog in the prefs. + // i.e. when the daemon is running and connected, and the device lists are populated. + bool deviceSettingsAvailable(); - std::string mSpatialSessionURI; - std::string mSpatialSessionCredentials; + // Requery the vivox 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); - std::string mMainSessionGroupHandle; // handle of the "main" session group. - - std::string mChannelName; // Name of the channel to be looked up - bool mAreaVoiceDisabled; - sessionState *mAudioSession; // Session state for the current audio session - bool mAudioSessionChanged; // set to true when the above pointer gets changed, so observers can be notified. + void setCaptureDevice(const std::string& name); + void setRenderDevice(const std::string& name); - sessionState *mNextAudioSession; // Session state for the audio session we're trying to join + const LLVoiceDeviceList& getCaptureDevices(); + const LLVoiceDeviceList& getRenderDevices(); -// std::string mSessionURI; // URI of the session we're in. -// std::string mSessionHandle; // returned by ? - - S32 mCurrentParcelLocalID; // Used to detect parcel boundary crossings - std::string mCurrentRegionName; // Used to detect parcel boundary crossings - - std::string mConnectorHandle; // returned by "Create Connector" message - std::string mAccountHandle; // returned by login message - int mNumberOfAliases; - U32 mCommandCookie; + //////////////////////////// + // 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(); + void setNonSpatialChannel( + const std::string &uri, + const std::string &credentials); + void setSpatialChannel( + const std::string &uri, + const std::string &credentials); + void leaveNonSpatialChannel(); + + // Returns the URI of the current channel, or an empty string if not currently in a channel. + // 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 + void callUser(const LLUUID &uuid); + bool answerInvite(std::string &channelHandle); + void declineInvite(std::string &channelHandle); + void leaveChannel(void); // call this on logout or teleport begin + + + ///////////////////////////// + // Sending updates of current state - std::string mVoiceAccountServerURI; - std::string mVoiceSIPURIHostName; - - int mLoginRetryCount; - - sessionMap mSessionsByHandle; // Active sessions, indexed by session handle. Sessions which are being initiated may not be in this map. - sessionSet mSessions; // All sessions, not indexed. This is the canonical session list. - - bool mBuddyListMapPopulated; - bool mBlockRulesListReceived; - bool mAutoAcceptRulesListReceived; - buddyListMap mBuddyListMap; - - deviceList mCaptureDevices; - deviceList mRenderDevices; - - std::string mCaptureDevice; - std::string mRenderDevice; - bool mCaptureDeviceDirty; - bool mRenderDeviceDirty; - - // This should be called when the code detects we have changed parcels. - // It initiates the call to the server that gets the parcel channel. - void parcelChanged(); - - void switchChannel(std::string uri = std::string(), bool spatial = true, bool no_reconnect = false, bool is_p2p = false, std::string hash = ""); - void joinSession(sessionState *session); - -static std::string nameFromAvatar(LLVOAvatar *avatar); -static std::string nameFromID(const LLUUID &id); -static bool IDFromName(const std::string name, LLUUID &uuid); -static std::string displayNameFromAvatar(LLVOAvatar *avatar); - std::string sipURIFromAvatar(LLVOAvatar *avatar); - std::string sipURIFromName(std::string &name); - - // Returns the name portion of the SIP URI if the string looks vaguely like a SIP URI, or an empty string if not. -static std::string nameFromsipURI(const std::string &uri); - bool inSpatialChannel(void); - std::string getAudioSessionURI(); - std::string getAudioSessionHandle(); - - void sendPositionalUpdate(void); - - void buildSetCaptureDevice(std::ostringstream &stream); - void buildSetRenderDevice(std::ostringstream &stream); - void buildLocalAudioUpdates(std::ostringstream &stream); - - void clearAllLists(); - void checkFriend(const LLUUID& id); - void sendFriendsListUpdates(); - - // start a text IM session with the specified user - // This will be asynchronous, the session may be established at a future time. - sessionState* startUserIMSession(const LLUUID& uuid); - void sendQueuedTextMessages(sessionState *session); - - void enforceTether(void); - - bool mSpatialCoordsDirty; - - LLVector3d mCameraPosition; - LLVector3d mCameraRequestedPosition; - LLVector3 mCameraVelocity; - LLMatrix3 mCameraRot; - - LLVector3d mAvatarPosition; - LLVector3 mAvatarVelocity; - LLMatrix3 mAvatarRot; - - bool mPTTDirty; - bool mPTT; - - bool mUsePTT; - bool mPTTIsMiddleMouse; - KEY mPTTKey; - bool mPTTIsToggle; - bool mUserPTTState; - bool mMuteMic; - - // Set to true when the friends list is known to have changed. - bool mFriendsListDirty; - - enum - { - earLocCamera = 0, // ear at camera - earLocAvatar, // ear at avatar - earLocMixed // ear at avatar location/camera direction - }; - - S32 mEarLocation; - - bool mSpeakerVolumeDirty; - bool mSpeakerMuteDirty; - int mSpeakerVolume; + void setVoiceVolume(F32 volume); + void setMicGain(F32 volume); + void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal) + bool voiceEnabled(); + void setLipSyncEnabled(BOOL enabled); + void setMuteMic(bool muted); // Use this to mute the local mic (for when the client is minimized, etc), ignoring user PTT state. + void setUserPTTState(bool ptt); + bool getUserPTTState(); + void toggleUserPTTState(void); + void inputUserControlState(bool down); // interpret any sort of up-down mic-open control input according to ptt-toggle prefs + void setVoiceEnabled(bool enabled); + + void setUsePTT(bool usePTT); + void setPTTIsToggle(bool PTTIsToggle); + bool getPTTIsToggle(); + + BOOL lipSyncEnabled(); + + // PTT key triggering + void keyDown(KEY key, MASK mask); + void keyUp(KEY key, MASK mask); + void middleMouseState(bool down); + + + ///////////////////////////// + // Accessors for data related to nearby speakers + BOOL getVoiceEnabled(const LLUUID& id); // true if we've received data for this avatar + std::string getDisplayName(const LLUUID& id); + BOOL isOnlineSIP(const LLUUID &id); + BOOL isParticipantAvatar(const LLUUID &id); + BOOL getIsSpeaking(const LLUUID& id); + BOOL getIsModeratorMuted(const LLUUID& id); + F32 getCurrentPower(const LLUUID& id); // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is... + BOOL getOnMuteList(const LLUUID& id); + F32 getUserVolume(const LLUUID& id); + + ///////////////////////////// + BOOL getAreaVoiceDisabled(); // returns true if the area the avatar is in is speech-disabled. + // Use this to determine whether to show a "no speech" icon in the menu bar. + void getParticipantList(std::set<LLUUID> &participants); + bool isParticipant(const LLUUID& speaker_id); + + ////////////////////////// + /// @name text chat + //@{ + BOOL isSessionTextIMPossible(const LLUUID& id); + BOOL isSessionCallBackPossible(const LLUUID& id); + BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message); + void endUserIMSession(const LLUUID &uuid); + //@} + - int mMicVolume; - bool mMicVolumeDirty; - - bool mVoiceEnabled; - bool mWriteInProgress; - std::string mWriteString; - - LLTimer mUpdateTimer; + void userAuthorized(const std::string& user_id, + const LLUUID &agentID); + + void addObserver(LLVoiceClientStatusObserver* observer); + void removeObserver(LLVoiceClientStatusObserver* observer); + void addObserver(LLFriendObserver* observer); + void removeObserver(LLFriendObserver* observer); + void addObserver(LLVoiceClientParticipantObserver* observer); + void removeObserver(LLVoiceClientParticipantObserver* observer); + + std::string sipURIFromID(const LLUUID &id); - BOOL mLipSyncEnabled; - - std::string mAPIVersion; - - typedef std::set<LLVoiceClientParticipantObserver*> observer_set_t; - observer_set_t mParticipantObservers; +protected: + LLVoiceModuleInterface* mVoiceModule; + LLPumpIO *m_servicePump; +}; - void notifyParticipantObservers(); +/** + * Speaker volume storage helper class + **/ - typedef std::set<LLVoiceClientStatusObserver*> status_observer_set_t; - status_observer_set_t mStatusObservers; - - void notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status); +class LLSpeakerVolumeStorage : public LLSingleton<LLSpeakerVolumeStorage> +{ + LOG_CLASS(LLSpeakerVolumeStorage); +public: - typedef std::set<LLFriendObserver*> friend_observer_set_t; - friend_observer_set_t mFriendObservers; - void notifyFriendObservers(); + /** + * Sets internal voluem level for specified user. + * + * @param[in] speaker_id - LLUUID of user to store volume level for + * @param[in] volume - external volume level to be stored for user. + */ + void storeSpeakerVolume(const LLUUID& speaker_id, F32 volume); + + /** + * Gets stored external volume level for specified speaker. + * + * If specified user is not found default level will be returned. It is equivalent of + * external level 0.5 from the 0.0..1.0 range. + * Default external level is calculated as: internal = 400 * external^2 + * Maps 0.0 to 1.0 to internal values 0-400 with default 0.5 == 100 + * + * @param[in] speaker_id - LLUUID of user to get his volume level + */ + S32 getSpeakerVolume(const LLUUID& speaker_id); + +private: + friend class LLSingleton<LLSpeakerVolumeStorage>; + LLSpeakerVolumeStorage(); + ~LLSpeakerVolumeStorage(); + + const static std::string SETTINGS_FILE_NAME; + + void load(); + void save(); + + typedef std::map<LLUUID, S32> speaker_data_map_t; + speaker_data_map_t mSpeakersData; }; -extern LLVoiceClient *gVoiceClient; - #endif //LL_VOICE_CLIENT_H |