From b49d94e934d946effb016ccdb19efe9c8baa5934 Mon Sep 17 00:00:00 2001 From: Cinders Date: Fri, 28 Jun 2013 21:17:28 -0600 Subject: [PATCH] Use pre-chui LLParticipantList (in fsparticipantlist.*) --- indra/newview/CMakeLists.txt | 2 + indra/newview/fsfloatervoicecontrols.cpp | 2 +- indra/newview/fspanelimcontrolpanel.cpp | 2 +- indra/newview/fsparticipantlist.cpp | 1062 ++++++++++++++++++++++ indra/newview/fsparticipantlist.h | 288 ++++++ indra/newview/llimview.h | 14 +- indra/newview/lloutputmonitorctrl.h | 9 +- indra/newview/llparticipantlist.cpp | 4 + indra/newview/llparticipantlist.h | 4 + 9 files changed, 1381 insertions(+), 6 deletions(-) create mode 100644 indra/newview/fsparticipantlist.cpp create mode 100644 indra/newview/fsparticipantlist.h diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ede36610a0..d6bcaf053c 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -159,6 +159,7 @@ set(viewer_SOURCE_FILES fspanelprofile.cpp fspanelprofileclassifieds.cpp fspanelradar.cpp + fsparticipantlist.cpp fspose.cpp fsradar.cpp fsradarentry.cpp @@ -841,6 +842,7 @@ set(viewer_HEADER_FILES fspanelprofile.h fspanelprofileclassifieds.h fspanelradar.h + fsparticipantlist.h fspose.h fsradar.h fsradarentry.h diff --git a/indra/newview/fsfloatervoicecontrols.cpp b/indra/newview/fsfloatervoicecontrols.cpp index 1771d42ccc..5a4d6a9fd5 100644 --- a/indra/newview/fsfloatervoicecontrols.cpp +++ b/indra/newview/fsfloatervoicecontrols.cpp @@ -43,7 +43,7 @@ #include "fsfloaterim.h" #include "llimview.h" #include "llfloaterreg.h" -#include "llparticipantlist.h" +#include "fsparticipantlist.h" #include "llspeakers.h" #include "lltextutil.h" #include "lltransientfloatermgr.h" diff --git a/indra/newview/fspanelimcontrolpanel.cpp b/indra/newview/fspanelimcontrolpanel.cpp index 8d7f6255c3..168b1bde06 100644 --- a/indra/newview/fspanelimcontrolpanel.cpp +++ b/indra/newview/fspanelimcontrolpanel.cpp @@ -39,7 +39,7 @@ #include "llbutton.h" #include "llgroupactions.h" #include "llavatarlist.h" -#include "llparticipantlist.h" +#include "fsparticipantlist.h" #include "llimview.h" #include "llvoicechannel.h" #include "llspeakers.h" diff --git a/indra/newview/fsparticipantlist.cpp b/indra/newview/fsparticipantlist.cpp new file mode 100644 index 0000000000..f65c1560f6 --- /dev/null +++ b/indra/newview/fsparticipantlist.cpp @@ -0,0 +1,1062 @@ +/** + * @file fsparticipantlist.cpp + * @brief LLParticipantList intended to update view(LLAvatarList) according to incoming messages + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "fsparticipantlist.h" + +// common includes +#include "lltrans.h" +#include "llavataractions.h" +#include "llagent.h" +// [SL:KB] - Patch: Chat-GroupSessionEject | Checked: 2012-02-04 (Catznip-3.2.1) +#include "llgroupactions.h" +// [/SL:KB] +#include "llimview.h" +#include "llnotificationsutil.h" +#include "llspeakers.h" +#include "llviewercontrol.h" +#include "llviewermenu.h" +#include "llvoiceclient.h" + +//LLParticipantList retrieves add, clear and remove events and updates view accordingly +#if LL_MSVC +#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally +#endif + +static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR; + +// helper function to update AvatarList Item's indicator in the voice participant list +static void update_speaker_indicator(const LLAvatarList* const avatar_list, const LLUUID& avatar_uuid, bool is_muted) +{ + LLAvatarListItem* item = dynamic_cast(avatar_list->getItemByValue(avatar_uuid)); + if (item) + { + LLOutputMonitorCtrl* indicator = item->getChild("speaking_indicator"); + indicator->setIsMuted(is_muted); + } +} + + +// 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 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 onParticipantsChanged() + { + uuid_set_t participant_uuids; + LLVoiceClient::getInstance()->getParticipantList(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 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), + mAvatarList(avatar_list), + mParticipantListMenu(NULL), + 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); + mSpeakerModeratorListener = new SpeakerModeratorUpdateListener(*this); + mSpeakerMuteListener = new SpeakerMuteListener(*this); + + mSpeakerMgr->addListener(mSpeakerAddListener, "add"); + mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove"); + mSpeakerMgr->addListener(mSpeakerClearListener, "clear"); + mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator"); + + mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData")); + LL_DEBUGS("SpeakingIndicator") << "Set session for speaking indicators: " << mSpeakerMgr->getSessionID() << LL_ENDL; + mAvatarList->setSessionID(mSpeakerMgr->getSessionID()); + mAvatarListDoubleClickConnection = mAvatarList->setItemDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, _1)); + mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2)); + // Set onAvatarListDoubleClicked as default on_return action. + mAvatarListReturnConnection = mAvatarList->setReturnCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); + + if (use_context_menu) + { + mParticipantListMenu = new LLParticipantListMenu(*this); + mAvatarList->setContextMenu(mParticipantListMenu); + } + else + { + mAvatarList->setContextMenu(NULL); + } + + if (use_context_menu && can_toggle_icons) + { + mAvatarList->setShowIcons("ParticipantListShowIcons"); + mAvatarListToggleIconsConnection = gSavedSettings.getControl("ParticipantListShowIcons")->getSignal()->connect(boost::bind(&LLAvatarList::toggleIcons, mAvatarList)); + } + + //Lets fill avatarList with existing speakers + 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& speakerp = *it; + + addAvatarIDExceptAgent(speakerp->mID); + if ( speakerp->mIsModerator ) + { + mModeratorList.insert(speakerp->mID); + } + else + { + mModeratorToRemoveList.insert(speakerp->mID); + } + } + // we need to exclude agent id for non group chat + sort(); +} + +LLParticipantList::~LLParticipantList() +{ + mAvatarListDoubleClickConnection.disconnect(); + mAvatarListRefreshConnection.disconnect(); + mAvatarListReturnConnection.disconnect(); + mAvatarListToggleIconsConnection.disconnect(); + + // It is possible Participant List will be re-created from LLCallFloater::onCurrentChannelChanged() + // See ticket EXT-3427 + // hide menu before deleting it to stop enable and check handlers from triggering. + if(mParticipantListMenu && !LLApp::isExiting()) + { + mParticipantListMenu->hide(); + } + + if (mParticipantListMenu) + { + delete mParticipantListMenu; + mParticipantListMenu = NULL; + } + + mAvatarList->setContextMenu(NULL); + mAvatarList->setComparator(NULL); + + delete mAvalineUpdater; +} + +void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible) +{ + mAvatarList->setSpeakingIndicatorsVisible(visible); +}; + +void LLParticipantList::onAvatarListDoubleClicked(LLUICtrl* ctrl) +{ + LLAvatarListItem* item = dynamic_cast(ctrl); + if(!item) + { + return; + } + + LLUUID clicked_id = item->getAvatarId(); + + if (clicked_id.isNull() || clicked_id == gAgent.getID()) + return; + + LLAvatarActions::startIM(clicked_id); +} + +void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) +{ + LLAvatarList* list = dynamic_cast(ctrl); + if (list) + { + const std::string moderator_indicator(LLTrans::getString("IM_moderator_label")); + const std::size_t moderator_indicator_len = moderator_indicator.length(); + + // Firstly remove moderators indicator + std::set::const_iterator + moderator_list_it = mModeratorToRemoveList.begin(), + moderator_list_end = mModeratorToRemoveList.end(); + for (;moderator_list_it != moderator_list_end; ++moderator_list_it) + { + LLAvatarListItem* item = dynamic_cast (list->getItemByValue(*moderator_list_it)); + if ( item ) + { + std::string name = item->getAvatarName(); + std::string tooltip = item->getAvatarToolTip(); + size_t found = name.find(moderator_indicator); + if (found != std::string::npos) + { + name.erase(found, moderator_indicator_len); + item->setAvatarName(name); + } + found = tooltip.find(moderator_indicator); + if (found != tooltip.npos) + { + tooltip.erase(found, moderator_indicator_len); + item->setAvatarToolTip(tooltip); + } + item->setState(LLAvatarListItem::IS_ONLINE); + } + } + + mModeratorToRemoveList.clear(); + + // Add moderators indicator + moderator_list_it = mModeratorList.begin(); + moderator_list_end = mModeratorList.end(); + for (;moderator_list_it != moderator_list_end; ++moderator_list_it) + { + LLAvatarListItem* item = dynamic_cast (list->getItemByValue(*moderator_list_it)); + if ( item ) + { + std::string name = item->getAvatarName(); + std::string tooltip = item->getAvatarToolTip(); + size_t found = name.find(moderator_indicator); + if (found == std::string::npos) + { + name += " "; + name += moderator_indicator; + item->setAvatarName(name); + } + found = tooltip.find(moderator_indicator); + if (found == std::string::npos) + { + tooltip += " "; + tooltip += moderator_indicator; + item->setAvatarToolTip(tooltip); + } + item->setState(LLAvatarListItem::IS_GROUPMOD); + } + } + + // update voice mute state of all items. See EXT-7235 + LLSpeakerMgr::speaker_list_t speaker_list; + + // Use also participants which are not in voice session now (the second arg is TRUE). + // They can already have mModeratorMutedVoice set from the previous voice session + // and LLSpeakerVoiceModerationEvent will not be sent when speaker manager is updated next time. + mSpeakerMgr->getSpeakerList(&speaker_list, TRUE); + for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++) + { + const LLPointer& speakerp = *it; + + if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) + { + update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice); + } + } + } +} + +/* + 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) +{ + const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder"); + + if ( speaker_sort_order != order ) + { + gSavedSettings.setU32("SpeakerParticipantDefaultOrder", (U32)order); + sort(); + } +} + +const LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder() const +{ + const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder"); + return EParticipantSortOrder(speaker_sort_order); +} + +void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t cb) +{ + mValidateSpeakerCallback = cb; +} + +void LLParticipantList::update() +{ + mSpeakerMgr->update(true); + + if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder() && !isHovered()) + { + // Resort avatar list + sort(); + } +} + +bool LLParticipantList::isHovered() +{ + S32 x, y; + LLUI::getMousePositionScreen(&x, &y); + return mAvatarList->calcScreenRect().pointInRect(x, y); +} + +bool LLParticipantList::onAddItemEvent(LLPointer event, const LLSD& userdata) +{ + LLUUID uu_id = event->getValue().asUUID(); + + if (mValidateSpeakerCallback && !mValidateSpeakerCallback(uu_id)) + { + return true; + } + + addAvatarIDExceptAgent(uu_id); + sort(); + return true; +} + +bool LLParticipantList::onRemoveItemEvent(LLPointer event, const LLSD& userdata) +{ + uuid_vec_t& group_members = mAvatarList->getIDs(); + uuid_vec_t::iterator pos = std::find(group_members.begin(), group_members.end(), event->getValue().asUUID()); + if(pos != group_members.end()) + { + group_members.erase(pos); + mAvatarList->setDirty(); + } + return true; +} + +bool LLParticipantList::onClearListEvent(LLPointer event, const LLSD& userdata) +{ + uuid_vec_t& group_members = mAvatarList->getIDs(); + group_members.clear(); + mAvatarList->setDirty(); + return true; +} + +bool LLParticipantList::onModeratorUpdateEvent(LLPointer event, const LLSD& userdata) +{ + const LLSD& evt_data = event->getValue(); + if ( evt_data.has("id") && evt_data.has("is_moderator") ) + { + LLUUID id = evt_data["id"]; + bool is_moderator = evt_data["is_moderator"]; + if ( id.notNull() ) + { + if ( is_moderator ) + mModeratorList.insert(id); + else + { + std::set::iterator it = mModeratorList.find (id); + if ( it != mModeratorList.end () ) + { + mModeratorToRemoveList.insert(id); + mModeratorList.erase(id); + } + } + + // apply changes immediately + onAvatarListRefreshed(mAvatarList, LLSD()); + } + } + return true; +} + +bool LLParticipantList::onSpeakerMuteEvent(LLPointer event, const LLSD& userdata) +{ + LLPointer speakerp = (LLSpeaker*)event->getSource(); + if (speakerp.isNull()) return false; + + // update UI on confirmation of moderator mutes + if (event->getValue().asString() == "voice") + { + update_speaker_indicator(mAvatarList, speakerp->mID, speakerp->mModeratorMutedVoice); + } + return true; +} + +void LLParticipantList::sort() +{ + if ( !mAvatarList ) + return; + + switch ( getSortOrder() ) + { + case E_SORT_BY_NAME : + // if mExcludeAgent == true , then no need to keep agent on top of the list + if(mExcludeAgent) + { + mAvatarList->sortByName(); + } + else + { + mAvatarList->setComparator(&AGENT_ON_TOP_NAME_COMPARATOR); + mAvatarList->sort(); + } + break; + case E_SORT_BY_RECENT_SPEAKERS: + if (mSortByRecentSpeakers.isNull()) + mSortByRecentSpeakers = new LLAvatarItemRecentSpeakerComparator(*this); + mAvatarList->setComparator(mSortByRecentSpeakers.get()); + mAvatarList->sort(); + break; + default : + llwarns << "Unrecognized sort order for " << mAvatarList->getName() << llendl; + return; + } +} + +void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) +{ + if (mExcludeAgent && gAgent.getID() == avatar_id) return; + if (mAvatarList->contains(avatar_id)) return; + + bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(avatar_id); + + if (is_avatar) + { + mAvatarList->getIDs().push_back(avatar_id); + mAvatarList->setDirty(); + } + else + { + std::string display_name = LLVoiceClient::getInstance()->getDisplayName(avatar_id); + mAvatarList->addAvalineItem(avatar_id, mSpeakerMgr->getSessionID(), display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name); + mAvalineUpdater->watchAvalineCaller(avatar_id); + } + adjustParticipant(avatar_id); +} + +void LLParticipantList::adjustParticipant(const LLUUID& speaker_id) +{ + LLPointer speakerp = mSpeakerMgr->findSpeaker(speaker_id); + if (speakerp.isNull()) return; + + // add listener to process moderation changes + speakerp->addListener(mSpeakerMuteListener); +} + +// +// LLParticipantList::SpeakerAddListener +// +bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer event, const LLSD& userdata) +{ + /** + * We need to filter speaking objects. These objects shouldn't appear in the list + * @see LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy + */ + const LLUUID& speaker_id = event->getValue().asUUID(); + LLPointer speaker = mParent.mSpeakerMgr->findSpeaker(speaker_id); + if(speaker.isNull() || speaker->mType == LLSpeaker::SPEAKER_OBJECT) + { + return false; + } + return mParent.onAddItemEvent(event, userdata); +} + +// +// LLParticipantList::SpeakerRemoveListener +// +bool LLParticipantList::SpeakerRemoveListener::handleEvent(LLPointer event, const LLSD& userdata) +{ + return mParent.onRemoveItemEvent(event, userdata); +} + +// +// LLParticipantList::SpeakerClearListener +// +bool LLParticipantList::SpeakerClearListener::handleEvent(LLPointer event, const LLSD& userdata) +{ + return mParent.onClearListEvent(event, userdata); +} + +// +// LLParticipantList::SpeakerModeratorListener +// +bool LLParticipantList::SpeakerModeratorUpdateListener::handleEvent(LLPointer event, const LLSD& userdata) +{ + return mParent.onModeratorUpdateEvent(event, userdata); +} + +bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer event, const LLSD& userdata) +{ + return mParent.onSpeakerMuteEvent(event, userdata); +} + +LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() +{ + // set up the callbacks for all of the avatar menu items + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + + registrar.add("ParticipantList.Sort", boost::bind(&LLParticipantList::LLParticipantListMenu::sortParticipantList, this, _2)); + registrar.add("ParticipantList.ToggleAllowTextChat", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleAllowTextChat, this, _2)); + registrar.add("ParticipantList.ToggleMuteText", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteText, this, _2)); +// [SL:KB] - Patch: Chat-GroupSessionEject | Checked: 2012-02-04 (Catznip-3.2.1) | Added: Catznip-3.2.1 + registrar.add("ParticipantList.Eject", boost::bind(&LLGroupActions::ejectFromGroup, mParent.mSpeakerMgr->getSessionID(), mUUIDs.front())); +// [SL:KB] + + registrar.add("Avatar.Profile", boost::bind(&LLAvatarActions::showProfile, mUUIDs.front())); + registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startIM, mUUIDs.front())); + registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs.front())); + registrar.add("Avatar.BlockUnblock", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteVoice, this, _2)); + registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, mUUIDs.front())); + registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs.front())); + registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, mUUIDs.front())); + + registrar.add("ParticipantList.ModerateVoice", boost::bind(&LLParticipantList::LLParticipantListMenu::moderateVoice, this, _2)); + + enable_registrar.add("ParticipantList.EnableItem", boost::bind(&LLParticipantList::LLParticipantListMenu::enableContextMenuItem, this, _2)); + enable_registrar.add("ParticipantList.EnableItem.Moderate", boost::bind(&LLParticipantList::LLParticipantListMenu::enableModerateContextMenuItem, this, _2)); + enable_registrar.add("ParticipantList.CheckItem", boost::bind(&LLParticipantList::LLParticipantListMenu::checkContextMenuItem, this, _2)); + + // create the context menu from the XUI + LLContextMenu* main_menu = createFromFile("menu_participant_list.xml"); + + // Don't show sort options for P2P chat + bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1); + // Hide SortBy separator + main_menu->setItemVisible("Sort Separator", is_sort_visible); + // + main_menu->setItemVisible("SortByName", is_sort_visible); + main_menu->setItemVisible("SortByRecentSpeakers", is_sort_visible); + main_menu->setItemVisible("Moderator Options Separator", isGroupModerator()); + main_menu->setItemVisible("Moderator Options", isGroupModerator()); + main_menu->setItemVisible("View Icons Separator", mParent.mAvatarListToggleIconsConnection.connected()); + main_menu->setItemVisible("View Icons", mParent.mAvatarListToggleIconsConnection.connected()); + main_menu->arrangeAndClear(); + + return main_menu; +} + +void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y) +{ + if (uuids.size() == 0) return; + + LLListContextMenu::show(spawning_view, uuids, x, y); + + const LLUUID& speaker_id = mUUIDs.front(); + BOOL is_muted = isMuted(speaker_id); + + if (is_muted) + { + LLMenuGL::sMenuContainer->getChildView("ModerateVoiceMuteSelected")->setVisible( false); + } + else + { + LLMenuGL::sMenuContainer->getChildView("ModerateVoiceUnMuteSelected")->setVisible( false); + } +} + +void LLParticipantList::LLParticipantListMenu::sortParticipantList(const LLSD& userdata) +{ + std::string param = userdata.asString(); + if ("sort_by_name" == param) + { + mParent.setSortOrder(E_SORT_BY_NAME); + } + else if ("sort_by_recent_speakers" == param) + { + mParent.setSortOrder(E_SORT_BY_RECENT_SPEAKERS); + } +} + +void LLParticipantList::LLParticipantListMenu::toggleAllowTextChat(const LLSD& userdata) +{ + + LLIMSpeakerMgr* mgr = dynamic_cast(mParent.mSpeakerMgr); + if (mgr) + { + const LLUUID speaker_id = mUUIDs.front(); + mgr->toggleAllowTextChat(speaker_id); + } +} + +void LLParticipantList::LLParticipantListMenu::toggleMute(const LLSD& userdata, U32 flags) +{ + const LLUUID speaker_id = mUUIDs.front(); + BOOL is_muted = LLMuteList::getInstance()->isMuted(speaker_id, flags); + std::string name; + + //fill in name using voice client's copy of name cache + LLPointer speakerp = mParent.mSpeakerMgr->findSpeaker(speaker_id); + if (speakerp.isNull()) + { + LL_WARNS("Speakers") << "Speaker " << speaker_id << " not found" << llendl; + return; + } + LLAvatarListItem* item = dynamic_cast(mParent.mAvatarList->getItemByValue(speaker_id)); + if (NULL == item) return; + + name = item->getAvatarName(); + + LLMute::EType mute_type; + switch (speakerp->mType) + { + case LLSpeaker::SPEAKER_AGENT: + mute_type = LLMute::AGENT; + break; + case LLSpeaker::SPEAKER_OBJECT: + mute_type = LLMute::OBJECT; + break; + case LLSpeaker::SPEAKER_EXTERNAL: + default: + mute_type = LLMute::EXTERNAL; + break; + } + LLMute mute(speaker_id, name, mute_type); + + if (!is_muted) + { + LLMuteList::getInstance()->add(mute, flags); + } + else + { + LLMuteList::getInstance()->remove(mute, flags); + } +} + +void LLParticipantList::LLParticipantListMenu::toggleMuteText(const LLSD& userdata) +{ + toggleMute(userdata, LLMute::flagTextChat); +} + +void LLParticipantList::LLParticipantListMenu::toggleMuteVoice(const LLSD& userdata) +{ + toggleMute(userdata, LLMute::flagVoiceChat); +} + +bool LLParticipantList::LLParticipantListMenu::isGroupModerator() +{ + if (!mParent.mSpeakerMgr) + { + llwarns << "Speaker manager is missing" << llendl; + return false; + } + + // Is session a group call/chat? + if(gAgent.isInGroup(mParent.mSpeakerMgr->getSessionID())) + { + LLSpeaker* speaker = mParent.mSpeakerMgr->findSpeaker(gAgentID).get(); + + // Is agent a moderator? + return speaker && speaker->mIsModerator; + } + return false; +} + +bool LLParticipantList::LLParticipantListMenu::isMuted(const LLUUID& avatar_id) +{ + LLPointer selected_speakerp = mParent.mSpeakerMgr->findSpeaker(avatar_id); + if (!selected_speakerp) return true; + + return selected_speakerp->mStatus == LLSpeaker::STATUS_MUTED; +} + +void LLParticipantList::LLParticipantListMenu::moderateVoice(const LLSD& userdata) +{ + if (!gAgent.getRegion()) return; + + bool moderate_selected = userdata.asString() == "selected"; + + if (moderate_selected) + { + const LLUUID& selected_avatar_id = mUUIDs.front(); + bool is_muted = isMuted(selected_avatar_id); + moderateVoiceParticipant(selected_avatar_id, is_muted); + } + else + { + bool unmute_all = userdata.asString() == "unmute_all"; + moderateVoiceAllParticipants(unmute_all); + } +} + +void LLParticipantList::LLParticipantListMenu::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute) +{ + LLIMSpeakerMgr* mgr = dynamic_cast(mParent.mSpeakerMgr); + if (mgr) + { + mgr->moderateVoiceParticipant(avatar_id, unmute); + } +} + +void LLParticipantList::LLParticipantListMenu::moderateVoiceAllParticipants(bool unmute) +{ + LLIMSpeakerMgr* mgr = dynamic_cast(mParent.mSpeakerMgr); + if (mgr) + { + if (!unmute) + { + LLSD payload; + payload["session_id"] = mgr->getSessionID(); + LLNotificationsUtil::add("ConfirmMuteAll", LLSD(), payload, confirmMuteAllCallback); + return; + } + + mgr->moderateVoiceAllParticipants(unmute); + } +} + +// static +void LLParticipantList::LLParticipantListMenu::confirmMuteAllCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + // if Cancel pressed + if (option == 1) + { + return; + } + + const LLSD& payload = notification["payload"]; + const LLUUID& session_id = payload["session_id"]; + + LLIMSpeakerMgr * speaker_manager = dynamic_cast ( + LLIMModel::getInstance()->getSpeakerManager(session_id)); + if (speaker_manager) + { + speaker_manager->moderateVoiceAllParticipants(false); + } + + return; +} + + +bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& userdata) +{ + std::string item = userdata.asString(); + const LLUUID& participant_id = mUUIDs.front(); + + // For now non of "can_view_profile" action and menu actions listed below except "can_block" + // can be performed for Avaline callers. + bool is_participant_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(participant_id); + if (!is_participant_avatar && "can_block" != item) return false; + + if (item == "can_mute_text" || "can_block" == item || "can_share" == item || "can_im" == item + || "can_pay" == item) + { + return mUUIDs.front() != gAgentID; + } + else if (item == std::string("can_add")) + { + // We can add friends if: + // - there are selected people + // - and there are no friends among selection yet. + + bool result = (mUUIDs.size() > 0); + + uuid_vec_t::const_iterator + id = mUUIDs.begin(), + uuids_end = mUUIDs.end(); + + for (;id != uuids_end; ++id) + { + if ( *id == gAgentID || LLAvatarActions::isFriend(*id) ) + { + result = false; + break; + } + } + return result; + } + else if (item == "can_call") + { + bool not_agent = mUUIDs.front() != gAgentID; + bool can_call = not_agent && LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); + return can_call; + } +// [SL:KB] - Patch: Chat-GroupSessionEject | Checked: 2012-02-04 (Catznip-3.2.1) | Added: Catznip-3.2.1 + else if (item == "can_eject") + { + return LLGroupActions::canEjectFromGroup(mParent.mSpeakerMgr->getSessionID(), mUUIDs.front()); + } +// [/SL:KB] + + return true; +} + +/* + Processed menu items with such parameters: + can_allow_text_chat + can_moderate_voice +*/ +bool LLParticipantList::LLParticipantListMenu::enableModerateContextMenuItem(const LLSD& userdata) +{ + // only group moderators can perform actions related to this "enable callback" + if (!isGroupModerator()) return false; + + const LLUUID& participant_id = mUUIDs.front(); + LLPointer speakerp = mParent.mSpeakerMgr->findSpeaker(participant_id); + + // not in voice participants can not be moderated + bool speaker_in_voice = speakerp.notNull() && speakerp->isInVoiceChannel(); + + const std::string& item = userdata.asString(); + + if ("can_moderate_voice" == item) + { + return speaker_in_voice; + } + + // For now non of menu actions except "can_moderate_voice" can be performed for Avaline callers. + bool is_participant_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(participant_id); + if (!is_participant_avatar) return false; + + return true; +} + +bool LLParticipantList::LLParticipantListMenu::checkContextMenuItem(const LLSD& userdata) +{ + std::string item = userdata.asString(); + const LLUUID& id = mUUIDs.front(); + + if (item == "is_muted") + { + return LLMuteList::getInstance()->isMuted(id, LLMute::flagTextChat); + } + else if (item == "is_allowed_text_chat") + { + LLPointer selected_speakerp = mParent.mSpeakerMgr->findSpeaker(id); + + if (selected_speakerp.notNull()) + { + return !selected_speakerp->mModeratorMutedText; + } + } + else if(item == "is_blocked") + { + return LLMuteList::getInstance()->isMuted(id, LLMute::flagVoiceChat); + } + else if(item == "is_sorted_by_name") + { + return E_SORT_BY_NAME == mParent.getSortOrder(); + } + else if(item == "is_sorted_by_recent_speakers") + { + return E_SORT_BY_RECENT_SPEAKERS == mParent.getSortOrder(); + } + + return false; +} + +bool LLParticipantList::LLAvatarItemRecentSpeakerComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const +{ + if (mParent.mSpeakerMgr) + { + LLPointer lhs = mParent.mSpeakerMgr->findSpeaker(avatar_item1->getAvatarId()); + LLPointer rhs = mParent.mSpeakerMgr->findSpeaker(avatar_item2->getAvatarId()); + if ( lhs.notNull() && rhs.notNull() ) + { + // Compare by last speaking time + if( lhs->mLastSpokeTime != rhs->mLastSpokeTime ) + return ( lhs->mLastSpokeTime > rhs->mLastSpokeTime ); + else if ( lhs->mSortIndex != rhs->mSortIndex ) + return ( lhs->mSortIndex < rhs->mSortIndex ); + } + else if ( lhs.notNull() ) + { + // True if only avatar_item1 speaker info available + return true; + } + else if ( rhs.notNull() ) + { + // False if only avatar_item2 speaker info available + return false; + } + } + // By default compare by name. + return LLAvatarItemNameComparator::doCompare(avatar_item1, avatar_item2); +} + +//EOF diff --git a/indra/newview/fsparticipantlist.h b/indra/newview/fsparticipantlist.h new file mode 100644 index 0000000000..c6f618a813 --- /dev/null +++ b/indra/newview/fsparticipantlist.h @@ -0,0 +1,288 @@ +/** + * @file fsparticipantlist.h + * @brief LLParticipantList intended to update view(LLAvatarList) according to incoming messages + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_PARTICIPANTLIST_H +#define LL_PARTICIPANTLIST_H + +#include "llviewerprecompiledheaders.h" +#include "llevent.h" +#include "llavatarlist.h" // for LLAvatarItemRecentSpeakerComparator +#include "lllistcontextmenu.h" + +class LLSpeakerMgr; +class LLAvatarList; +class LLUICtrl; +class LLAvalineUpdater; + +class LLParticipantList +{ + LOG_CLASS(LLParticipantList); +public: + + typedef boost::function validate_speaker_callback_t; + + LLParticipantList(LLSpeakerMgr* data_source, + LLAvatarList* avatar_list, + bool use_context_menu = true, + bool exclude_agent = true, + bool can_toggle_icons = true); + ~LLParticipantList(); + void setSpeakingIndicatorsVisible(BOOL visible); + + enum EParticipantSortOrder + { + E_SORT_BY_NAME = 0, + E_SORT_BY_RECENT_SPEAKERS = 1, + }; + + /** + * 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); + const EParticipantSortOrder getSortOrder() const; + + /** + * Refreshes the participant list. + */ + void update(); + + /** + * 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 + */ + bool onAddItemEvent(LLPointer event, const LLSD& userdata); + bool onRemoveItemEvent(LLPointer event, const LLSD& userdata); + bool onClearListEvent(LLPointer event, const LLSD& userdata); + bool onModeratorUpdateEvent(LLPointer event, const LLSD& userdata); + bool onSpeakerMuteEvent(LLPointer event, const LLSD& userdata); + + /** + * Sorts the Avatarlist by stored order + */ + void sort(); + + /** + * List of listeners implementing LLOldEvents::LLSimpleListener. + * There is no way to handle all the events in one listener as LLSpeakerMgr registers + * listeners in such a way that one listener can handle only one type of event + **/ + class BaseSpeakerListener : public LLOldEvents::LLSimpleListener + { + public: + BaseSpeakerListener(LLParticipantList& parent) : mParent(parent) {} + protected: + LLParticipantList& mParent; + }; + + class SpeakerAddListener : public BaseSpeakerListener + { + public: + SpeakerAddListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {} + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); + }; + + class SpeakerRemoveListener : public BaseSpeakerListener + { + public: + SpeakerRemoveListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {} + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); + }; + + class SpeakerClearListener : public BaseSpeakerListener + { + public: + SpeakerClearListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {} + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); + }; + + class SpeakerModeratorUpdateListener : public BaseSpeakerListener + { + public: + SpeakerModeratorUpdateListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {} + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); + }; + + class SpeakerMuteListener : public BaseSpeakerListener + { + public: + SpeakerMuteListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {} + + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); + }; + + /** + * Menu used in the participant list. + */ + class LLParticipantListMenu : public LLListContextMenu + { + public: + LLParticipantListMenu(LLParticipantList& parent):mParent(parent){}; + /*virtual*/ LLContextMenu* createMenu(); + /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); + protected: + LLParticipantList& mParent; + private: + bool enableContextMenuItem(const LLSD& userdata); + bool enableModerateContextMenuItem(const LLSD& userdata); + bool checkContextMenuItem(const LLSD& userdata); + + void sortParticipantList(const LLSD& userdata); + void toggleAllowTextChat(const LLSD& userdata); + void toggleMute(const LLSD& userdata, U32 flags); + void toggleMuteText(const LLSD& userdata); + void toggleMuteVoice(const LLSD& userdata); + + /** + * Return true if Agent is group moderator(and moderator of group call). + */ + bool isGroupModerator(); + + // Voice moderation support + /** + * Check whether specified by argument avatar is muted for group chat or not. + */ + bool isMuted(const LLUUID& avatar_id); + + /** + * Processes Voice moderation menu items. + * + * It calls either moderateVoiceParticipant() or moderateVoiceParticipant() depend on + * passed parameter. + * + * @param userdata can be "selected" or "others". + * + * @see moderateVoiceParticipant() + * @see moderateVoiceAllParticipants() + */ + void moderateVoice(const LLSD& userdata); + + /** + * Mutes/Unmutes avatar for current group voice chat. + * + * It only marks avatar as muted for session and does not use local Agent's Block list. + * It does not mute Agent itself. + * + * @param[in] avatar_id UUID of avatar to be processed + * @param[in] unmute if true - specified avatar will be muted, otherwise - unmuted. + * + * @see moderateVoiceAllParticipants() + */ + void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute); + + /** + * Mutes/Unmutes all avatars for current group voice chat. + * + * It only marks avatars as muted for session and does not use local Agent's Block list. + * + * @param[in] unmute if true - avatars will be muted, otherwise - unmuted. + * + * @see moderateVoiceParticipant() + */ + void moderateVoiceAllParticipants(bool unmute); + + static void confirmMuteAllCallback(const LLSD& notification, const LLSD& response); + }; + + /** + * Comparator for comparing avatar items by last spoken time + */ + class LLAvatarItemRecentSpeakerComparator : public LLAvatarItemNameComparator, public LLRefCount + { + LOG_CLASS(LLAvatarItemRecentSpeakerComparator); + public: + LLAvatarItemRecentSpeakerComparator(LLParticipantList& parent):mParent(parent){}; + virtual ~LLAvatarItemRecentSpeakerComparator() {}; + protected: + virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const; + private: + LLParticipantList& mParent; + }; + +private: + void onAvatarListDoubleClicked(LLUICtrl* ctrl); + void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param); + + void onAvalineCallerFound(const LLUUID& participant_id); + void onAvalineCallerRemoved(const LLUUID& participant_id); + + /** + * Adjusts passed participant to work properly. + * + * Adds SpeakerMuteListener to process moderation actions. + */ + void adjustParticipant(const LLUUID& speaker_id); + + bool isHovered(); + + LLSpeakerMgr* mSpeakerMgr; + LLAvatarList* mAvatarList; + + std::set mModeratorList; + std::set mModeratorToRemoveList; + + LLPointer mSpeakerAddListener; + LLPointer mSpeakerRemoveListener; + LLPointer mSpeakerClearListener; + LLPointer mSpeakerModeratorListener; + LLPointer mSpeakerMuteListener; + + LLParticipantListMenu* mParticipantListMenu; + + /** + * This field manages an adding a new avatar_id in the mAvatarList + * If true, then agent_id wont be added into mAvatarList + * Also by default this field is controlling a sort procedure, @c sort() + */ + bool mExcludeAgent; + + // boost::connections + boost::signals2::connection mAvatarListDoubleClickConnection; + boost::signals2::connection mAvatarListRefreshConnection; + boost::signals2::connection mAvatarListReturnConnection; + boost::signals2::connection mAvatarListToggleIconsConnection; + + LLPointer mSortByRecentSpeakers; + validate_speaker_callback_t mValidateSpeakerCallback; + LLAvalineUpdater* mAvalineUpdater; +}; + +#endif // LL_PARTICIPANTLIST_H diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 03c8677e4d..562affc986 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -194,6 +194,14 @@ public: */ bool clearSession(const LLUUID& session_id); + // Make public for FS Communications UI + /** + * Populate supplied std::list with messages starting from index specified by start_index without + * emitting no unread messages signal. + */ + void getMessagesSilently(const LLUUID& session_id, std::list& messages, int start_index = 0); + // + /** * Sends no unread messages signal. */ @@ -293,12 +301,14 @@ public: private: + // Post CHUI - Move this public for FS Communications UI /** * Populate supplied std::list with messages starting from index specified by start_index without * emitting no unread messages signal. */ - void getMessagesSilently(const LLUUID& session_id, std::list& messages, int start_index = 0); - + //void getMessagesSilently(const LLUUID& session_id, std::list& messages, int start_index = 0); + // + /** * Add message to a list of message associated with session specified by session_id */ diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index 86ef06b739..fdc4224772 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -28,10 +28,10 @@ #define LL_LLOUTPUTMONITORCTRL_H #include "v4color.h" -#include "../llui/llview.h" +#include "llview.h" #include "llmutelist.h" #include "llspeakingindicatormanager.h" -//#include "../llui/lluiimage.h" +//#include "lluiimage.h" class LLTextBox; class LLUICtrlFactory; @@ -73,6 +73,11 @@ public: void setPower(F32 val); F32 getPower(F32 val) const { return mPower; } + // FS Communications UI + bool getIsMuted() const { return mIsMuted; } + void setIsMuted(bool val) { mIsMuted = val; } + // + // For the current user, need to know the PTT state to show // correct button image. void setIsAgentControl(bool val) { mIsAgentControl = val; } diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 6efc635e42..fcf5610c67 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -24,6 +24,8 @@ * $/LicenseInfo$ */ +#if 0 + #include "llviewerprecompiledheaders.h" #include "llavatarnamecache.h" @@ -470,4 +472,6 @@ bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer