diff options
author | Leyla Farazha <leyla@lindenlab.com> | 2010-04-16 14:51:15 -0700 |
---|---|---|
committer | Leyla Farazha <leyla@lindenlab.com> | 2010-04-16 14:51:15 -0700 |
commit | 663d8f7870c2858956aea8ab20129fd084a96dc8 (patch) | |
tree | 5ea7eaf40a018fbabaee165cc511998c5390f181 /indra/newview/llparticipantlist.cpp | |
parent | ba057d34cdc8fb91093aadaaad22618b6371cd0f (diff) | |
parent | 8cb7af4f73c0a703b5842a708e94d80aea26b6db (diff) |
Merge
Diffstat (limited to 'indra/newview/llparticipantlist.cpp')
-rw-r--r-- | indra/newview/llparticipantlist.cpp | 210 |
1 files changed, 208 insertions, 2 deletions
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 026be882ed..53f92f7ad1 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -50,6 +50,145 @@ static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR; +// See EXT-4301. +/** + * class LLAvalineUpdater - observe the list of voice participants in session and check + * presence of Avaline Callers among them. + * + * LLAvalineUpdater is a LLVoiceClientParticipantObserver. It provides two kinds of validation: + * - whether Avaline caller presence among participants; + * - whether watched Avaline caller still exists in voice channel. + * Both validations have callbacks which will notify subscriber if any of event occur. + * + * @see findAvalineCaller() + * @see checkIfAvalineCallersExist() + */ +class LLAvalineUpdater : public LLVoiceClientParticipantObserver +{ +public: + typedef boost::function<void(const LLUUID& speaker_id)> process_avaline_callback_t; + + LLAvalineUpdater(process_avaline_callback_t found_cb, process_avaline_callback_t removed_cb) + : mAvalineFoundCallback(found_cb) + , mAvalineRemovedCallback(removed_cb) + { + LLVoiceClient::getInstance()->addObserver(this); + } + ~LLAvalineUpdater() + { + if (LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->removeObserver(this); + } + } + + /** + * Adds UUID of Avaline caller to watch. + * + * @see checkIfAvalineCallersExist(). + */ + void watchAvalineCaller(const LLUUID& avaline_caller_id) + { + mAvalineCallers.insert(avaline_caller_id); + } + + void onChange() + { + uuid_set_t participant_uuids; + LLVoiceClient::getInstance()->getParticipantsUUIDSet(participant_uuids); + + + // check whether Avaline caller exists among voice participants + // and notify Participant List + findAvalineCaller(participant_uuids); + + // check whether watched Avaline callers still present among voice participant + // and remove if absents. + checkIfAvalineCallersExist(participant_uuids); + } + +private: + typedef std::set<LLUUID> uuid_set_t; + + /** + * Finds Avaline callers among voice participants and calls mAvalineFoundCallback. + * + * When Avatar is in group call with Avaline caller and then ends call Avaline caller stays + * in Group Chat floater (exists in LLSpeakerMgr). If Avatar starts call with that group again + * Avaline caller is added to voice channel AFTER Avatar is connected to group call. + * But Voice Control Panel (VCP) is filled from session LLSpeakerMgr and there is no information + * if a speaker is Avaline caller. + * + * In this case this speaker is created as avatar and will be recreated when it appears in + * Avatar's Voice session. + * + * @see LLParticipantList::onAvalineCallerFound() + */ + void findAvalineCaller(const uuid_set_t& participant_uuids) + { + uuid_set_t::const_iterator it = participant_uuids.begin(), it_end = participant_uuids.end(); + + for(; it != it_end; ++it) + { + const LLUUID& participant_id = *it; + if (!LLVoiceClient::getInstance()->isParticipantAvatar(participant_id)) + { + LL_DEBUGS("Avaline") << "Avaline caller found among voice participants: " << participant_id << LL_ENDL; + + if (mAvalineFoundCallback) + { + mAvalineFoundCallback(participant_id); + } + } + } + } + + /** + * Finds Avaline callers which are not anymore among voice participants and calls mAvalineRemovedCallback. + * + * The problem is when Avaline caller ends a call it is removed from Voice Client session but + * still exists in LLSpeakerMgr. Server does not send such information. + * This method implements a HUCK to notify subscribers that watched Avaline callers by class + * are not anymore in the call. + * + * @see LLParticipantList::onAvalineCallerRemoved() + */ + void checkIfAvalineCallersExist(const uuid_set_t& participant_uuids) + { + uuid_set_t::iterator it = mAvalineCallers.begin(); + uuid_set_t::const_iterator participants_it_end = participant_uuids.end(); + + while (it != mAvalineCallers.end()) + { + const LLUUID participant_id = *it; + LL_DEBUGS("Avaline") << "Check avaline caller: " << participant_id << LL_ENDL; + bool not_found = participant_uuids.find(participant_id) == participants_it_end; + if (not_found) + { + LL_DEBUGS("Avaline") << "Watched Avaline caller is not found among voice participants: " << participant_id << LL_ENDL; + + // notify Participant List + if (mAvalineRemovedCallback) + { + mAvalineRemovedCallback(participant_id); + } + + // remove from the watch list + mAvalineCallers.erase(it++); + } + else + { + ++it; + } + } + } + + process_avaline_callback_t mAvalineFoundCallback; + process_avaline_callback_t mAvalineRemovedCallback; + + uuid_set_t mAvalineCallers; +}; + LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu/* = true*/, bool exclude_agent /*= true*/, bool can_toggle_icons /*= true*/): mSpeakerMgr(data_source), @@ -59,6 +198,9 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av , mExcludeAgent(exclude_agent) , mValidateSpeakerCallback(NULL) { + mAvalineUpdater = new LLAvalineUpdater(boost::bind(&LLParticipantList::onAvalineCallerFound, this, _1), + boost::bind(&LLParticipantList::onAvalineCallerRemoved, this, _1)); + mSpeakerAddListener = new SpeakerAddListener(*this); mSpeakerRemoveListener = new SpeakerRemoveListener(*this); mSpeakerClearListener = new SpeakerClearListener(*this); @@ -137,6 +279,9 @@ LLParticipantList::~LLParticipantList() } mAvatarList->setContextMenu(NULL); + mAvatarList->setComparator(NULL); + + delete mAvalineUpdater; } void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible) @@ -210,6 +355,55 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) } } +/* +Seems this method is not necessary after onAvalineCallerRemoved was implemented; + +It does nothing because list item is always created with correct class type for Avaline caller. +For now Avaline Caller is removed from the LLSpeakerMgr List when it is removed from the Voice Client +session. +This happens in two cases: if Avaline Caller ends call itself or if Resident ends group call. + +Probably Avaline caller should be removed from the LLSpeakerMgr list ONLY if it ends call itself. +Asked in EXT-4301. +*/ +void LLParticipantList::onAvalineCallerFound(const LLUUID& participant_id) +{ + LLPanel* item = mAvatarList->getItemByValue(participant_id); + + if (NULL == item) + { + LL_WARNS("Avaline") << "Something wrong. Unable to find item for: " << participant_id << LL_ENDL; + return; + } + + if (typeid(*item) == typeid(LLAvalineListItem)) + { + LL_DEBUGS("Avaline") << "Avaline caller has already correct class type for: " << participant_id << LL_ENDL; + // item representing an Avaline caller has a correct type already. + return; + } + + LL_DEBUGS("Avaline") << "remove item from the list and re-add it: " << participant_id << LL_ENDL; + + // remove UUID from LLAvatarList::mIDs to be able add it again. + uuid_vec_t& ids = mAvatarList->getIDs(); + uuid_vec_t::iterator pos = std::find(ids.begin(), ids.end(), participant_id); + ids.erase(pos); + + // remove item directly + mAvatarList->removeItem(item); + + // re-add avaline caller with a correct class instance. + addAvatarIDExceptAgent(participant_id); +} + +void LLParticipantList::onAvalineCallerRemoved(const LLUUID& participant_id) +{ + LL_DEBUGS("Avaline") << "Removing avaline caller from the list: " << participant_id << LL_ENDL; + + mSpeakerMgr->removeAvalineSpeaker(participant_id); +} + void LLParticipantList::setSortOrder(EParticipantSortOrder order) { if ( mSortOrder != order ) @@ -355,8 +549,20 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) if (mExcludeAgent && gAgent.getID() == avatar_id) return; if (mAvatarList->contains(avatar_id)) return; - mAvatarList->getIDs().push_back(avatar_id); - mAvatarList->setDirty(); + bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(avatar_id); + + if (is_avatar) + { + mAvatarList->getIDs().push_back(avatar_id); + mAvatarList->setDirty(); + } + else + { + LLVoiceClient::participantState *participant = LLVoiceClient::getInstance()->findParticipantByID(avatar_id); + + mAvatarList->addAvalineItem(avatar_id, mSpeakerMgr->getSessionID(), participant ? participant->mAccountName : LLTrans::getString("AvatarNameWaiting")); + mAvalineUpdater->watchAvalineCaller(avatar_id); + } adjustParticipant(avatar_id); } |