summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llimpanel.cpp24
-rw-r--r--indra/newview/llimpanel.h4
-rw-r--r--indra/newview/llvoiceclient.cpp240
-rw-r--r--indra/newview/llvoiceclient.h20
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: