llvoiceclient.h

Go to the documentation of this file.
00001 
00031 #ifndef LL_VOICE_CLIENT_H
00032 #define LL_VOICE_CLIENT_H
00033 
00034 // This would create a circular reference -- just do a forward definition of necessary class names.
00035 //#include "llvoavatar.h"
00036 class LLVOAvatar;
00037 class LLVivoxProtocolParser;
00038 
00039 #include "lliopipe.h"
00040 #include "llpumpio.h"
00041 #include "llchainio.h"
00042 #include "lliosocket.h"
00043 #include "v3math.h"
00044 #include "llframetimer.h"
00045 #include "llviewerregion.h"
00046 
00047 class LLVoiceClientParticipantObserver
00048 {
00049 public:
00050         virtual ~LLVoiceClientParticipantObserver() { }
00051         virtual void onChange() = 0;
00052 };
00053 
00054 class LLVoiceClientStatusObserver
00055 {
00056 public:
00057         typedef enum e_voice_status_type
00058         {
00059                 // NOTE: when updating this enum, please also update the switch in
00060                 //  LLVoiceClientStatusObserver::status2string().
00061                 STATUS_LOGIN_RETRY,
00062                 STATUS_LOGGED_IN,
00063                 STATUS_JOINING,
00064                 STATUS_JOINED,
00065                 STATUS_LEFT_CHANNEL,
00066                 BEGIN_ERROR_STATUS,
00067                 ERROR_CHANNEL_FULL,
00068                 ERROR_CHANNEL_LOCKED,
00069                 ERROR_NOT_AVAILABLE,
00070                 ERROR_UNKNOWN
00071         } EStatusType;
00072 
00073         virtual ~LLVoiceClientStatusObserver() { }
00074         virtual void onChange(EStatusType status, const std::string &channelURI, bool proximal) = 0;
00075 
00076         static const char *status2string(EStatusType inStatus);
00077 };
00078 
00079 class LLVoiceClient: public LLSingleton<LLVoiceClient>
00080 {
00081         LOG_CLASS(LLVoiceClient);
00082         public:
00083                 LLVoiceClient();        
00084                 ~LLVoiceClient();
00085                 
00086         public:
00087                 static void init(LLPumpIO *pump);       // Call this once at application startup (creates connector)
00088                 static void terminate();        // Call this to clean up during shutdown
00089                                                 
00090         protected:
00091                 bool writeString(const std::string &str);
00092 
00093         public:
00094                 
00095                 enum serviceType
00096                 {
00097                         serviceTypeUnknown,     // Unknown, returned if no data on the avatar is available
00098                         serviceTypeA,           // spatialized local chat
00099                         serviceTypeB,           // remote multi-party chat
00100                         serviceTypeC            // one-to-one and small group chat
00101                 };
00102                 static F32 OVERDRIVEN_POWER_LEVEL;
00103                                 
00105                 // session control messages
00106                 void connect();
00107 
00108                 void connectorCreate();
00109                 void connectorShutdown();
00110 
00111                 void requestVoiceAccountProvision(S32 retries = 3);
00112                 void userAuthorized(
00113                         const std::string& firstName,
00114                         const std::string& lastName,
00115                         const LLUUID &agentID);
00116                 void login(const std::string& accountName, const std::string &password);
00117                 void loginSendMessage();
00118                 void logout();
00119                 void logoutSendMessage();
00120                 
00121                 void channelGetListSendMessage();
00122                 void sessionCreateSendMessage();
00123                 void sessionConnectSendMessage();
00124                 void sessionTerminate();
00125                 void sessionTerminateSendMessage();
00126                 void sessionTerminateByHandle(std::string &sessionHandle);
00127                 
00128                 void getCaptureDevicesSendMessage();
00129                 void getRenderDevicesSendMessage();
00130                 
00131                 void clearCaptureDevices();
00132                 void addCaptureDevice(const std::string& name);
00133                 void setCaptureDevice(const std::string& name);
00134                 
00135                 void clearRenderDevices();
00136                 void addRenderDevice(const std::string& name);
00137                 void setRenderDevice(const std::string& name);
00138 
00139                 void tuningStart();
00140                 void tuningStop();
00141                 bool inTuningMode();
00142                 
00143                 void tuningRenderStartSendMessage(const std::string& name, bool loop);
00144                 void tuningRenderStopSendMessage();
00145 
00146                 void tuningCaptureStartSendMessage(int duration);
00147                 void tuningCaptureStopSendMessage();
00148                 
00149                 void tuningSetMicVolume(float volume);
00150                 void tuningSetSpeakerVolume(float volume);
00151                 float tuningGetEnergy(void);
00152                                 
00153                 // This returns true when it's safe to bring up the "device settings" dialog in the prefs.
00154                 // i.e. when the daemon is running and connected, and the device lists are populated.
00155                 bool deviceSettingsAvailable();
00156                 
00157                 // Requery the vivox daemon for the current list of input/output devices.
00158                 // If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed
00159                 // (use this if you want to know when it's done).
00160                 // 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.
00161                 void refreshDeviceLists(bool clearCurrentList = true);
00162                 
00163                 // Call this if the connection to the daemon terminates unexpectedly.  It will attempt to reset everything and relaunch.
00164                 void daemonDied();
00165 
00166                 // Call this if we're just giving up on voice (can't provision an account, etc.).  It will clean up and go away.
00167                 void giveUp();
00168                 
00170                 // Response/Event handlers
00171                 void connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle);
00172                 void loginResponse(int statusCode, std::string &statusString, std::string &accountHandle);
00173                 void channelGetListResponse(int statusCode, std::string &statusString);
00174                 void sessionCreateResponse(int statusCode, std::string &statusString, std::string &sessionHandle);
00175                 void sessionConnectResponse(int statusCode, std::string &statusString);
00176                 void sessionTerminateResponse(int statusCode, std::string &statusString);
00177                 void logoutResponse(int statusCode, std::string &statusString);
00178                 void connectorShutdownResponse(int statusCode, std::string &statusString);
00179 
00180                 void loginStateChangeEvent(std::string &accountHandle, int statusCode, std::string &statusString, int state);
00181                 void sessionNewEvent(std::string &accountHandle, std::string &eventSessionHandle, int state, std::string &nameString, std::string &uriString);
00182                 void sessionStateChangeEvent(std::string &uriString, int statusCode, std::string &statusString, std::string &sessionHandle, int state,  bool isChannel, std::string &nameString);
00183                 void participantStateChangeEvent(std::string &uriString, int statusCode, std::string &statusString, int state,  std::string &nameString, std::string &displayNameString, int participantType);
00184                 void participantPropertiesEvent(std::string &uriString, int statusCode, std::string &statusString, bool isLocallyMuted, bool isModeratorMuted, bool isSpeaking, int volume, F32 energy);
00185                 void auxAudioPropertiesEvent(F32 energy);
00186         
00187                 void muteListChanged();
00188                 
00190                 // Sending updates of current state
00191                 void setCameraPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot);
00192                 void setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot);
00193                 bool channelFromRegion(LLViewerRegion *region, std::string &name);
00194                 void leaveChannel(void);                // call this on logout or teleport begin
00195 
00196                 
00197                 void setMuteMic(bool muted);            // Use this to mute the local mic (for when the client is minimized, etc), ignoring user PTT state.
00198                 void setUserPTTState(bool ptt);
00199                 bool getUserPTTState();
00200                 void toggleUserPTTState(void);
00201                 void setVoiceEnabled(bool enabled);
00202                 static bool voiceEnabled();
00203                 void setUsePTT(bool usePTT);
00204                 void setPTTIsToggle(bool PTTIsToggle);
00205                 void setPTTKey(std::string &key);
00206                 void setEarLocation(S32 loc);
00207                 void setVoiceVolume(F32 volume);
00208                 void setMicGain(F32 volume);
00209                 void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal)
00210                 void setVivoxDebugServerName(std::string &serverName);
00211 
00212                 // PTT key triggering
00213                 void keyDown(KEY key, MASK mask);
00214                 void keyUp(KEY key, MASK mask);
00215                 void middleMouseState(bool down);
00216                 
00218                 // Accessors for data related to nearby speakers
00219                 BOOL getVoiceEnabled(const LLUUID& id);         // true if we've received data for this avatar
00220                 BOOL getIsSpeaking(const LLUUID& id);
00221                 F32 getCurrentPower(const LLUUID& id);          // "power" is related to "amplitude" in a defined way.  I'm just not sure what the formula is...
00222                 BOOL getPTTPressed(const LLUUID& id);                   // This is the inverse of the "locally muted" property.
00223                 BOOL getOnMuteList(const LLUUID& id);
00224                 F32 getUserVolume(const LLUUID& id);
00225                 LLString getDisplayName(const LLUUID& id);
00226                 
00227                 // MBW -- XXX -- Not sure how to get this data out of the TVC
00228                 BOOL getUsingPTT(const LLUUID& id);
00229                 serviceType getServiceType(const LLUUID& id);   // type of chat the user is involved in (see bHear scope doc for definitions of A/B/C)
00230                 std::string getGroupID(const LLUUID& id);               // group ID if the user is in group chat (empty string if not applicable)
00231 
00233                 BOOL getAreaVoiceDisabled();            // returns true if the area the avatar is in is speech-disabled.
00234                                                                                         // Use this to determine whether to show a "no speech" icon in the menu bar.
00235 
00236                 struct participantState
00237                 {
00238                 public:
00239                         participantState(const std::string &uri);
00240                         std::string mURI;
00241                         std::string mName;
00242                         std::string mDisplayName;
00243                         bool mPTT;
00244                         bool mIsSpeaking;
00245                         LLFrameTimer mSpeakingTimeout;
00246                         F32     mLastSpokeTimestamp;
00247                         F32 mPower;
00248                         int mVolume;
00249                         serviceType mServiceType;
00250                         std::string mGroupID;
00251                         bool mOnMuteList;               // true if this avatar is on the user's mute list (and should be muted)
00252                         int mUserVolume;
00253                         bool mVolumeDirty;              // true if this participant needs a volume command sent (either mOnMuteList or mUserVolume has changed)
00254                         bool mAvatarIDValid;
00255                         LLUUID mAvatarID;
00256                 };
00257                 typedef std::map<std::string, participantState*> participantMap;
00258                 
00259                 participantState *findParticipant(const std::string &uri);
00260                 participantState *findParticipantByAvatar(LLVOAvatar *avatar);
00261                 participantState *findParticipantByID(const LLUUID& id);
00262                 
00263                 participantMap *getParticipantList(void);
00264 
00265                 void addObserver(LLVoiceClientParticipantObserver* observer);
00266                 void removeObserver(LLVoiceClientParticipantObserver* observer);
00267 
00268                 void addStatusObserver(LLVoiceClientStatusObserver* observer);
00269                 void removeStatusObserver(LLVoiceClientStatusObserver* observer);
00270                 
00271                 static void onAvatarNameLookup(const LLUUID& id, const char* first, const char* last, BOOL is_group, void* user_data);
00272                 typedef std::vector<std::string> deviceList;
00273 
00274                 deviceList *getCaptureDevices();
00275                 deviceList *getRenderDevices();
00276                 
00277                 void setNonSpatialChannel(
00278                         const std::string &uri,
00279                         const std::string &credentials);
00280                 void setSpatialChannel(
00281                         const std::string &uri,
00282                         const std::string &credentials);
00283                 void callUser(LLUUID &uuid);
00284                 void answerInvite(std::string &sessionHandle, LLUUID& other_user_id);
00285                 void declineInvite(std::string &sessionHandle);
00286                 void leaveNonSpatialChannel();
00287 
00288                 // Returns the URI of the current channel, or an empty string if not currently in a channel.
00289                 // NOTE that it will return an empty string if it's in the process of joining a channel.
00290                 std::string getCurrentChannel();
00291                 
00292                 // returns true iff the user is currently in a proximal (local spatial) channel.
00293                 // Note that gestures should only fire if this returns true.
00294                 bool inProximalChannel();
00295 
00296                 std::string sipURIFromID(const LLUUID &id);
00297 
00298         private:
00299 
00300                 // internal state for a simple state machine.  This is used to deal with the asynchronous nature of some of the messages.
00301                 // Note: if you change this list, please make corresponding changes to LLVoiceClient::state2string().
00302                 enum state
00303                 {
00304                         stateDisabled,                          // Voice is turned off.
00305                         stateStart,                                     // Class is initialized, socket is created
00306                         stateDaemonLaunched,            // Daemon has been launched
00307                         stateConnecting,                        // connect() call has been issued
00308                         stateIdle,                                      // socket is connected, ready for messaging
00309                         stateConnectorStart,            // connector needs to be started
00310                         stateConnectorStarting,         // waiting for connector handle
00311                         stateConnectorStarted,          // connector handle received
00312                         stateMicTuningNoLogin,          // mic tuning before login
00313                         stateLoginRetry,                        // need to retry login (failed due to changing password)
00314                         stateLoginRetryWait,            // waiting for retry timer
00315                         stateNeedsLogin,                        // send login request
00316                         stateLoggingIn,                         // waiting for account handle
00317                         stateLoggedIn,                          // account handle received
00318                         stateNoChannel,                         // 
00319                         stateMicTuningLoggedIn,         // mic tuning for a logged in user
00320                         stateSessionCreate,                     // need to send Session.Create command
00321                         stateSessionConnect,            // need to send Session.Connect command
00322                         stateJoiningSession,            // waiting for session handle
00323                         stateSessionJoined,                     // session handle received
00324                         stateRunning,                           // in session, steady state
00325                         stateLeavingSession,            // waiting for terminate session response
00326                         stateSessionTerminated,         // waiting for terminate session response
00327 
00328                         stateLoggingOut,                        // waiting for logout response
00329                         stateLoggedOut,                         // logout response received
00330                         stateConnectorStopping,         // waiting for connector stop
00331                         stateConnectorStopped,          // connector stop received
00332                         
00333                         // We go to this state if the login fails because the account needs to be provisioned.
00334                         
00335                         // error states.  No way to recover from these yet.
00336                         stateConnectorFailed,
00337                         stateConnectorFailedWaiting,
00338                         stateLoginFailed,
00339                         stateLoginFailedWaiting,
00340                         stateJoinSessionFailed,
00341                         stateJoinSessionFailedWaiting,
00342 
00343                         stateJail                                       // Go here when all else has failed.  Nothing will be retried, we're done.
00344                 };
00345                 
00346                 state mState;
00347                 bool mSessionTerminateRequested;
00348                 bool mNonSpatialChannel;
00349                 
00350                 void setState(state inState);
00351                 state getState(void)  { return mState; };
00352                 static const char *state2string(state inState);
00353                 
00354                 void stateMachine();
00355                 static void idle(void *user_data);
00356                 
00357                 LLHost mDaemonHost;
00358                 LLSocket::ptr_t mSocket;
00359                 bool mConnected;
00360                 
00361                 void closeSocket(void);
00362                 
00363                 LLPumpIO *mPump;
00364                 friend class LLVivoxProtocolParser;
00365                 
00366                 std::string mAccountName;
00367                 std::string mAccountPassword;
00368                 std::string mAccountDisplayName;
00369                 std::string mAccountFirstName;
00370                 std::string mAccountLastName;
00371                 
00372                 std::string mNextP2PSessionURI;         // URI of the P2P session to join next
00373                 std::string mNextSessionURI;            // URI of the session to join next
00374                 std::string mNextSessionHandle;         // Session handle of the session to join next
00375                 std::string mNextSessionHash;           // Password hash for the session to join next
00376                 bool mNextSessionSpatial;                       // Will next session be a spatial chat?
00377                 bool mNextSessionNoReconnect;           // Next session should not auto-reconnect (i.e. user -> user chat)
00378                 bool mNextSessionResetOnClose;          // If this is true, go back to spatial chat when the next session terminates.
00379                 
00380                 std::string mSessionStateEventHandle;   // session handle received in SessionStateChangeEvents
00381                 std::string mSessionStateEventURI;              // session URI received in SessionStateChangeEvents
00382                 
00383                 bool mTuningMode;
00384                 float mTuningEnergy;
00385                 std::string mTuningAudioFile;
00386                 int mTuningMicVolume;
00387                 bool mTuningMicVolumeDirty;
00388                 int mTuningSpeakerVolume;
00389                 bool mTuningSpeakerVolumeDirty;
00390                 bool mTuningCaptureRunning;
00391                 
00392                 std::string mSpatialSessionURI;
00393                 
00394                 bool mSessionResetOnClose;
00395                 
00396                 int mVivoxErrorStatusCode;              
00397                 std::string mVivoxErrorStatusString;
00398                 
00399                 std::string mChannelName;                       // Name of the channel to be looked up 
00400                 bool mAreaVoiceDisabled;
00401                 std::string mSessionURI;                        // URI of the session we're in.
00402                 bool mSessionP2P;                                       // true if this session is a p2p call
00403                 
00404                 S32 mCurrentParcelLocalID;                      // Used to detect parcel boundary crossings
00405                 std::string mCurrentRegionName;         // Used to detect parcel boundary crossings
00406                 
00407                 std::string mConnectorHandle;   // returned by "Create Connector" message
00408                 std::string mAccountHandle;             // returned by login message            
00409                 std::string mSessionHandle;             // returned by ?
00410                 U32 mCommandCookie;
00411         
00412                 std::string mAccountServerName;
00413                 std::string mAccountServerURI;
00414                 
00415                 int mLoginRetryCount;
00416                 
00417                 participantMap mParticipantMap;
00418                 bool mParticipantMapChanged;
00419                 
00420                 deviceList mCaptureDevices;
00421                 deviceList mRenderDevices;
00422 
00423                 std::string mCaptureDevice;
00424                 std::string mRenderDevice;
00425                 bool mCaptureDeviceDirty;
00426                 bool mRenderDeviceDirty;
00427                 
00428                 participantState *addParticipant(const std::string &uri);
00429                 // Note: after removeParticipant returns, the participant* that was passed to it will have been deleted.
00430                 // Take care not to use the pointer again after that.
00431                 void removeParticipant(participantState *participant);
00432                 void removeAllParticipants();
00433 
00434                 void updateMuteState(participantState *participant);
00435 
00436                 typedef std::map<std::string, std::string> channelMap;
00437                 channelMap mChannelMap;
00438                 
00439                 // These are used by the parser when processing a channel list response.
00440                 void clearChannelMap(void);
00441                 void addChannelMapEntry(std::string &name, std::string &uri);
00442                 std::string findChannelURI(std::string &name);
00443                         
00444                 // This should be called when the code detects we have changed parcels.
00445                 // It initiates the call to the server that gets the parcel channel.
00446                 void parcelChanged();
00447                 
00448         void switchChannel(std::string uri = std::string(), bool spatial = true, bool noReconnect = false, std::string hash = "");
00449                 void joinSession(std::string handle, std::string uri);
00450                 
00451                 std::string nameFromAvatar(LLVOAvatar *avatar);
00452                 std::string nameFromID(const LLUUID &id);
00453                 bool IDFromName(const std::string name, LLUUID &uuid);
00454                 std::string displayNameFromAvatar(LLVOAvatar *avatar);
00455                 std::string sipURIFromAvatar(LLVOAvatar *avatar);
00456                 std::string sipURIFromName(std::string &name);
00457                                 
00458                 void sendPositionalUpdate(void);
00459                 
00460                 void buildSetCaptureDevice(std::ostringstream &stream);
00461                 void buildSetRenderDevice(std::ostringstream &stream);
00462                 
00463                 void enforceTether(void);
00464                 
00465                 bool            mSpatialCoordsDirty;
00466                 
00467                 LLVector3d      mCameraPosition;
00468                 LLVector3d      mCameraRequestedPosition;
00469                 LLVector3       mCameraVelocity;
00470                 LLMatrix3       mCameraRot;
00471 
00472                 LLVector3d      mAvatarPosition;
00473                 LLVector3       mAvatarVelocity;
00474                 LLMatrix3       mAvatarRot;
00475                 
00476                 bool            mPTTDirty;
00477                 bool            mPTT;
00478                 
00479                 bool            mUsePTT;
00480                 bool            mPTTIsMiddleMouse;
00481                 KEY                     mPTTKey;
00482                 bool            mPTTIsToggle;
00483                 bool            mUserPTTState;
00484                 bool            mMuteMic;
00485                 
00486                 // Set to true when the mute state of someone in the participant list changes.
00487                 // The code will have to walk the list to find the changed participant(s).
00488                 bool            mVolumeDirty;
00489                 
00490                 enum
00491                 {
00492                         earLocCamera = 0,               // ear at camera
00493                         earLocAvatar,                   // ear at avatar
00494                         earLocMixed                             // ear at avatar location/camera direction
00495                 };
00496                 
00497                 S32                     mEarLocation;  
00498                 
00499                 bool            mSpeakerVolumeDirty;
00500                 bool            mSpeakerMuteDirty;
00501                 int                     mSpeakerVolume;
00502 
00503                 int                     mMicVolume;
00504                 bool            mMicVolumeDirty;
00505                 
00506                 bool            mVoiceEnabled;
00507                 bool            mWriteInProgress;
00508                 std::string mWriteString;
00509                 size_t          mWriteOffset;
00510                 
00511                 LLTimer         mUpdateTimer;
00512                 
00513                 typedef std::set<LLVoiceClientParticipantObserver*> observer_set_t;
00514                 observer_set_t mObservers;
00515 
00516                 void notifyObservers();
00517 
00518                 typedef std::set<LLVoiceClientStatusObserver*> status_observer_set_t;
00519                 status_observer_set_t mStatusObservers;
00520                 
00521                 void notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status);
00522 };
00523 
00524 extern LLVoiceClient *gVoiceClient;
00525 
00526 #endif //LL_VOICE_CLIENT_H
00527 
00528 
00529 

Generated on Thu Jul 1 06:09:37 2010 for Second Life Viewer by  doxygen 1.4.7