diff options
Diffstat (limited to 'indra/newview/llvoicevivox.cpp')
-rwxr-xr-x | indra/newview/llvoicevivox.cpp | 343 |
1 files changed, 115 insertions, 228 deletions
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 99190e9919..6ac8d84771 100755 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -91,10 +91,9 @@ const F32 LOGIN_RETRY_SECONDS = 10.0f; const int MAX_LOGIN_RETRIES = 12; // Defines the maximum number of times(in a row) "stateJoiningSession" case for spatial channel is reached in stateMachine() -// which is treated as normal. If this number is exceeded we suspect there is a problem with connection -// to voice server (EXT-4313). When voice works correctly, there is from 1 to 15 times. 50 was chosen -// to make sure we don't make mistake when slight connection problems happen- situation when connection to server is -// blocked is VERY rare and it's better to sacrifice response time in this situation for the sake of stability. +// which is treated as normal. The is the number of frames to wait for a channel join before giving up. This was changed +// from the original count of 50 for two reason. Modern PCs have higher frame rates and sometimes the SLVoice process +// backs up processing join requests. There is a log statement that records when channel joins take longer than 100 frames. const int MAX_NORMAL_JOINING_SPATIAL_NUM = 1500; // How often to check for expired voice fonts in seconds @@ -277,9 +276,10 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() : mTuningEnergy(0.0f), mTuningMicVolume(0), mTuningMicVolumeDirty(true), - mTuningSpeakerVolume(0), + mTuningSpeakerVolume(50), // Set to 50 so the user can hear himself when he sets his mic volume mTuningSpeakerVolumeDirty(true), mTuningExitState(stateDisabled), + mDevicesListUpdated(false), mAreaVoiceDisabled(false), mAudioSession(NULL), @@ -718,8 +718,9 @@ void LLVivoxVoiceClient::stateMachine() setVoiceEnabled(false); } - if(mVoiceEnabled || (!mIsInitialized &&!mTerminateDaemon) ) + if ((getState() == stateRunning) && inSpatialChannel() && mUpdateTimer.hasExpired() && !mTerminateDaemon) { + // poll the avatar position so its available in various states when a 3d position is sent. updatePosition(); } else if(mTuningMode) @@ -728,7 +729,8 @@ void LLVivoxVoiceClient::stateMachine() } else { - if((getState() != stateDisabled) && (getState() != stateDisableCleanup)) + if (!gSavedSettings.getBOOL("EnableVoiceChat")) + //if((getState() != stateDisabled) && (getState() != stateDisableCleanup)) { // User turned off voice support. Send the cleanup messages, close the socket, and reset. if(!mConnected || mTerminateDaemon) @@ -746,6 +748,10 @@ void LLVivoxVoiceClient::stateMachine() } } + + // send any requests to adjust mic and speaker settings if they have changed + sendLocalAudioUpdates(); + switch(getState()) { @@ -973,6 +979,19 @@ void LLVivoxVoiceClient::stateMachine() else { // loop mic back to render device. + //setMuteMic(0); // make sure the mic is not muted + std::ostringstream stream; + + stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalMic.1\">" + << "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>" + << "<Value>false</Value>" + << "</Request>\n\n\n"; + + // Dirty the mute mic state so that it will get reset when we finishing previewing + mMuteMicDirty = true; + mTuningSpeakerVolumeDirty = true; + + writeString(stream.str()); tuningCaptureStartSendMessage(1); // 1-loop, zero, don't loop setState(stateMicTuningRunning); @@ -1243,16 +1262,8 @@ void LLVivoxVoiceClient::stateMachine() } // Set the initial state of mic mute, local speaker volume, etc. - { - std::ostringstream stream; - - buildLocalAudioUpdates(stream); + sendLocalAudioUpdates(); - if(!stream.str().empty()) - { - writeString(stream.str()); - } - } break; //MARK: stateVoiceFontsWait @@ -1525,9 +1536,9 @@ void LLVivoxVoiceClient::stateMachine() // Must do this first, since it uses mAudioSession. notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL); - if(mAudioSession) + if (mAudioSession) { - leaveAudioSession(); + leaveAudioSession(); sessionState *oldSession = mAudioSession; mAudioSession = NULL; @@ -1977,21 +1988,6 @@ void LLVivoxVoiceClient::sessionMediaDisconnectSendMessage(sessionState *session } -/* obsolete -void LLVivoxVoiceClient::sessionTextDisconnectSendMessage(sessionState *session) -{ - std::ostringstream stream; - - LL_DEBUGS("Voice") << "Sending Session.TextDisconnect with handle " << session->mHandle << LL_ENDL; - stream - << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.TextDisconnect.1\">" - << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>" - << "<SessionHandle>" << session->mHandle << "</SessionHandle>" - << "</Request>\n\n\n"; - - writeString(stream.str()); -} -*/ void LLVivoxVoiceClient::getCaptureDevicesSendMessage() { @@ -2050,6 +2046,10 @@ void LLVivoxVoiceClient::setCaptureDevice(const std::string& name) } } } +void LLVivoxVoiceClient::setDevicesListUpdated(bool state) +{ + mDevicesListUpdated = state; +} void LLVivoxVoiceClient::clearRenderDevices() { @@ -2210,6 +2210,16 @@ bool LLVivoxVoiceClient::deviceSettingsAvailable() return result; } +bool LLVivoxVoiceClient::deviceSettingsUpdated() +{ + if (mDevicesListUpdated) + { + // a hot swap event or a polling of the audio devices has been parsed since the last redraw of the input and output device panel. + mDevicesListUpdated = !mDevicesListUpdated; // toggle the setting + return true; + } + return false; +} void LLVivoxVoiceClient::refreshDeviceLists(bool clearCurrentList) { @@ -2373,7 +2383,6 @@ void LLVivoxVoiceClient::sendPositionalUpdate(void) { std::ostringstream stream; - if (getState() != stateRunning) return; // don't send position updates if we are transitioning between out of running. if(mSpatialCoordsDirty) { @@ -2582,7 +2591,7 @@ void LLVivoxVoiceClient::sendPositionalUpdate(void) } } - buildLocalAudioUpdates(stream); + //sendLocalAudioUpdates(); obsolete, used to send volume setting on position updates if(!stream.str().empty()) { @@ -2622,68 +2631,73 @@ void LLVivoxVoiceClient::buildSetRenderDevice(std::ostringstream &stream) } } -void LLVivoxVoiceClient::buildLocalAudioUpdates(std::ostringstream &stream) +void LLVivoxVoiceClient::sendLocalAudioUpdates() { - buildSetCaptureDevice(stream); + // Check all of the dirty states and then send messages to those needing to be changed. + // Tuningmode hands its own mute settings. - buildSetRenderDevice(stream); + std::ostringstream stream; - if(mMuteMicDirty) + if (mMuteMicDirty && !mTuningMode) { mMuteMicDirty = false; // Send a local mute command. - - LL_DEBUGS("Voice") << "Sending MuteLocalMic command with parameter " << (mMuteMic?"true":"false") << LL_ENDL; + + LL_DEBUGS("Voice") << "Sending MuteLocalMic command with parameter " << (mMuteMic ? "true" : "false") << LL_ENDL; stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalMic.1\">" << "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>" - << "<Value>" << (mMuteMic?"true":"false") << "</Value>" + << "<Value>" << (mMuteMic ? "true" : "false") << "</Value>" << "</Request>\n\n\n"; - + } - if(mSpeakerMuteDirty) + if (mSpeakerMuteDirty && !mTuningMode) { - const char *muteval = ((mSpeakerVolume <= scale_speaker_volume(0))?"true":"false"); + const char *muteval = ((mSpeakerVolume <= scale_speaker_volume(0)) ? "true" : "false"); mSpeakerMuteDirty = false; - LL_INFOS("Voice") << "Setting speaker mute to " << muteval << LL_ENDL; - + LL_INFOS("Voice") << "Setting speaker mute to " << muteval << LL_ENDL; + stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalSpeaker.1\">" << "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>" << "<Value>" << muteval << "</Value>" - << "</Request>\n\n\n"; - + << "</Request>\n\n\n"; + } - - if(mSpeakerVolumeDirty) + + if (mSpeakerVolumeDirty) { mSpeakerVolumeDirty = false; - LL_INFOS("Voice") << "Setting speaker volume to " << mSpeakerVolume << LL_ENDL; + LL_INFOS("Voice") << "Setting speaker volume to " << mSpeakerVolume << LL_ENDL; stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.SetLocalSpeakerVolume.1\">" << "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>" << "<Value>" << mSpeakerVolume << "</Value>" << "</Request>\n\n\n"; - + } - - if(mMicVolumeDirty) + + if (mMicVolumeDirty) { mMicVolumeDirty = false; - LL_INFOS("Voice") << "Setting mic volume to " << mMicVolume << LL_ENDL; + LL_INFOS("Voice") << "Setting mic volume to " << mMicVolume << LL_ENDL; stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.SetLocalMicVolume.1\">" << "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>" << "<Value>" << mMicVolume << "</Value>" - << "</Request>\n\n\n"; + << "</Request>\n\n\n"; } - + + if (!stream.str().empty()) + { + writeString(stream.str()); + } } ///////////////////////////// @@ -2830,7 +2844,8 @@ void LLVivoxVoiceClient::sessionConnectResponse(std::string &requestId, int stat sessionState *session = findSession(requestId); // 1026 is session already has media, somehow mediaconnect was called twice on the same session. // set the session info to reflect that the user is already connected. - if (statusCode == 1026){ + if (statusCode == 1026) + { session->mVoiceEnabled = true; session->mMediaConnectInProgress = false; session->mMediaStreamState = streamStateConnected; @@ -2846,7 +2861,9 @@ void LLVivoxVoiceClient::sessionConnectResponse(std::string &requestId, int stat session->mErrorStatusCode = statusCode; session->mErrorStatusString = statusString; if (session == mAudioSession) + { setState(stateJoinSessionFailed); + } } } else @@ -2985,7 +3002,6 @@ void LLVivoxVoiceClient::joinedAudioSession(sessionState *session) { setState(stateSessionJoined); - // SLIM SDK: we don't always receive a participant state change for ourselves when joining a channel now. // Add the current user as a participant here. participantState *participant = session->addParticipant(sipURIFromName(mAccountName)); if(participant) @@ -3299,55 +3315,6 @@ void LLVivoxVoiceClient::mediaStreamUpdatedEvent( } } -/* Obsolete -void LLVivoxVoiceClient::textStreamUpdatedEvent( - std::string &sessionHandle, - std::string &sessionGroupHandle, - bool enabled, - int state, - bool incoming) -{ - sessionState *session = findSession(sessionHandle); - - if(session) - { - // Save the state for later use - session->mTextStreamState = state; - - // We know about this session - switch(state) - { - case 0: // We see this when the text stream closes - LL_DEBUGS("Voice") << "stream closed" << LL_ENDL; - break; - - case 1: // We see this on an incoming call from the Connector - // Try to send any text messages queued for this session. - sendQueuedTextMessages(session); - - // Send the text chat invite to the GUI layer - // TODO: Question: Should we correlate with the mute list here? - session->mTextInvitePending = true; - if(session->mName.empty()) - { - lookupName(session->mCallerID); - } - else - { - // Act like we just finished resolving the name - avatarNameResolved(session->mCallerID, session->mName); - } - break; - - default: - LL_WARNS("Voice") << "unknown state " << state << LL_ENDL; - break; - - } - } -} - obsolete */ - void LLVivoxVoiceClient::participantAddedEvent( std::string &sessionHandle, std::string &sessionGroupHandle, @@ -4224,62 +4191,6 @@ LLVivoxVoiceClient::sessionState* LLVivoxVoiceClient::startUserIMSession(const L return session; } -/* obsolete -BOOL LLVivoxVoiceClient::sendTextMessage(const LLUUID& participant_id, const std::string& message) -{ - bool result = false; - - // Attempt to locate the indicated session - sessionState *session = startUserIMSession(participant_id); - if(session) - { - // found the session, attempt to send the message - session->mTextMsgQueue.push(message); - - // Try to send queued messages (will do nothing if the session is not open yet) - sendQueuedTextMessages(session); - - // The message is queued, so we succeed. - result = true; - } - else - { - LL_DEBUGS("Voice") << "Session not found for participant ID " << participant_id << LL_ENDL; - } - - return result; -} -*/ -/* obsolete -void LLVivoxVoiceClient::sendQueuedTextMessages(sessionState *session) -{ - if(session->mTextStreamState == 1) - { - if(!session->mTextMsgQueue.empty()) - { - std::ostringstream stream; - - while(!session->mTextMsgQueue.empty()) - { - std::string message = session->mTextMsgQueue.front(); - session->mTextMsgQueue.pop(); - stream - << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SendMessage.1\">" - << "<SessionHandle>" << session->mHandle << "</SessionHandle>" - << "<MessageHeader>text/HTML</MessageHeader>" - << "<MessageBody>" << message << "</MessageBody>" - << "</Request>" - << "\n\n\n"; - } - writeString(stream.str()); - } - } - else - { - // Session isn't connected yet, defer until later. - } -} - obsolete */ void LLVivoxVoiceClient::endUserIMSession(const LLUUID &uuid) { @@ -4641,11 +4552,6 @@ void LLVivoxVoiceClient::enforceTether(void) void LLVivoxVoiceClient::updatePosition(void) { - - // Throttle the position updates to one every 1/10 of a second if we are in an audio session at all - if (mAudioSession == NULL) { - return; - } LLViewerRegion *region = gAgent.getRegion(); if(region && isAgentAvatarValid()) @@ -5109,7 +5015,7 @@ void LLVivoxVoiceClient::filePlaybackSetMode(bool vox, float speed) LLVivoxVoiceClient::sessionState::sessionState() : mErrorStatusCode(0), mMediaStreamState(streamStateUnknown), - mTextStreamState(streamStateUnknown), + //mTextStreamState(streamStateUnknown), mCreateInProgress(false), mMediaConnectInProgress(false), mVoiceInvitePending(false), @@ -6705,6 +6611,10 @@ void LLVivoxProtocolParser::EndTag(const char *tag) uriString = string; else if (!stricmp("Presence", tag)) statusString = string; + else if (!stricmp("CaptureDevices", tag)) + LLVivoxVoiceClient::getInstance()->setDevicesListUpdated(true); + else if (!stricmp("RenderDevices", tag)) + LLVivoxVoiceClient::getInstance()->setDevicesListUpdated(true); else if (!stricmp("CaptureDevice", tag)) { LLVivoxVoiceClient::getInstance()->addCaptureDevice(deviceString); @@ -6833,7 +6743,13 @@ void LLVivoxProtocolParser::processResponse(std::string tag) if (isEvent) { const char *eventTypeCstr = eventTypeString.c_str(); - if (!stricmp(eventTypeCstr, "AccountLoginStateChangeEvent")) + if (!stricmp(eventTypeCstr, "ParticipantUpdatedEvent")) + { + // These happen so often that logging them is pretty useless. + squelchDebugOutput = true; + LLVivoxVoiceClient::getInstance()->participantUpdatedEvent(sessionHandle, sessionGroupHandle, uriString, alias, isModeratorMuted, isSpeaking, volume, energy); + } + else if (!stricmp(eventTypeCstr, "AccountLoginStateChangeEvent")) { LLVivoxVoiceClient::getInstance()->accountLoginStateChangeEvent(accountHandle, statusCode, statusString, state); } @@ -6857,7 +6773,7 @@ void LLVivoxProtocolParser::processResponse(std::string tag) } else if (!stricmp(eventTypeCstr, "SessionGroupUpdatedEvent")) { - //TODO, we don't process this event, but we should not WARN that we have received it. + //nothng useful to process for this event, but we should not WARN that we have received it. } else if (!stricmp(eventTypeCstr, "SessionGroupAddedEvent")) { @@ -6887,13 +6803,6 @@ void LLVivoxProtocolParser::processResponse(std::string tag) */ LLVivoxVoiceClient::getInstance()->mediaCompletionEvent(sessionGroupHandle, mediaCompletionType); } - /* obsolete, let else statement complain if a text message arrives - else if (!stricmp(eventTypeCstr, "TextStreamUpdatedEvent")) - { - - LLVivoxVoiceClient::getInstance()->textStreamUpdatedEvent(sessionHandle, sessionGroupHandle, enabled, state, incoming); - - } */ else if (!stricmp(eventTypeCstr, "ParticipantAddedEvent")) { /* @@ -6920,52 +6829,20 @@ void LLVivoxProtocolParser::processResponse(std::string tag) */ LLVivoxVoiceClient::getInstance()->participantRemovedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString); } - else if (!stricmp(eventTypeCstr, "ParticipantUpdatedEvent")) - { - /* - <Event type="ParticipantUpdatedEvent"> - <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle> - <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle> - <ParticipantUri>sip:xFnPP04IpREWNkuw1cOXlhw==@bhr.vivox.com</ParticipantUri> - <IsModeratorMuted>false</IsModeratorMuted> - <IsSpeaking>true</IsSpeaking> - <Volume>44</Volume> - <Energy>0.0879437</Energy> - </Event> - */ - - // These happen so often that logging them is pretty useless. - squelchDebugOutput = true; - - LLVivoxVoiceClient::getInstance()->participantUpdatedEvent(sessionHandle, sessionGroupHandle, uriString, alias, isModeratorMuted, isSpeaking, volume, energy); - } else if (!stricmp(eventTypeCstr, "AuxAudioPropertiesEvent")) { // These are really spammy in tuning mode squelchDebugOutput = true; - LLVivoxVoiceClient::getInstance()->auxAudioPropertiesEvent(energy); } - else if (!stricmp(eventTypeCstr, "BuddyChangedEvent")) - { - /* - <Event type="BuddyChangedEvent"> - <AccountHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==</AccountHandle> - <BuddyURI>sip:x9fFHFZjOTN6OESF1DUPrZQ==@bhr.vivox.com</BuddyURI> - <DisplayName>Monroe Tester</DisplayName> - <BuddyData /> - <GroupID>0</GroupID> - <ChangeType>Set</ChangeType> - </Event> - */ - // TODO: Question: Do we need to process this at all? - } else if (!stricmp(eventTypeCstr, "MessageEvent")) { + //TODO: This probably is not received any more, it was used to support SLim clients LLVivoxVoiceClient::getInstance()->messageEvent(sessionHandle, uriString, alias, messageHeader, messageBody, applicationString); } else if (!stricmp(eventTypeCstr, "SessionNotificationEvent")) { + //TODO: This probably is not received any more, it was used to support SLim clients LLVivoxVoiceClient::getInstance()->sessionNotificationEvent(sessionHandle, uriString, notificationType); } else if (!stricmp(eventTypeCstr, "SessionUpdatedEvent")) @@ -6985,19 +6862,29 @@ void LLVivoxProtocolParser::processResponse(std::string tag) */ // We don't need to process this, but we also shouldn't warn on it, since that confuses people. } - - else if (!stricmp(eventTypeCstr, "SessionGroupRemovedEvent")) + else if (!stricmp(eventTypeCstr, "SessionGroupRemovedEvent")) { - /* - <Event type="SessionGroupRemovedEvent"> - <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle> - </Event> - */ // We don't need to process this, but we also shouldn't warn on it, since that confuses people. } - else if (!stricmp(eventTypeCstr, "VoiceServiceConnectionStateChangedEvent")) + else if (!stricmp(eventTypeCstr, "VoiceServiceConnectionStateChangedEvent")) { // Yet another ignored event } + else if (!stricmp(eventTypeCstr, "AudioDeviceHotSwapEvent")) + { + /* + <Event type = "AudioDeviceHotSwapEvent"> + <EventType>RenderDeviceChanged< / EventType> + <RelevantDevice> + <Device>Speakers(Turtle Beach P11 Headset)< / Device> + <DisplayName>Speakers(Turtle Beach P11 Headset)< / DisplayName> + <Type>SpecificDevice< / Type> + < / RelevantDevice> + < / Event> + */ + // an audio device was removed or added, fetch and update the local list of audio devices. + LLVivoxVoiceClient::getInstance()->getCaptureDevicesSendMessage(); + LLVivoxVoiceClient::getInstance()->getRenderDevicesSendMessage(); + } else { LL_WARNS("VivoxProtocolParser") << "Unknown event type " << eventTypeString << LL_ENDL; @@ -7006,7 +6893,12 @@ void LLVivoxProtocolParser::processResponse(std::string tag) else { const char *actionCstr = actionString.c_str(); - if (!stricmp(actionCstr, "Connector.Create.1")) + if (!stricmp(actionCstr, "Session.Set3DPosition.1")) + { + // We don't need to process these, but they're so spammy we don't want to log them. + squelchDebugOutput = true; + } + else if (!stricmp(actionCstr, "Connector.Create.1")) { LLVivoxVoiceClient::getInstance()->connectorCreateResponse(statusCode, statusString, connectorHandle, versionID); } @@ -7034,11 +6926,6 @@ void LLVivoxProtocolParser::processResponse(std::string tag) { LLVivoxVoiceClient::getInstance()->connectorShutdownResponse(statusCode, statusString); } - else if (!stricmp(actionCstr, "Session.Set3DPosition.1")) - { - // We don't need to process these, but they're so spammy we don't want to log them. - squelchDebugOutput = true; - } else if (!stricmp(actionCstr, "Account.GetSessionFonts.1")) { LLVivoxVoiceClient::getInstance()->accountGetSessionFontsResponse(statusCode, statusString); |