diff options
Diffstat (limited to 'indra/newview/llparticipantlist.cpp')
-rw-r--r-- | indra/newview/llparticipantlist.cpp | 424 |
1 files changed, 62 insertions, 362 deletions
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 49850748ee..eb245453db 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -2,25 +2,31 @@ * @file llparticipantlist.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. + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, 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. + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * - * 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. + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * - * 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 + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ @@ -31,11 +37,8 @@ #include "llavataractions.h" #include "llagent.h" -#include "llimview.h" -#include "llnotificationsutil.h" #include "llparticipantlist.h" #include "llspeakers.h" -#include "llviewercontrol.h" #include "llviewermenu.h" #include "llvoiceclient.h" @@ -46,159 +49,8 @@ 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<LLAvatarListItem*>(avatar_list->getItemByValue(avatar_uuid)); - if (item) - { - LLOutputMonitorCtrl* indicator = item->getChild<LLOutputMonitorCtrl>("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<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 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<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*/): + bool exclude_agent /*= true*/): mSpeakerMgr(data_source), mAvatarList(avatar_list), mSortOrder(E_SORT_BY_NAME) @@ -206,9 +58,6 @@ 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); @@ -238,12 +87,6 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av 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); @@ -270,7 +113,6 @@ 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 @@ -287,9 +129,6 @@ LLParticipantList::~LLParticipantList() } mAvatarList->setContextMenu(NULL); - mAvatarList->setComparator(NULL); - - delete mAvalineUpdater; } void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible) @@ -360,70 +199,7 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) } } } - - // 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<LLSpeaker>& speakerp = *it; - - 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) @@ -526,7 +302,12 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event // update UI on confirmation of moderator mutes if (event->getValue().asString() == "voice") { - update_speaker_indicator(mAvatarList, speakerp->mID, speakerp->mModeratorMutedVoice); + LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(mAvatarList->getItemByValue(speakerp->mID)); + if (item) + { + LLOutputMonitorCtrl* indicator = item->getChild<LLOutputMonitorCtrl>("speaking_indicator"); + indicator->setIsMuted(speakerp->mModeratorMutedVoice); + } } return true; } @@ -566,19 +347,8 @@ 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); - } + mAvatarList->getIDs().push_back(avatar_id); + mAvatarList->setDirty(); adjustParticipant(avatar_id); } @@ -659,20 +429,17 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() 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"); + LLContextMenu* main_menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( + "menu_participant_list.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); // Don't show sort options for P2P chat bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1); 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; @@ -680,20 +447,22 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y) { - if (uuids.size() == 0) return; + LLPanelPeopleMenus::ContextMenu::show(spawning_view, uuids, x, y); - LLListContextMenu::show(spawning_view, uuids, x, y); + if (uuids.size() == 0) return; - const LLUUID& speaker_id = mUUIDs.front(); + const LLUUID speaker_id = mUUIDs.front(); BOOL is_muted = isMuted(speaker_id); if (is_muted) { LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceMuteSelected", false); + LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceMuteOthers", false); } else { LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteSelected", false); + LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteOthers", false); } } @@ -733,26 +502,10 @@ void LLParticipantList::LLParticipantListMenu::toggleMute(const LLSD& userdata, { return; } - LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(mParent.mAvatarList->getItemByValue(speaker_id)); - if (NULL == item) return; - name = item->getAvatarName(); + name = speakerp->mDisplayName; - 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); + LLMute mute(speaker_id, name, speakerp->mType == LLSpeaker::SPEAKER_AGENT ? LLMute::AGENT : LLMute::OBJECT); if (!is_muted) { @@ -798,17 +551,16 @@ void LLParticipantList::LLParticipantListMenu::moderateVoice(const LLSD& userdat if (!gAgent.getRegion()) return; bool moderate_selected = userdata.asString() == "selected"; + const LLUUID& selected_avatar_id = mUUIDs.front(); + bool is_muted = isMuted(selected_avatar_id); 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); + moderateVoiceOtherParticipants(selected_avatar_id, is_muted); } } @@ -821,62 +573,40 @@ void LLParticipantList::LLParticipantListMenu::moderateVoiceParticipant(const LL } } -void LLParticipantList::LLParticipantListMenu::moderateVoiceAllParticipants(bool unmute) +void LLParticipantList::LLParticipantListMenu::moderateVoiceOtherParticipants(const LLUUID& excluded_avatar_id, bool unmute) { LLIMSpeakerMgr* mgr = dynamic_cast<LLIMSpeakerMgr*>(mParent.mSpeakerMgr); if (mgr) { - if (!unmute) - { - LLSD payload; - payload["session_id"] = mgr->getSessionID(); - LLNotificationsUtil::add("ConfirmMuteAll", LLSD(), payload, confirmMuteAllCallback); - return; - } - - mgr->moderateVoiceAllParticipants(unmute); + mgr->moderateVoiceOtherParticipants(excluded_avatar_id, 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<LLIMSpeakerMgr*> ( - 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 == "can_allow_text_chat") + { + return isGroupModerator(); + } + else if ("can_moderate_voice" == item) + { + if (isGroupModerator()) + { + LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(mUUIDs.front()); + if (speakerp.notNull()) + { + // not in voice participants can not be moderated + return speakerp->isInVoiceChannel(); + } + } + return false; + } else if (item == std::string("can_add")) { // We can add friends if: @@ -902,43 +632,13 @@ bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& else if (item == "can_call") { bool not_agent = mUUIDs.front() != gAgentID; - bool can_call = not_agent && LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); + bool can_call = not_agent && LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking(); return can_call; } 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<LLSpeaker> 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(); |