Skip to content

Commit 0a14318

Browse files
committed
First commit for a second experiment, investigating how nearby voice/chat moderation might work
1 parent c257304 commit 0a14318

File tree

6 files changed

+291
-57
lines changed

6 files changed

+291
-57
lines changed

indra/newview/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ set(viewer_SOURCE_FILES
414414
llfloaterimnearbychat.cpp
415415
llfloaterimnearbychathandler.cpp
416416
llfloaterimnearbychatlistener.cpp
417+
llnearbyvoicemoderation.cpp
417418
llnetmap.cpp
418419
llnotificationalerthandler.cpp
419420
llnotificationgrouphandler.cpp
@@ -1087,6 +1088,7 @@ set(viewer_HEADER_FILES
10871088
llnameeditor.h
10881089
llnamelistctrl.h
10891090
llnavigationbar.h
1091+
llnearbyvoicemoderation.h
10901092
llnetmap.h
10911093
llnotificationhandler.h
10921094
llnotificationlistitem.h

indra/newview/llfloaterimcontainer.cpp

Lines changed: 91 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
#include "llsdserialize.h"
5858
#include "llviewermenu.h" // is_agent_mappable
5959
#include "llviewerobjectlist.h"
60+
#include "llvoavatar.h"
61+
#include "llnearbyvoicemoderation.h"
6062

6163

6264
const S32 EVENTS_PER_IDLE_LOOP_CURRENT_SESSION = 80;
@@ -502,12 +504,13 @@ void LLFloaterIMContainer::idleUpdate()
502504
const LLConversationItem *current_session = getCurSelectedViewModelItem();
503505
if (current_session)
504506
{
505-
if (current_session->getType() == LLConversationItem::CONV_SESSION_GROUP)
507+
bool is_nearby_chat = current_session->getType() == LLConversationItem::CONV_SESSION_NEARBY;
508+
if (current_session->getType() == LLConversationItem::CONV_SESSION_GROUP || is_nearby_chat)
506509
{
507510
// Update moderator options visibility
508511
LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = current_session->getChildrenBegin();
509512
LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = current_session->getChildrenEnd();
510-
bool is_moderator = isGroupModerator();
513+
bool is_moderator = isGroupModerator() || (is_nearby_chat && isNearbyChatModerator());
511514
bool can_ban = haveAbilityToBan();
512515
while (current_participant_model != end_participant_model)
513516
{
@@ -1685,6 +1688,10 @@ bool LLFloaterIMContainer::visibleContextMenuItem(const LLSD& userdata)
16851688
{
16861689
return isMuted(conversation_item->getUUID());
16871690
}
1691+
else if ("can_allow_text_chat" == item)
1692+
{
1693+
return !isNearbyChatSpeakerSelected();
1694+
}
16881695

16891696
return true;
16901697
}
@@ -2009,9 +2016,27 @@ LLConversationViewParticipant* LLFloaterIMContainer::createConversationViewParti
20092016

20102017
bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& userdata, bool is_self)
20112018
{
2012-
// only group moderators can perform actions related to this "enable callback"
2013-
if (!isGroupModerator())
2019+
if (isNearbyChatModerator() && isNearbyChatSpeakerSelected())
2020+
{
2021+
// Determine here which actions are allowed
2022+
if ("can_moderate_voice" == userdata)
2023+
{
2024+
return true;
2025+
}
2026+
else if (("can_mute" == userdata))
2027+
{
2028+
return true;
2029+
}
2030+
else if ("can_unmute" == userdata)
2031+
{
2032+
return true;
2033+
}
2034+
2035+
return false;
2036+
}
2037+
else if (!isGroupModerator())
20142038
{
2039+
// only group moderators can perform actions related to this "enable callback"
20152040
return false;
20162041
}
20172042

@@ -2144,7 +2169,37 @@ void LLFloaterIMContainer::banSelectedMember(const LLUUID& participant_uuid)
21442169

21452170
void LLFloaterIMContainer::moderateVoice(const std::string& command, const LLUUID& userID)
21462171
{
2147-
if (!gAgent.getRegion()) return;
2172+
if (!gAgent.getRegion())
2173+
{
2174+
return;
2175+
}
2176+
2177+
if (isNearbyChatSpeakerSelected())
2178+
{
2179+
if ("selected" == command)
2180+
{
2181+
// Toggle the voice icon display
2182+
LLAvatarActions::toggleMuteVoice(userID);
2183+
2184+
// Request a mute/unmute using a capability request via the simulator
2185+
const bool mute_state = LLAvatarActions::isVoiceMuted(userID);
2186+
LLNearbyVoiceModeration::getInstance()->requestMuteChange(userID, mute_state);
2187+
}
2188+
else
2189+
if ("mute_all" == command)
2190+
{
2191+
// TODO: the SpatialVoiceModerationRequest has an mute_all/unmute_all
2192+
// verb but we do not have an equivalent of LLAvatarActions::toggleMuteVoice(userID);
2193+
// to visually mute all the speaker icons in the conversation floater
2194+
}
2195+
else
2196+
if ("unmute_all" == command)
2197+
{
2198+
// TODO: same idea as "mute_all" above
2199+
}
2200+
2201+
return;
2202+
}
21482203

21492204
if (command.compare("selected"))
21502205
{
@@ -2262,6 +2317,37 @@ LLSpeaker * LLFloaterIMContainer::getSpeakerOfSelectedParticipant(LLSpeakerMgr *
22622317
return speaker_managerp->findSpeaker(participant_itemp->getUUID());
22632318
}
22642319

2320+
bool LLFloaterIMContainer::isNearbyChatSpeakerSelected()
2321+
{
2322+
LLFolderViewItem *selectedItem = mConversationsRoot->getCurSelectedItem();
2323+
if (NULL == selectedItem)
2324+
{
2325+
LL_WARNS() << "Current selected item is null" << LL_ENDL;
2326+
return NULL;
2327+
}
2328+
2329+
conversations_widgets_map::const_iterator iter = mConversationsWidgets.begin();
2330+
conversations_widgets_map::const_iterator end = mConversationsWidgets.end();
2331+
const LLUUID * conversation_uuidp = NULL;
2332+
while(iter != end)
2333+
{
2334+
if (iter->second == selectedItem || iter->second == selectedItem->getParentFolder())
2335+
{
2336+
conversation_uuidp = &iter->first;
2337+
break;
2338+
}
2339+
++iter;
2340+
}
2341+
// Nearby chat ID is LLUUID::null
2342+
return conversation_uuidp->isNull();
2343+
}
2344+
2345+
bool LLFloaterIMContainer::isNearbyChatModerator()
2346+
{
2347+
// TODO: Need a better heurestic for determining if this person is a moderator :)
2348+
return true;
2349+
}
2350+
22652351
void LLFloaterIMContainer::toggleAllowTextChat(const LLUUID& participant_uuid)
22662352
{
22672353
LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr*>(getSpeakerMgrForSelectedParticipant());

indra/newview/llfloaterimcontainer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ class LLFloaterIMContainer
178178
void banSelectedMember(const LLUUID& participant_uuid);
179179
void openNearbyChat();
180180
bool isParticipantListExpanded();
181+
bool isNearbyChatSpeakerSelected();
182+
bool isNearbyChatModerator();
181183

182184
void idleUpdate(); // for convenience (self) from static idle
183185
void idleProcessEvents();
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/**
2+
* @file llnearbyvoicemoderation.cpp
3+
*
4+
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
5+
* Second Life Viewer Source Code
6+
* Copyright (C) 2010, Linden Research, Inc.
7+
*
8+
* This library is free software; you can redistribute it and/or
9+
* modify it under the terms of the GNU Lesser General Public
10+
* License as published by the Free Software Foundation;
11+
* version 2.1 of the License only.
12+
*
13+
* This library is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16+
* Lesser General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public
19+
* License along with this library; if not, write to the Free Software
20+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21+
*
22+
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
23+
* $/LicenseInfo$
24+
*/
25+
26+
#include "llviewerprecompiledheaders.h"
27+
28+
#include "llagent.h"
29+
#include "llviewerregion.h"
30+
#include "llvoavatar.h"
31+
#include "llviewerobjectlist.h"
32+
33+
#include "llnearbyvoicemoderation.h"
34+
35+
LLVOAvatar* LLNearbyVoiceModeration::getVOAvatarFromId(const LLUUID& agent_id)
36+
{
37+
LLViewerObject *obj = gObjectList.findObject(agent_id);
38+
while (obj && obj->isAttachment())
39+
{
40+
obj = (LLViewerObject*)obj->getParent();
41+
}
42+
43+
if (obj && obj->isAvatar())
44+
{
45+
return (LLVOAvatar*)obj;
46+
}
47+
else
48+
{
49+
return NULL;
50+
}
51+
}
52+
53+
void LLNearbyVoiceModeration::requestMuteChange(const LLUUID& agent_id, bool mute)
54+
{
55+
LLVOAvatar* avatar = getVOAvatarFromId(agent_id);
56+
if (avatar)
57+
{
58+
LLViewerRegion* region = avatar->getRegion();
59+
if (! region || ! region->capabilitiesReceived())
60+
{
61+
// TODO: Retry if fails since the capabilities may not have been received
62+
// if this is called early into a region entry
63+
LL_INFOS() << "Region or region capabilities unavailable" << LL_ENDL;
64+
return;
65+
}
66+
LL_INFOS() << "Region name is " << region->getName() << LL_ENDL;
67+
68+
std::string url = region->getCapability("SpatialVoiceModerationRequest");
69+
if (url.empty())
70+
{
71+
// TODO: Retry if fails since URL may not have not be available
72+
// if this is called early into a region entry
73+
LL_INFOS() << "Capability URL is empty" << LL_ENDL;
74+
return;
75+
}
76+
LL_INFOS() << "Capability URL is " << url << LL_ENDL;
77+
78+
const std::string agent_name = avatar->getFullname();
79+
80+
const std::string operand = mute ? "mute" : "unmute";
81+
82+
LLSD body;
83+
body["operand"] = operand;
84+
body["agent_id"] = agent_id;
85+
body["moderator_id"] = gAgent.getID();
86+
87+
LL_INFOS() << "Resident " << agent_name
88+
<< " (" << agent_id << ")" << " applying " << operand << LL_ENDL;
89+
90+
std::string success_msg =
91+
STRINGIZE("Resident " << agent_name
92+
<< " (" << agent_id << ")" << " nearby voice was set to " << operand);
93+
94+
std::string failure_msg =
95+
STRINGIZE("Unable to change voice muting for resident "
96+
<< agent_name << " (" << agent_id << ")");
97+
98+
LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body,
99+
success_msg,
100+
failure_msg);
101+
}
102+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* @file llnearbyvoicemoderation.h
3+
*
4+
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
5+
* Second Life Viewer Source Code
6+
* Copyright (C) 2010, Linden Research, Inc.
7+
*
8+
* This library is free software; you can redistribute it and/or
9+
* modify it under the terms of the GNU Lesser General Public
10+
* License as published by the Free Software Foundation;
11+
* version 2.1 of the License only.
12+
*
13+
* This library is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16+
* Lesser General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public
19+
* License along with this library; if not, write to the Free Software
20+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21+
*
22+
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
23+
* $/LicenseInfo$
24+
*/
25+
26+
#pragma once
27+
28+
class LLVOAvatar;
29+
30+
class LLNearbyVoiceModeration :
31+
public LLSingleton <LLNearbyVoiceModeration> {
32+
LLSINGLETON(LLNearbyVoiceModeration) {
33+
};
34+
35+
~LLNearbyVoiceModeration() {
36+
};
37+
38+
public:
39+
LLVOAvatar* getVOAvatarFromId(const LLUUID& id);
40+
void requestMuteChange(const LLUUID& userID, bool mute);
41+
};

0 commit comments

Comments
 (0)