summaryrefslogtreecommitdiff
path: root/indra/newview/llcallfloater.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llcallfloater.cpp')
-rw-r--r--indra/newview/llcallfloater.cpp343
1 files changed, 140 insertions, 203 deletions
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index a402f59fa1..c8552de66a 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -43,15 +43,19 @@
#include "llavatariconctrl.h"
#include "llavatarlist.h"
#include "llbottomtray.h"
+#include "lldraghandle.h"
#include "llimfloater.h"
#include "llfloaterreg.h"
#include "llparticipantlist.h"
#include "llspeakers.h"
+#include "lltextutil.h"
#include "lltransientfloatermgr.h"
#include "llviewerwindow.h"
#include "llvoicechannel.h"
+#include "llviewerparcelmgr.h"
static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids);
+void reshape_floater(LLCallFloater* floater, S32 delta_height);
class LLNonAvatarCaller : public LLAvatarListItem
{
@@ -76,6 +80,12 @@ public:
return rv;
}
+ void setName(const std::string& name)
+ {
+ const std::string& formatted_phone = LLTextUtil::formatPhoneNumber(name);
+ LLAvatarListItem::setName(formatted_phone);
+ }
+
void setSpeakerId(const LLUUID& id) { mSpeakingIndicator->setSpeakerId(id); }
};
@@ -85,22 +95,6 @@ static void* create_non_avatar_caller(void*)
return new LLNonAvatarCaller;
}
-LLCallFloater::LLAvatarListItemRemoveTimer::LLAvatarListItemRemoveTimer(callback_t remove_cb, F32 period, const LLUUID& speaker_id)
-: LLEventTimer(period)
-, mRemoveCallback(remove_cb)
-, mSpeakerId(speaker_id)
-{
-}
-
-BOOL LLCallFloater::LLAvatarListItemRemoveTimer::tick()
-{
- if (mRemoveCallback)
- {
- mRemoveCallback(mSpeakerId);
- }
- return TRUE;
-}
-
LLVoiceChannel* LLCallFloater::sCurrentVoiceCanel = NULL;
LLCallFloater::LLCallFloater(const LLSD& key)
@@ -114,19 +108,22 @@ LLCallFloater::LLCallFloater(const LLSD& key)
, mSpeakingIndicator(NULL)
, mIsModeratorMutedVoice(false)
, mInitParticipantsVoiceState(false)
-, mVoiceLeftRemoveDelay(10)
{
static LLUICachedControl<S32> voice_left_remove_delay ("VoiceParticipantLeftRemoveDelay", 10);
- mVoiceLeftRemoveDelay = voice_left_remove_delay;
+ mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), voice_left_remove_delay);
mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);
LLVoiceClient::getInstance()->addObserver(this);
LLTransientFloaterMgr::getInstance()->addControlView(this);
+
+ // force docked state since this floater doesn't save it between recreations
+ setDocked(true);
}
LLCallFloater::~LLCallFloater()
{
resetVoiceRemoveTimers();
+ delete mSpeakerDelayRemover;
delete mParticipants;
mParticipants = NULL;
@@ -166,6 +163,13 @@ BOOL LLCallFloater::postBuild()
connectToChannel(LLVoiceChannel::getCurrentVoiceChannel());
+ setIsChrome(true);
+ //chrome="true" hides floater caption
+ if (mDragHandle)
+ mDragHandle->setTitleVisible(TRUE);
+
+ updateSession();
+
return TRUE;
}
@@ -217,16 +221,6 @@ void LLCallFloater::onChange()
}
}
-S32 LLCallFloater::notifyParent(const LLSD& info)
-{
- if("size_changes" == info["action"])
- {
- reshapeToFitContent();
- return 1;
- }
- return LLDockableFloater::notifyParent(info);
-}
-
//////////////////////////////////////////////////////////////////////////
/// PRIVATE SECTION
//////////////////////////////////////////////////////////////////////////
@@ -258,7 +252,7 @@ void LLCallFloater::updateSession()
}
}
- const LLUUID& session_id = voice_channel->getSessionID();
+ const LLUUID& session_id = voice_channel ? voice_channel->getSessionID() : LLUUID::null;
lldebugs << "Set speaker manager for session: " << session_id << llendl;
LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
@@ -270,6 +264,11 @@ void LLCallFloater::updateSession()
case IM_NOTHING_SPECIAL:
case IM_SESSION_P2P_INVITE:
mVoiceType = VC_PEER_TO_PEER;
+
+ if (!im_session->mOtherParticipantIsAvatar)
+ {
+ mVoiceType = VC_PEER_TO_PEER_AVALINE;
+ }
break;
case IM_SESSION_CONFERENCE_START:
case IM_SESSION_GROUP_START:
@@ -302,13 +301,15 @@ void LLCallFloater::updateSession()
//hide "Leave Call" button for nearby chat
bool is_local_chat = mVoiceType == VC_LOCAL_CHAT;
- childSetVisible("leave_call_btn", !is_local_chat);
-
+ childSetVisible("leave_call_btn_panel", !is_local_chat);
+
refreshParticipantList();
updateAgentModeratorState();
- //show floater for voice calls
- if (!is_local_chat)
+ //show floater for voice calls & only in CONNECTED to voice channel state
+ if (!is_local_chat &&
+ voice_channel &&
+ LLVoiceChannel::STATE_CONNECTED == voice_channel->getState())
{
LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
bool show_me = !(im_floater && im_floater->getVisible());
@@ -321,16 +322,13 @@ void LLCallFloater::updateSession()
void LLCallFloater::refreshParticipantList()
{
- bool non_avatar_caller = false;
- if (VC_PEER_TO_PEER == mVoiceType)
+ bool non_avatar_caller = VC_PEER_TO_PEER_AVALINE == mVoiceType;
+
+ if (non_avatar_caller)
{
LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSpeakerManager->getSessionID());
- non_avatar_caller = !session->mOtherParticipantIsAvatar;
- if (non_avatar_caller)
- {
- mNonAvatarCaller->setSpeakerId(session->mOtherParticipantID);
- mNonAvatarCaller->setName(session->mName);
- }
+ mNonAvatarCaller->setSpeakerId(session->mOtherParticipantID);
+ mNonAvatarCaller->setName(session->mName);
}
mNonAvatarCaller->setVisible(non_avatar_caller);
@@ -340,6 +338,7 @@ void LLCallFloater::refreshParticipantList()
{
mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT);
mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1));
+ mParticipants->setSortOrder(LLParticipantList::E_SORT_BY_RECENT_SPEAKERS);
if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager)
{
@@ -390,9 +389,17 @@ void LLCallFloater::updateTitle()
title = getString("title_nearby");
break;
case VC_PEER_TO_PEER:
+ case VC_PEER_TO_PEER_AVALINE:
{
+ title = voice_channel->getSessionName();
+
+ if (VC_PEER_TO_PEER_AVALINE == mVoiceType)
+ {
+ title = LLTextUtil::formatPhoneNumber(title);
+ }
+
LLStringUtil::format_map_t args;
- args["[NAME]"] = voice_channel->getSessionName();
+ args["[NAME]"] = title;
title = getString("title_peer_2_peer", args);
}
break;
@@ -570,33 +577,46 @@ void LLCallFloater::updateParticipantsVoiceState()
if (!found)
{
- // If an avatarID is not found in a speakers list from VoiceClient and
- // a panel with this ID has a JOINED status this means that this person
- // HAS LEFT the call.
- if ((getState(participant_id) == STATE_JOINED))
- {
- setState(item, STATE_LEFT);
+ updateNotInVoiceParticipantState(item);
+ }
+ }
+}
- LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(item->getAvatarId());
- if (speaker.isNull())
- {
- continue;
- }
+void LLCallFloater::updateNotInVoiceParticipantState(LLAvatarListItem* item)
+{
+ LLUUID participant_id = item->getAvatarId();
+ ESpeakerState current_state = getState(participant_id);
- speaker->mHasLeftCurrentCall = TRUE;
- }
- // If an avatarID is not found in a speakers list from VoiceClient and
- // a panel with this ID has a LEFT status this means that this person
- // HAS ENTERED session but it is not in voice chat yet. So, set INVITED status
- else if ((getState(participant_id) != STATE_LEFT))
- {
- setState(item, STATE_INVITED);
- }
- else
+ switch (current_state)
+ {
+ case STATE_JOINED:
+ // If an avatarID is not found in a speakers list from VoiceClient and
+ // a panel with this ID has a JOINED status this means that this person
+ // HAS LEFT the call.
+ setState(item, STATE_LEFT);
+
+ {
+ LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(participant_id);
+ if (speaker.notNull())
{
- llwarns << "Unsupported (" << getState(participant_id) << ") state: " << item->getAvatarName() << llendl;
+ speaker->mHasLeftCurrentCall = TRUE;
}
}
+ break;
+ case STATE_INVITED:
+ case STATE_LEFT:
+ // nothing to do. These states should not be changed.
+ break;
+ case STATE_UNKNOWN:
+ // If an avatarID is not found in a speakers list from VoiceClient and
+ // a panel with this ID has an UNKNOWN status this means that this person
+ // HAS ENTERED session but it is not in voice chat yet. So, set INVITED status
+ setState(item, STATE_INVITED);
+ break;
+ default:
+ // for possible new future states.
+ llwarns << "Unsupported (" << getState(participant_id) << ") state for: " << item->getAvatarName() << llendl;
+ break;
}
}
@@ -640,33 +660,11 @@ void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state)
void LLCallFloater::setVoiceRemoveTimer(const LLUUID& voice_speaker_id)
{
-
- // If there is already a started timer for the current panel don't do anything.
- bool no_timer_for_current_panel = true;
- if (mVoiceLeftTimersMap.size() > 0)
- {
- timers_map::iterator found_it = mVoiceLeftTimersMap.find(voice_speaker_id);
- if (found_it != mVoiceLeftTimersMap.end())
- {
- no_timer_for_current_panel = false;
- }
- }
-
- if (no_timer_for_current_panel)
- {
- // Starting a timer to remove an avatar row panel after timeout
- mVoiceLeftTimersMap.insert(timer_pair(voice_speaker_id,
- new LLAvatarListItemRemoveTimer(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), mVoiceLeftRemoveDelay, voice_speaker_id)));
- }
+ mSpeakerDelayRemover->setActionTimer(voice_speaker_id);
}
-void LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id)
+bool LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id)
{
- if (mVoiceLeftTimersMap.size() > 0)
- {
- mVoiceLeftTimersMap.erase(mVoiceLeftTimersMap.find(voice_speaker_id));
- }
-
LLAvatarList::uuid_vector_t& speaker_uuids = mAvatarList->getIDs();
LLAvatarList::uuid_vector_t::iterator pos = std::find(speaker_uuids.begin(), speaker_uuids.end(), voice_speaker_id);
if(pos != speaker_uuids.end())
@@ -674,45 +672,45 @@ void LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id)
speaker_uuids.erase(pos);
mAvatarList->setDirty();
}
+
+ return false;
}
void LLCallFloater::resetVoiceRemoveTimers()
{
- if (mVoiceLeftTimersMap.size() > 0)
- {
- for (timers_map::iterator iter = mVoiceLeftTimersMap.begin();
- iter != mVoiceLeftTimersMap.end(); ++iter)
- {
- delete iter->second;
- }
- }
- mVoiceLeftTimersMap.clear();
+ mSpeakerDelayRemover->removeAllTimers();
}
void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id)
{
- // Remove the timer if it has been already started
- if (mVoiceLeftTimersMap.size() > 0)
- {
- timers_map::iterator found_it = mVoiceLeftTimersMap.find(voice_speaker_id);
- if (found_it != mVoiceLeftTimersMap.end())
- {
- delete found_it->second;
- mVoiceLeftTimersMap.erase(found_it);
- }
- }
+ mSpeakerDelayRemover->unsetActionTimer(voice_speaker_id);
}
bool LLCallFloater::validateSpeaker(const LLUUID& speaker_id)
{
- if (mVoiceType != VC_LOCAL_CHAT)
- return true;
+ bool is_valid = true;
+ switch (mVoiceType)
+ {
+ case VC_LOCAL_CHAT:
+ {
+ // A nearby chat speaker is considered valid it it's known to LLVoiceClient (i.e. has enabled voice).
+ std::vector<LLUUID> speakers;
+ get_voice_participants_uuids(speakers);
+ is_valid = std::find(speakers.begin(), speakers.end(), speaker_id) != speakers.end();
+ }
+ break;
+ case VC_GROUP_CHAT:
+ // if participant had left this call before do not allow add her again. See EXT-4216.
+ // but if she Join she will be added into the list from the LLCallFloater::onChange()
+ is_valid = STATE_LEFT != getState(speaker_id);
+ break;
+ default:
+ // do nothing. required for Linux build
+ break;
+ }
- // A nearby chat speaker is considered valid it it's known to LLVoiceClient (i.e. has enabled voice).
- std::vector<LLUUID> speakers;
- get_voice_participants_uuids(speakers);
- return std::find(speakers.begin(), speakers.end(), speaker_id) != speakers.end();
+ return is_valid;
}
void LLCallFloater::connectToChannel(LLVoiceChannel* channel)
@@ -728,7 +726,15 @@ void LLCallFloater::connectToChannel(LLVoiceChannel* channel)
void LLCallFloater::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
{
- updateState(new_state);
+ // check is voice operational and if it doesn't work hide VCP (EXT-4397)
+ if(LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking())
+ {
+ updateState(new_state);
+ }
+ else
+ {
+ closeFloater();
+ }
}
void LLCallFloater::updateState(const LLVoiceChannel::EState& new_state)
@@ -740,11 +746,11 @@ void LLCallFloater::updateState(const LLVoiceChannel::EState& new_state)
}
else
{
- reset();
+ reset(new_state);
}
}
-void LLCallFloater::reset()
+void LLCallFloater::reset(const LLVoiceChannel::EState& new_state)
{
// lets forget states from the previous session
// for timers...
@@ -757,99 +763,30 @@ void LLCallFloater::reset()
mParticipants = NULL;
mAvatarList->clear();
- // update floater to show Loading while waiting for data.
- mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData"));
- mAvatarList->setVisible(TRUE);
- mNonAvatarCaller->setVisible(FALSE);
-
- mSpeakerManager = NULL;
-}
-
-void reshape_floater(LLCallFloater* floater, S32 delta_height)
-{
- // Try to update floater top side if it is docked(to bottom bar).
- // Try to update floater bottom side or top side if it is un-docked.
- // If world rect is too small, floater will not be reshaped at all.
-
- LLRect floater_rect = floater->getRect();
- LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
-
- // floater is docked to bottom bar
- if(floater->isDocked())
+ // These ifs were added instead of simply showing "loading" to make VCP work correctly in parcels
+ // with disabled voice (EXT-4648 and EXT-4649)
+ if (!LLViewerParcelMgr::getInstance()->allowAgentVoice() && LLVoiceChannel::STATE_HUNG_UP == new_state)
{
- // can update floater top side
- if(floater_rect.mTop + delta_height < world_rect.mTop)
- {
- floater_rect.set(floater_rect.mLeft, floater_rect.mTop + delta_height,
- floater_rect.mRight, floater_rect.mBottom);
- }
+ // hides "Leave Call" when call is ended in parcel with disabled voice- hiding usually happens in
+ // updateSession() which won't be called here because connect to nearby voice never happens
+ childSetVisible("leave_call_btn_panel", false);
+ // setting title to nearby chat an "no one near..." text- because in region with disabled
+ // voice we won't have chance to really connect to nearby, so VCP is changed here manually
+ setTitle(getString("title_nearby"));
+ mAvatarList->setNoItemsCommentText(getString("no_one_near"));
}
- // floater is un-docked
- else
+ // "loading" is shown only when state is "ringing" to avoid showing it in nearby chat vcp
+ // of parcels with disabled voice all the time- "no_one_near" is now shown there (EXT-4648)
+ else if (new_state == LLVoiceChannel::STATE_RINGING)
{
- // can update floater bottom side
- if( floater_rect.mBottom - delta_height >= world_rect.mBottom )
- {
- floater_rect.set(floater_rect.mLeft, floater_rect.mTop,
- floater_rect.mRight, floater_rect.mBottom - delta_height);
- }
- // could not update floater bottom side, check if we can update floater top side
- else if( floater_rect.mTop + delta_height < world_rect.mTop )
- {
- floater_rect.set(floater_rect.mLeft, floater_rect.mTop + delta_height,
- floater_rect.mRight, floater_rect.mBottom);
- }
+ // update floater to show Loading while waiting for data.
+ mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData"));
}
- floater->reshape(floater_rect.getWidth(), floater_rect.getHeight());
- floater->setRect(floater_rect);
-}
-
-void LLCallFloater::reshapeToFitContent()
-{
- const S32 ITEM_HEIGHT = getParticipantItemHeight();
- static const S32 MAX_VISIBLE_ITEMS = getMaxVisibleItems();
-
- static S32 items_pad = mAvatarList->getItemsPad();
- S32 list_height = mAvatarList->getRect().getHeight();
- S32 items_height = mAvatarList->getItemsRect().getHeight();
- if(items_height <= 0)
- {
- // make "no one near" text visible
- items_height = ITEM_HEIGHT + items_pad;
- }
- S32 max_list_height = MAX_VISIBLE_ITEMS * ITEM_HEIGHT + items_pad * (MAX_VISIBLE_ITEMS - 1);
- max_list_height += 2* mAvatarList->getBorderWidth();
-
- S32 delta = items_height - list_height;
- // too many items, don't reshape floater anymore, let scroll bar appear.
- if(items_height > max_list_height)
- {
- delta = max_list_height - list_height;
- }
-
- reshape_floater(this, delta);
-}
-
-S32 LLCallFloater::getParticipantItemHeight()
-{
- std::vector<LLPanel*> items;
- mAvatarList->getItems(items);
- if(items.size() > 0)
- {
- return items[0]->getRect().getHeight();
- }
- else
- {
- return getChild<LLPanel>("non_avatar_caller")->getRect().getHeight();
- }
-}
+ mAvatarList->setVisible(TRUE);
+ mNonAvatarCaller->setVisible(FALSE);
-S32 LLCallFloater::getMaxVisibleItems()
-{
- S32 value = 5; // default value, in case convertToS32() fails.
- LLStringUtil::convertToS32(getString("max_visible_items"), value);
- return value;
+ mSpeakerManager = NULL;
}
//EOF