diff options
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/llimpanel.cpp | 24 | ||||
-rw-r--r-- | indra/newview/llimpanel.h | 4 | ||||
-rw-r--r-- | indra/newview/llvoiceclient.cpp | 240 | ||||
-rw-r--r-- | indra/newview/llvoiceclient.h | 20 |
4 files changed, 259 insertions, 29 deletions
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index f3943345c7..fcebfa7053 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -1120,6 +1120,9 @@ LLFloaterIMPanel::LLFloaterIMPanel( mSentTypingState(TRUE), mShowSpeakersOnConnect(TRUE), mAutoConnect(FALSE), + mTextIMPossible(TRUE), + mProfileButtonEnabled(TRUE), + mCallBackEnabled(TRUE), mSpeakers(NULL), mSpeakerPanel(NULL), mFirstKeystrokeTimer(), @@ -1165,7 +1168,13 @@ void LLFloaterIMPanel::init(const std::string& session_label) break; // just received text from another user case IM_NOTHING_SPECIAL: + xml_filename = "floater_instant_message.xml"; + + mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionUUID); + mProfileButtonEnabled = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionUUID); + mCallBackEnabled = LLVoiceClient::getInstance()->isSessionCallBackPossible(mSessionUUID); + mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, mSessionLabel, mOtherParticipantUUID); break; default: @@ -1297,6 +1306,11 @@ BOOL LLFloaterIMPanel::postBuild() { childSetEnabled("profile_btn", FALSE); } + + if(!mProfileButtonEnabled) + { + childSetEnabled("profile_callee_btn", FALSE); + } sTitleString = getString("title_string"); sTypingStartString = getString("typing_start_string"); @@ -1365,7 +1379,8 @@ void LLFloaterIMPanel::draw() BOOL enable_connect = (region && region->getCapability("ChatSessionRequest") != "") && mSessionInitialized - && LLVoiceClient::voiceEnabled(); + && LLVoiceClient::voiceEnabled() + && mCallBackEnabled; // hide/show start call and end call buttons childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() >= LLVoiceChannel::STATE_CALL_STARTED); @@ -1374,7 +1389,12 @@ void LLFloaterIMPanel::draw() childSetEnabled("send_btn", !childGetValue("chat_editor").asString().empty()); LLPointer<LLSpeaker> self_speaker = mSpeakers->findSpeaker(gAgent.getID()); - if (self_speaker.notNull() && self_speaker->mModeratorMutedText) + if(!mTextIMPossible) + { + mInputEditor->setEnabled(FALSE); + mInputEditor->setLabel(getString("unavailable_text_label")); + } + else if (self_speaker.notNull() && self_speaker->mModeratorMutedText) { mInputEditor->setEnabled(FALSE); mInputEditor->setLabel(getString("muted_text_label")); diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index e54cec56c7..8b3ca202c7 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -343,6 +343,10 @@ private: BOOL mShowSpeakersOnConnect; BOOL mAutoConnect; + + BOOL mTextIMPossible; + BOOL mProfileButtonEnabled; + BOOL mCallBackEnabled; LLIMSpeakerMgr* mSpeakers; LLPanelActiveSpeakers* mSpeakerPanel; diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 3bcc0af7d5..94407ed08c 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -844,6 +844,16 @@ 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")) + { + /* + <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 { LL_WARNS("VivoxProtocolParser") << "Unknown event type " << eventTypeString << LL_ENDL; @@ -1560,20 +1570,27 @@ void LLVoiceClient::stateMachine() std::string regionName = region->getName(); std::string capURI = region->getCapability("ParcelVoiceInfoRequest"); -// LL_DEBUGS("Voice") << "Region name = \"" << regionName <<"\", " << "parcel local ID = " << parcelLocalID << LL_ENDL; +// LL_DEBUGS("Voice") << "Region name = \"" << regionName << "\", parcel local ID = " << parcelLocalID << ", cap URI = \"" << capURI << "\"" << LL_ENDL; // The region name starts out empty and gets filled in later. // Also, the cap gets filled in a short time after the region cross, but a little too late for our purposes. // If either is empty, wait for the next time around. - if(!regionName.empty() && !capURI.empty()) + if(!regionName.empty()) { - if((parcelLocalID != mCurrentParcelLocalID) || (regionName != mCurrentRegionName)) + if(!capURI.empty()) { - // We have changed parcels. Initiate a parcel channel lookup. - mCurrentParcelLocalID = parcelLocalID; - mCurrentRegionName = regionName; - - parcelChanged(); + if((parcelLocalID != mCurrentParcelLocalID) || (regionName != mCurrentRegionName)) + { + // We have changed parcels. Initiate a parcel channel lookup. + mCurrentParcelLocalID = parcelLocalID; + mCurrentRegionName = regionName; + + parcelChanged(); + } + } + else + { + LL_WARNS("Voice") << "region doesn't have ParcelVoiceInfoRequest capability. This is normal for a short time after teleporting, but bad if it persists for very long." << LL_ENDL; } } } @@ -1840,6 +1857,10 @@ void LLVoiceClient::stateMachine() } setState(stateConnectorStart); } + else + { + LL_WARNS("Voice") << "region doesn't have ProvisionVoiceAccountRequest capability!" << LL_ENDL; + } } } break; @@ -2308,12 +2329,27 @@ void LLVoiceClient::stateMachine() //MARK: stateLoggingOut case stateLoggingOut: // waiting for logout response - // The handler for the Account.Logout response will transition from here to stateLoggedOut. + // The handler for the AccountLoginStateChangeEvent will transition from here to stateLoggedOut. break; + //MARK: stateLoggedOut case stateLoggedOut: // logout response received - // shut down the connector - connectorShutdown(); + + // Once we're logged out, all these things are invalid. + mAccountHandle.clear(); + deleteAllSessions(); + deleteAllBuddies(); + + if(mVoiceEnabled && !mRelogRequested) + { + // User was logged out, but wants to be logged in. Send a new login request. + setState(stateNeedsLogin); + } + else + { + // shut down the connector + connectorShutdown(); + } break; //MARK: stateConnectorStopping @@ -2332,6 +2368,10 @@ void LLVoiceClient::stateMachine() break; //MARK: stateConnectorFailedWaiting case stateConnectorFailedWaiting: + if(!mVoiceEnabled) + { + setState(stateDisableCleanup); + } break; //MARK: stateLoginFailed @@ -2340,7 +2380,10 @@ void LLVoiceClient::stateMachine() break; //MARK: stateLoginFailedWaiting case stateLoginFailedWaiting: - // No way to recover from these. Yet. + if(!mVoiceEnabled) + { + setState(stateDisableCleanup); + } break; //MARK: stateJoinSessionFailed @@ -2689,6 +2732,19 @@ void LLVoiceClient::sessionTerminateSendMessage(sessionState *session) writeString(stream.str()); } +void LLVoiceClient::sessionGroupTerminateSendMessage(sessionState *session) +{ + std::ostringstream stream; + + LL_DEBUGS("Voice") << "Sending SessionGroup.Terminate with handle " << session->mGroupHandle << LL_ENDL; + stream + << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.Terminate.1\">" + << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>" + << "</Request>\n\n\n"; + + writeString(stream.str()); +} + void LLVoiceClient::sessionMediaDisconnectSendMessage(sessionState *session) { std::ostringstream stream; @@ -3227,14 +3283,23 @@ void LLVoiceClient::sendPositionalUpdate(void) // Can't set volume/mute for yourself if(!p->mIsSelf) { - int volume = p->mUserVolume; + int volume = 56; // nominal default value bool mute = p->mOnMuteList; + + if(p->mUserVolume != -1) + { + // scale from user volume in the range 0-400 (with 100 as "normal") to vivox volume in the range 0-100 (with 56 as "normal") + if(p->mUserVolume < 100) + volume = (p->mUserVolume * 56) / 100; + else + volume = (((p->mUserVolume - 100) * (100 - 56)) / 300) + 56; + } + else if(p->mVolume != -1) + { + // Use the previously reported internal volume (comes in with a ParticipantUpdatedEvent) + volume = p->mVolume; + } - // SLIM SDK: scale volume from 0-400 (with 100 as "normal") to 0-100 (with 56 as "normal") - if(volume < 100) - volume = (volume * 56) / 100; - else - volume = (((volume - 100) * (100 - 56)) / 300) + 56; if(mute) { @@ -3813,11 +3878,6 @@ void LLVoiceClient::logoutResponse(int statusCode, std::string &statusString) LL_WARNS("Voice") << "Account.Logout response failure: " << statusString << LL_ENDL; // Should this ever fail? do we care if it does? } - - if(getState() == stateLoggingOut) - { - setState(stateLoggedOut); - } } void LLVoiceClient::connectorShutdownResponse(int statusCode, std::string &statusString) @@ -3990,6 +4050,10 @@ void LLVoiceClient::sessionRemovedEvent( // This message invalidates the session's handle. Set it to empty. setSessionHandle(session); + // This also means that the session's session group is now empty. + // Terminate the session group so it doesn't leak. + sessionGroupTerminateSendMessage(session); + // Reset the media state (we now have no info) session->mMediaStreamState = streamStateUnknown; session->mTextStreamState = streamStateUnknown; @@ -4131,6 +4195,16 @@ void LLVoiceClient::accountLoginStateChangeEvent( setState(stateLoggedIn); } break; + + case 3: + // The user is in the process of logging out. + setState(stateLoggingOut); + break; + + case 0: + // The user has been logged out. + setState(stateLoggedOut); + break; default: //Used to be a commented out warning @@ -4756,9 +4830,9 @@ LLVoiceClient::participantState::participantState(const std::string &uri) : mIsModeratorMuted(false), mLastSpokeTimestamp(0.f), mPower(0.f), - mVolume(0), + mVolume(-1), mOnMuteList(false), - mUserVolume(100), + mUserVolume(-1), mVolumeDirty(false), mAvatarIDValid(false), mIsSelf(false) @@ -4843,6 +4917,11 @@ bool LLVoiceClient::participantState::updateMuteState() return result; } +bool LLVoiceClient::participantState::isAvatar() +{ + return mAvatarIDValid; +} + void LLVoiceClient::sessionState::removeParticipant(LLVoiceClient::participantState *participant) { if(participant) @@ -5276,6 +5355,66 @@ bool LLVoiceClient::isOnlineSIP(const LLUUID &id) return result; } +// Returns true if the indicated participant in the current audio session is really an SL avatar. +// Currently this will be false only for PSTN callers into group chats, and PSTN p2p calls. +bool LLVoiceClient::isParticipantAvatar(const LLUUID &id) +{ + bool result = true; + sessionState *session = findSession(id); + + if(session != NULL) + { + // this is a p2p session with the indicated caller, or the session with the specified UUID. + if(session->mSynthesizedCallerID) + result = false; + } + else + { + // Didn't find a matching session -- check the current audio session for a matching participant + if(mAudioSession != NULL) + { + participantState *participant = findParticipantByID(id); + if(participant != NULL) + { + result = participant->isAvatar(); + } + } + } + + return result; +} + +// 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. +bool LLVoiceClient::isSessionCallBackPossible(const LLUUID &session_id) +{ + bool result = true; + sessionState *session = findSession(session_id); + + if(session != NULL) + { + result = session->isCallBackPossible(); + } + + return result; +} + +// Returns true if the session can accepte text IM's. +// Currently this will be false only for PSTN P2P calls. +bool LLVoiceClient::isSessionTextIMPossible(const LLUUID &session_id) +{ + bool result = true; + sessionState *session = findSession(session_id); + + if(session != NULL) + { + result = session->isTextIMPossible(); + } + + return result; +} + + void LLVoiceClient::declineInvite(std::string &sessionHandle) { sessionState *session = findSession(sessionHandle); @@ -5928,10 +6067,42 @@ F32 LLVoiceClient::getUserVolume(const LLUUID& id) participantState *participant = findParticipantByID(id); if(participant) { - S32 ires = participant->mUserVolume; // 0-400 + S32 ires = 100; // nominal default volume + + if(participant->mIsSelf) + { + // Always make it look like the user's own volume is set at the default. + } + else if(participant->mUserVolume != -1) + { + // Use the internal volume + ires = participant->mUserVolume; + + // Enable this when debugging voice slider issues. It's way to spammy even for debug-level logging. +// LL_DEBUGS("Voice") << "mapping from mUserVolume " << ires << LL_ENDL; + } + else if(participant->mVolume != -1) + { + // Map backwards from vivox volume + + // Enable this when debugging voice slider issues. It's way to spammy even for debug-level logging. +// LL_DEBUGS("Voice") << "mapping from mVolume " << participant->mVolume << LL_ENDL; + + if(participant->mVolume < 56) + { + ires = (participant->mVolume * 100) / 56; + } + else + { + ires = (((participant->mVolume - 56) * 300) / (100 - 56)) + 100; + } + } result = sqrtf(((F32)ires) / 400.f); } + // Enable this when debugging voice slider issues. It's way to spammy even for debug-level logging. +// LL_DEBUGS("Voice") << "returning " << result << LL_ENDL; + return result; } @@ -6095,6 +6266,21 @@ LLVoiceClient::sessionState::~sessionState() removeAllParticipants(); } +bool LLVoiceClient::sessionState::isCallBackPossible() +{ + // This may change to be explicitly specified by vivox in the future... + // Currently, only PSTN P2P calls cannot be returned. + // Conveniently, this is also the only case where we synthesize a caller UUID. + return !mSynthesizedCallerID; +} + +bool LLVoiceClient::sessionState::isTextIMPossible() +{ + // This may change to be explicitly specified by vivox in the future... + return !mSynthesizedCallerID; +} + + LLVoiceClient::sessionIterator LLVoiceClient::sessionsBegin(void) { return mSessions.begin(); @@ -6141,7 +6327,7 @@ LLVoiceClient::sessionState *LLVoiceClient::findSession(const LLUUID &participan for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++) { sessionState *session = *iter; - if(session->mCallerID == participant_id) + if((session->mCallerID == participant_id) || (session->mIMSessionID == participant_id)) { result = session; break; diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 43bbc8e29c..cfc336b27d 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -255,6 +255,7 @@ static void updatePosition(void); participantState(const std::string &uri); bool updateMuteState(); + bool isAvatar(); std::string mURI; LLUUID mAvatarID; @@ -301,6 +302,9 @@ static void updatePosition(void); participantState *findParticipant(const std::string &uri); participantState *findParticipantByID(const LLUUID& id); + bool isCallBackPossible(); + bool isTextIMPossible(); + std::string mHandle; std::string mGroupHandle; std::string mSIPURI; @@ -434,6 +438,7 @@ static void updatePosition(void); 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); @@ -496,6 +501,21 @@ static void updatePosition(void); // 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); + + // 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: |