summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Savchuk <vsavchuk@productengine.com>2009-12-25 20:47:42 +0200
committerVadim Savchuk <vsavchuk@productengine.com>2009-12-25 20:47:42 +0200
commit614a214870e223ea187bda32169a1859380844d3 (patch)
tree6b60aa4b128aaf74cdeeba368b166d899506a087
parent87aad0fe2177ab863704e5432435a0657277fb92 (diff)
parent38742b462a222cf97d67b2f2e866d225a4000c1d (diff)
merge
--HG-- branch : product-engine
-rw-r--r--indra/newview/llavatarlist.cpp6
-rw-r--r--indra/newview/llavatarlist.h1
-rw-r--r--indra/newview/llcallfloater.cpp74
-rw-r--r--indra/newview/llcallfloater.h16
-rw-r--r--indra/newview/llparticipantlist.cpp28
-rw-r--r--indra/newview/llparticipantlist.h28
6 files changed, 108 insertions, 45 deletions
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 5317cf2cd0..b3ef6464f6 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -51,6 +51,12 @@ static const F32 LIT_UPDATE_PERIOD = 5;
// Used to limit time spent for avatar list update per frame.
static const unsigned ADD_LIMIT = 50;
+bool LLAvatarList::contains(const LLUUID& id)
+{
+ const uuid_vector_t& ids = getIDs();
+ return std::find(ids.begin(), ids.end(), id) != ids.end();
+}
+
void LLAvatarList::toggleIcons()
{
// Save the new value for new items to use.
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index e913be0f62..0d2ce884ae 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -75,6 +75,7 @@ public:
void setNameFilter(const std::string& filter);
void setDirty(bool val = true) { mDirty = val; }
uuid_vector_t& getIDs() { return mIDs; }
+ bool contains(const LLUUID& id);
void setContextMenu(LLAvatarListItem::ContextMenu* menu) { mContextMenu = menu; }
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index 1c65eaba9c..581890c4fd 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -48,6 +48,7 @@
#include "llspeakers.h"
#include "lltransientfloatermgr.h"
+static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids);
class LLNonAvatarCaller : public LLAvatarListItem
{
@@ -98,7 +99,7 @@ BOOL LLCallFloater::LLAvatarListItemRemoveTimer::tick()
LLCallFloater::LLCallFloater(const LLSD& key)
: LLDockableFloater(NULL, false, key)
, mSpeakerManager(NULL)
-, mPaticipants(NULL)
+, mParticipants(NULL)
, mAvatarList(NULL)
, mNonAvatarCaller(NULL)
, mVoiceType(VC_LOCAL_CHAT)
@@ -120,8 +121,8 @@ LLCallFloater::~LLCallFloater()
{
resetVoiceRemoveTimers();
- delete mPaticipants;
- mPaticipants = NULL;
+ delete mParticipants;
+ mParticipants = NULL;
mAvatarListRefreshConnection.disconnect();
@@ -185,8 +186,8 @@ void LLCallFloater::draw()
}
// Need to resort the participant list if it's in sort by recent speaker order.
- if (mPaticipants)
- mPaticipants->updateRecentSpeakersOrder();
+ if (mParticipants)
+ mParticipants->updateRecentSpeakersOrder();
LLDockableFloater::draw();
}
@@ -194,9 +195,17 @@ void LLCallFloater::draw()
// virtual
void LLCallFloater::onChange()
{
- if (NULL == mPaticipants) return;
+ if (NULL == mParticipants) return;
updateParticipantsVoiceState();
+
+ // Add newly joined participants.
+ std::vector<LLUUID> speakers_uuids;
+ get_voice_participants_uuids(speakers_uuids);
+ for (std::vector<LLUUID>::const_iterator it = speakers_uuids.begin(); it != speakers_uuids.end(); it++)
+ {
+ mParticipants->addAvatarIDExceptAgent(*it);
+ }
}
@@ -277,7 +286,7 @@ void LLCallFloater::updateSession()
bool is_local_chat = mVoiceType == VC_LOCAL_CHAT;
childSetVisible("leave_call_btn", !is_local_chat);
- refreshPartisipantList();
+ refreshParticipantList();
updateAgentModeratorState();
//show floater for voice calls
@@ -292,7 +301,7 @@ void LLCallFloater::updateSession()
}
}
-void LLCallFloater::refreshPartisipantList()
+void LLCallFloater::refreshParticipantList()
{
// lets forget states from the previous session
// for timers...
@@ -301,8 +310,8 @@ void LLCallFloater::refreshPartisipantList()
// ...and for speaker state
mSpeakerStateMap.clear();
- delete mPaticipants;
- mPaticipants = NULL;
+ delete mParticipants;
+ mParticipants = NULL;
mAvatarList->clear();
bool non_avatar_caller = false;
@@ -322,7 +331,8 @@ void LLCallFloater::refreshPartisipantList()
if (!non_avatar_caller)
{
- mPaticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT);
+ mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT);
+ mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1));
if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager)
{
@@ -447,7 +457,7 @@ void LLCallFloater::updateAgentModeratorState()
mAgentPanel->childSetValue("user_text", name);
}
-void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids)
+static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids)
{
// Get a list of participants from VoiceClient
LLVoiceClient::participantMap *voice_map = gVoiceClient->getParticipantList();
@@ -560,13 +570,23 @@ void LLCallFloater::updateParticipantsVoiceState()
// HAS LEFT the call.
if ((getState(participant_id) == STATE_JOINED))
{
- setState(item, STATE_LEFT);
-
- LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(item->getAvatarId());
- if (speaker.isNull())
- continue;
-
- speaker->mHasLeftCurrentCall = TRUE;
+ if (mVoiceType == VC_LOCAL_CHAT)
+ {
+ // Don't display avatars that aren't in our nearby chat range anymore as "left". Remove them immediately.
+ removeVoiceLeftParticipant(participant_id);
+ }
+ else
+ {
+ setState(item, STATE_LEFT);
+
+ LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(item->getAvatarId());
+ if (speaker.isNull())
+ {
+ continue;
+ }
+
+ 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
@@ -575,9 +595,12 @@ void LLCallFloater::updateParticipantsVoiceState()
{
setState(item, STATE_INVITED);
}
+ else
+ {
+ llwarns << "Unsupported (" << getState(participant_id) << ") state: " << item->getAvatarName() << llendl;
+ }
}
}
-
}
void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state)
@@ -684,4 +707,15 @@ void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id)
}
}
+bool LLCallFloater::validateSpeaker(const LLUUID& speaker_id)
+{
+ if (mVoiceType != VC_LOCAL_CHAT)
+ return true;
+
+ // 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();
+}
+
//EOF
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
index ee3bc9b9fe..3df9e333c5 100644
--- a/indra/newview/llcallfloater.h
+++ b/indra/newview/llcallfloater.h
@@ -108,7 +108,7 @@ private:
/**
* Refreshes participant list according to current Voice Channel
*/
- void refreshPartisipantList();
+ void refreshParticipantList();
/**
* Handles event on avatar list is refreshed after it was marked dirty.
@@ -127,7 +127,7 @@ private:
/**
* Sets initial participants voice states in avatar list (Invited, Joined, Has Left).
*
- * @see refreshPartisipantList()
+ * @see refreshParticipantList()
* @see onAvatarListRefreshed()
* @see mInitParticipantsVoiceState
*/
@@ -182,10 +182,20 @@ private:
*/
void removeVoiceRemoveTimer(const LLUUID& voice_speaker_id);
+ /**
+ * Called by LLParticipantList before adding a speaker to the participant list.
+ *
+ * If false is returned, the speaker will not be added to the list.
+ *
+ * @param speaker_id Speaker to validate.
+ * @return true if this is a valid speaker, false otherwise.
+ */
+ bool validateSpeaker(const LLUUID& speaker_id);
+
private:
speaker_state_map_t mSpeakerStateMap;
LLSpeakerMgr* mSpeakerManager;
- LLParticipantList* mPaticipants;
+ LLParticipantList* mParticipants;
LLAvatarList* mAvatarList;
LLNonAvatarCaller* mNonAvatarCaller;
EVoiceControls mVoiceType;
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 54a837d17d..479c29f656 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -57,6 +57,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av
mSortOrder(E_SORT_BY_NAME)
, mParticipantListMenu(NULL)
, mExcludeAgent(exclude_agent)
+, mValidateSpeakerCallback(NULL)
{
mSpeakerAddListener = new SpeakerAddListener(*this);
mSpeakerRemoveListener = new SpeakerRemoveListener(*this);
@@ -86,22 +87,19 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av
}
//Lets fill avatarList with existing speakers
- LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
-
LLSpeakerMgr::speaker_list_t speaker_list;
mSpeakerMgr->getSpeakerList(&speaker_list, true);
for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++)
{
const LLPointer<LLSpeaker>& speakerp = *it;
- addAvatarIDExceptAgent(group_members, speakerp->mID);
+ addAvatarIDExceptAgent(speakerp->mID);
if ( speakerp->mIsModerator )
{
mModeratorList.insert(speakerp->mID);
}
}
// we need to exclude agent id for non group chat
- mAvatarList->setDirty(true);
sort();
}
@@ -208,6 +206,11 @@ LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder()
return mSortOrder;
}
+void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t cb)
+{
+ mValidateSpeakerCallback = cb;
+}
+
void LLParticipantList::updateRecentSpeakersOrder()
{
if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder())
@@ -221,19 +224,14 @@ void LLParticipantList::updateRecentSpeakersOrder()
bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
{
- LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
LLUUID uu_id = event->getValue().asUUID();
- LLAvatarList::uuid_vector_t::iterator found = std::find(group_members.begin(), group_members.end(), uu_id);
- if(found != group_members.end())
+ if (mValidateSpeakerCallback && mValidateSpeakerCallback(uu_id))
{
- llinfos << "Already got a buddy" << llendl;
return true;
}
- addAvatarIDExceptAgent(group_members, uu_id);
- // Mark AvatarList as dirty one
- mAvatarList->setDirty();
+ addAvatarIDExceptAgent(uu_id);
sort();
return true;
}
@@ -331,11 +329,13 @@ void LLParticipantList::sort()
}
}
-void LLParticipantList::addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id)
+void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
{
if (mExcludeAgent && gAgent.getID() == avatar_id) return;
+ if (mAvatarList->contains(avatar_id)) return;
- existing_list.push_back(avatar_id);
+ mAvatarList->getIDs().push_back(avatar_id);
+ mAvatarList->setDirty();
adjustParticipant(avatar_id);
}
@@ -355,7 +355,7 @@ bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::L
{
/**
* We need to filter speaking objects. These objects shouldn't appear in the list
- * @c LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy
+ * @see LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy
*/
const LLUUID& speaker_id = event->getValue().asUUID();
LLPointer<LLSpeaker> speaker = mParent.mSpeakerMgr->findSpeaker(speaker_id);
diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h
index c4eb180917..d15ec980db 100644
--- a/indra/newview/llparticipantlist.h
+++ b/indra/newview/llparticipantlist.h
@@ -44,6 +44,9 @@ class LLParticipantList
{
LOG_CLASS(LLParticipantList);
public:
+
+ typedef boost::function<bool (const LLUUID& speaker_id)> validate_speaker_callback_t;
+
LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu = true, bool exclude_agent = true);
~LLParticipantList();
void setSpeakingIndicatorsVisible(BOOL visible);
@@ -54,6 +57,13 @@ class LLParticipantList
} EParticipantSortOrder;
/**
+ * Adds specified avatar ID to the existing list if it is not Agent's ID
+ *
+ * @param[in] avatar_id - Avatar UUID to be added into the list
+ */
+ void addAvatarIDExceptAgent(const LLUUID& avatar_id);
+
+ /**
* Set and sort Avatarlist by given order
*/
void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME);
@@ -64,6 +74,15 @@ class LLParticipantList
*/
void updateRecentSpeakersOrder();
+ /**
+ * Set a callback to be called before adding a speaker. Invalid speakers will not be added.
+ *
+ * If the callback is unset all speakers are considered as valid.
+ *
+ * @see onAddItemEvent()
+ */
+ void setValidateSpeakerCallback(validate_speaker_callback_t cb);
+
protected:
/**
* LLSpeakerMgr event handlers
@@ -218,14 +237,6 @@ class LLParticipantList
void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param);
/**
- * Adds specified avatar ID to the existing list if it is not Agent's ID
- *
- * @param[in, out] existing_list - vector with avatars' UUIDs already in the list
- * @param[in] avatar_id - Avatar UUID to be added into the list
- */
- void addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id);
-
- /**
* Adjusts passed participant to work properly.
*
* Adds SpeakerMuteListener to process moderation actions.
@@ -260,4 +271,5 @@ class LLParticipantList
boost::signals2::connection mAvatarListReturnConnection;
LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers;
+ validate_speaker_callback_t mValidateSpeakerCallback;
};