diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 92004554e..9ce08dfa0 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -420,8 +420,25 @@ LLFloaterIMPanel::~LLFloaterIMPanel() delete mSpeakers; mSpeakers = NULL; - + + // End the text IM session if necessary + if(LLVoiceClient::instanceExists() && mOtherParticipantUUID.notNull()) + { + switch(mDialog) + { + case IM_NOTHING_SPECIAL: + case IM_SESSION_P2P_INVITE: + LLVoiceClient::getInstance()->endUserIMSession(mOtherParticipantUUID); + break; + + default: + // Appease the compiler + break; + } + } + //kicks you out of the voice channel if it is currently active + // HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point). mVoiceChannel->deactivate(); @@ -1061,12 +1078,20 @@ void deliver_message(const std::string& utf8_text, EInstantMessage dialog) { std::string name; + bool sent = false; gAgent.buildFullname(name); const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id); U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE; + if((offline == IM_OFFLINE) && (LLVoiceClient::getInstance()->isOnlineSIP(other_participant_id))) + { + // User is online through the OOW connector, but not with a regular viewer. Try to send the message via SLVoice. + sent = LLVoiceClient::getInstance()->sendTextMessage(other_participant_id, utf8_text); + } + + if(!sent) { // Send message normally. diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index c5b7e66a7..54ca806de 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -354,7 +354,6 @@ BOOL LLVoiceClient::isSessionCallBackPossible(const LLUUID& id) } } -/* BOOL LLVoiceClient::sendTextMessage(const LLUUID& participant_id, const std::string& message) { if (mVoiceModule) @@ -374,7 +373,6 @@ void LLVoiceClient::endUserIMSession(const LLUUID& participant_id) mVoiceModule->endUserIMSession(participant_id); } } -*/ //---------------------------------------------- // channels diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index a4a1dba5f..b8cf474cc 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -212,8 +212,8 @@ public: //@{ 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; + virtual BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message)=0; + virtual void endUserIMSession(const LLUUID &uuid)=0; //@} // authorize the user @@ -428,8 +428,8 @@ public: //@{ 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); + BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message); + void endUserIMSession(const LLUUID &uuid); //@} diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 8a5f2a299..ce1d09041 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -80,10 +80,10 @@ 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. 1500 was chosen +// 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. -const int MAX_NORMAL_JOINING_SPATIAL_NUM = 1500; +const int MAX_NORMAL_JOINING_SPATIAL_NUM = 50; // How often to check for expired voice fonts in seconds const F32 VOICE_FONT_EXPIRY_INTERVAL = 10.f; @@ -478,21 +478,17 @@ bool LLVivoxVoiceClient::writeString(const std::string &str) (const char*)str.data(), &written); - if (err == 0 && written == size) + if(err == 0) { // Success. result = true; } - else if (err == 0 && written != size) - { - // Did a short write, log it for now - LL_WARNS("Voice") << ") short write on socket sending data to vivox daemon." << "Sent " << written << "bytes instead of " << size << LL_ENDL; - } - else if (APR_STATUS_IS_EAGAIN(err)) - { - char buf[MAX_STRING]; - LL_WARNS("Voice") << "EAGAIN error " << err << " (" << apr_strerror(err, buf, MAX_STRING) << ") sending data to vivox daemon." << LL_ENDL; - } + // TODO: handle partial writes (written is number of bytes written) + // Need to set socket to non-blocking before this will work. +// else if(APR_STATUS_IS_EAGAIN(err)) +// { +// // +// } else { // Assume any socket error means something bad. For now, just close the socket. @@ -1130,8 +1126,8 @@ void LLVivoxVoiceClient::stateMachine() } else { - // loop mic back to render device. - tuningCaptureStartSendMessage(1); // 1-loop, zero, don't loop + // duration parameter is currently unused, per Mike S. + tuningCaptureStartSendMessage(10000); setState(stateMicTuningRunning); } @@ -1568,8 +1564,6 @@ void LLVivoxVoiceClient::stateMachine() //MARK: stateSessionJoined case stateSessionJoined: // session handle received - if (mSpatialJoiningNum > 100) - llwarns << "There seems to be problem with connecting to a voice channel. Frames to join were " << mSpatialJoiningNum << LL_ENDL; mSpatialJoiningNum = 0; // It appears that I need to wait for BOTH the SessionGroup.AddSession response and the SessionStateChangeEvent with state 4 @@ -1668,7 +1662,7 @@ void LLVivoxVoiceClient::stateMachine() //MARK: stateLeavingSession case stateLeavingSession: // waiting for terminate session response // The handler for the Session.Terminate response will transition from here to stateSessionTerminated. - // Fall through and clean up session before getting terminated event. + break; //MARK: stateSessionTerminated case stateSessionTerminated: @@ -1678,7 +1672,6 @@ void LLVivoxVoiceClient::stateMachine() if(mAudioSession) { - leaveAudioSession(); sessionState *oldSession = mAudioSession; mAudioSession = NULL; @@ -1838,7 +1831,6 @@ void LLVivoxVoiceClient::loginSendMessage() << "" << mAccountPassword << "" << "VerifyAnswer" << "false" - << "0" << "Application" << "5" << (autoPostCrashDumps?"true":"") @@ -2039,7 +2031,6 @@ void LLVivoxVoiceClient::leaveAudioSession() case stateJoiningSession: case stateSessionJoined: case stateRunning: - case stateSessionTerminated: if(!mAudioSession->mHandle.empty()) { @@ -2070,12 +2061,10 @@ void LLVivoxVoiceClient::leaveAudioSession() case stateJoinSessionFailed: case stateJoinSessionFailedWaiting: setState(stateSessionTerminated); - break; - case stateLeavingSession: // managed to get back to this case statement before the media gets disconnected. break; default: - LL_WARNS("Voice") << "called from unknown state " << getState() << LL_ENDL; + LL_WARNS("Voice") << "called from unknown state" << LL_ENDL; break; } } @@ -2128,7 +2117,6 @@ void LLVivoxVoiceClient::sessionMediaDisconnectSendMessage(sessionState *session } -/* obsolete void LLVivoxVoiceClient::sessionTextDisconnectSendMessage(sessionState *session) { std::ostringstream stream; @@ -2142,7 +2130,6 @@ void LLVivoxVoiceClient::sessionTextDisconnectSendMessage(sessionState *session) writeString(stream.str()); } -*/ void LLVivoxVoiceClient::getCaptureDevicesSendMessage() { @@ -2294,15 +2281,14 @@ void LLVivoxVoiceClient::tuningRenderStopSendMessage() writeString(stream.str()); } -void LLVivoxVoiceClient::tuningCaptureStartSendMessage(int loop) +void LLVivoxVoiceClient::tuningCaptureStartSendMessage(int duration) { LL_DEBUGS("Voice") << "sending CaptureAudioStart" << LL_ENDL; std::ostringstream stream; stream << "" - << "-1" - << "" << loop << "" + << "" << duration << "" << "\n\n\n"; writeString(stream.str()); @@ -2516,8 +2502,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) { LLVector3 l, u, a, vel; @@ -2950,25 +2934,15 @@ void LLVivoxVoiceClient::sessionGroupAddSessionResponse(std::string &requestId, void LLVivoxVoiceClient::sessionConnectResponse(std::string &requestId, int statusCode, std::string &statusString) { 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) - { - session->mVoiceEnabled = true; - session->mMediaConnectInProgress = false; - session->mMediaStreamState = streamStateConnected; - //session->mTextStreamState = streamStateConnected; - session->mErrorStatusCode = 0; - } - else if (statusCode != 0) + if(statusCode != 0) { LL_WARNS("Voice") << "Session.Connect response failure (" << statusCode << "): " << statusString << LL_ENDL; - if (session) + if(session) { session->mMediaConnectInProgress = false; session->mErrorStatusCode = statusCode; session->mErrorStatusString = statusString; - if (session == mAudioSession) + if(session == mAudioSession) setState(stateJoinSessionFailed); } } @@ -3164,7 +3138,7 @@ void LLVivoxVoiceClient::sessionRemovedEvent( // Reset the media state (we now have no info) session->mMediaStreamState = streamStateUnknown; - //session->mTextStreamState = streamStateUnknown; + session->mTextStreamState = streamStateUnknown; // Conditionally delete the session reapSession(session); @@ -3375,9 +3349,8 @@ void LLVivoxVoiceClient::mediaStreamUpdatedEvent( switch(state) { - case streamStateDisconnecting: case streamStateIdle: - // Standard "left audio session", Vivox state 'disconnected' + // Standard "left audio session" session->mVoiceEnabled = false; session->mMediaConnectInProgress = false; leftAudioSession(session); @@ -3387,7 +3360,6 @@ void LLVivoxVoiceClient::mediaStreamUpdatedEvent( session->mVoiceEnabled = true; session->mMediaConnectInProgress = false; joinedAudioSession(session); - case streamStateConnecting: // do nothing, but prevents a warning getting into the logs. break; case streamStateRinging: @@ -3422,7 +3394,6 @@ void LLVivoxVoiceClient::mediaStreamUpdatedEvent( } } -/* Obsolete void LLVivoxVoiceClient::textStreamUpdatedEvent( std::string &sessionHandle, std::string &sessionGroupHandle, @@ -3469,7 +3440,6 @@ void LLVivoxVoiceClient::textStreamUpdatedEvent( } } } - obsolete */ void LLVivoxVoiceClient::participantAddedEvent( std::string &sessionHandle, @@ -4290,7 +4260,7 @@ LLVivoxVoiceClient::sessionState* LLVivoxVoiceClient::startUserIMSession(const L if(session->mHandle.empty()) { // Session isn't active -- start it up. - sessionCreateSendMessage(session, false, false); + sessionCreateSendMessage(session, false, true); } else { @@ -4301,7 +4271,6 @@ LLVivoxVoiceClient::sessionState* LLVivoxVoiceClient::startUserIMSession(const L return session; } -/* obsolete BOOL LLVivoxVoiceClient::sendTextMessage(const LLUUID& participant_id, const std::string& message) { bool result = false; @@ -4326,8 +4295,7 @@ BOOL LLVivoxVoiceClient::sendTextMessage(const LLUUID& participant_id, const std return result; } -*/ -/* obsolete + void LLVivoxVoiceClient::sendQueuedTextMessages(sessionState *session) { if(session->mTextStreamState == 1) @@ -4356,9 +4324,7 @@ void LLVivoxVoiceClient::sendQueuedTextMessages(sessionState *session) // Session isn't connected yet, defer until later. } } - obsolete */ -/* void LLVivoxVoiceClient::endUserIMSession(const LLUUID &uuid) { // Figure out if a session with the user exists @@ -4368,7 +4334,7 @@ void LLVivoxVoiceClient::endUserIMSession(const LLUUID &uuid) // found the session if(!session->mHandle.empty()) { - // sessionTextDisconnectSendMessage(session); // a SLim leftover, not used any more. + sessionTextDisconnectSendMessage(session); } } else @@ -4376,7 +4342,6 @@ void LLVivoxVoiceClient::endUserIMSession(const LLUUID &uuid) LL_DEBUGS("Voice") << "Session not found for participant ID " << uuid << LL_ENDL; } } -*/ bool LLVivoxVoiceClient::isValidChannel(std::string &sessionHandle) { return(findSession(sessionHandle) != NULL); @@ -4720,8 +4685,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()) @@ -6837,10 +6800,6 @@ void LLVivoxProtocolParser::processResponse(std::string tag) { LLVivoxVoiceClient::getInstance()->sessionRemovedEvent(sessionHandle, sessionGroupHandle); } - else if (!stricmp(eventTypeCstr, "SessionGroupUpdatedEvent")) - { - //TODO, we don't process this event, but we should not WARN that we have received it. - } else if (!stricmp(eventTypeCstr, "SessionGroupAddedEvent")) { LLVivoxVoiceClient::getInstance()->sessionGroupAddedEvent(sessionGroupHandle); @@ -6869,11 +6828,19 @@ 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")) { + /* + + c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg1 + c1_m1000xFnPP04IpREWNkuw1cOXlhw==1 + true + 1 + true + + */ LLVivoxVoiceClient::getInstance()->textStreamUpdatedEvent(sessionHandle, sessionGroupHandle, enabled, state, incoming); - } */ + } else if (!stricmp(eventTypeCstr, "ParticipantAddedEvent")) { /* diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index ad7df8960..2d723184b 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -92,10 +92,10 @@ public: virtual bool isParticipant(const LLUUID& speaker_id); // 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; } + virtual BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message); // close any existing text IM session with the specified user - //virtual void endUserIMSession(const LLUUID &uuid); + virtual void endUserIMSession(const LLUUID &uuid); // 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. @@ -242,8 +242,6 @@ protected: streamStateIdle = 1, streamStateConnected = 2, streamStateRinging = 3, - streamStateConnecting = 6, // same as Vivox session_media_connecting enum - streamStateDisconnecting = 7, //Same as Vivox session_media_disconnecting enum }; struct participantState { @@ -434,7 +432,7 @@ protected: void tuningRenderStartSendMessage(const std::string& name, bool loop); void tuningRenderStopSendMessage(); - void tuningCaptureStartSendMessage(int loop); + void tuningCaptureStartSendMessage(int duration); void tuningCaptureStopSendMessage(); //---------------------------------- @@ -465,7 +463,7 @@ protected: void accountLoginStateChangeEvent(std::string &accountHandle, int statusCode, std::string &statusString, int state); void mediaCompletionEvent(std::string &sessionGroupHandle, std::string &mediaCompletionType); void mediaStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, int statusCode, std::string &statusString, int state, bool incoming); - // obsolete void textStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, bool enabled, 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); @@ -581,7 +579,7 @@ protected: void sessionTerminateSendMessage(sessionState *session); void sessionGroupTerminateSendMessage(sessionState *session); void sessionMediaDisconnectSendMessage(sessionState *session); - // void sessionTextDisconnectSendMessage(sessionState *session); + void sessionTextDisconnectSendMessage(sessionState *session); @@ -743,7 +741,7 @@ private: // 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); - // obsolete void sendQueuedTextMessages(sessionState *session); + void sendQueuedTextMessages(sessionState *session); void enforceTether(void); diff --git a/indra/newview/skins/default/xui/en-us/panel_sound_devices.xml b/indra/newview/skins/default/xui/en-us/panel_sound_devices.xml index b805e16ec..eb6f6a035 100644 --- a/indra/newview/skins/default/xui/en-us/panel_sound_devices.xml +++ b/indra/newview/skins/default/xui/en-us/panel_sound_devices.xml @@ -43,7 +43,7 @@ + tool_tip="Change the volume using this slider" width="120" /> Please wait