Skip to content

Commit cf048cf

Browse files
#4013 Update voice moderator options; show notifications when muted; add stub code for info request
1 parent 21e9b38 commit cf048cf

File tree

8 files changed

+165
-46
lines changed

8 files changed

+165
-46
lines changed

indra/newview/llfloaterimcontainer.cpp

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param
9292

9393
mAutoResize = false;
9494
LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);
95+
LLNearbyVoiceModeration::getInstance();
9596
}
9697

9798
LLFloaterIMContainer::~LLFloaterIMContainer()
@@ -543,7 +544,7 @@ void LLFloaterIMContainer::idleUpdate()
543544
dynamic_cast<LLConversationItemParticipant*>((*current_participant_model).get());
544545
if (participant_model)
545546
{
546-
participant_model->setModeratorOptionsVisible(isNearbyChatModerator());
547+
participant_model->setModeratorOptionsVisible(LLNearbyVoiceModeration::getInstance()->isNearbyChatModerator());
547548
}
548549

549550
current_participant_model++;
@@ -2037,7 +2038,7 @@ LLConversationViewParticipant* LLFloaterIMContainer::createConversationViewParti
20372038

20382039
bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& userdata, bool is_self)
20392040
{
2040-
if (isNearbyChatModerator() && isNearbyChatSpeakerSelected())
2041+
if (LLNearbyVoiceModeration::getInstance()->isNearbyChatModerator() && isNearbyChatSpeakerSelected())
20412042
{
20422043
// Determine here which actions are allowed
20432044
if ("can_moderate_voice" == userdata)
@@ -2046,7 +2047,7 @@ bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& user
20462047
}
20472048
else if (("can_mute" == userdata))
20482049
{
2049-
return true;
2050+
return !is_self;
20502051
}
20512052
else if ("can_unmute" == userdata)
20522053
{
@@ -2199,39 +2200,19 @@ void LLFloaterIMContainer::moderateVoice(const std::string& command, const LLUUI
21992200
{
22002201
if ("selected" == command)
22012202
{
2202-
// Toggle the voice icon display
2203-
LLAvatarActions::toggleMuteVoice(userID);
2204-
22052203
// Request a mute/unmute using a capability request via the simulator
2206-
const bool mute_state = LLAvatarActions::isVoiceMuted(userID);
2207-
LLNearbyVoiceModeration::getInstance()->requestMuteIndividual(userID, mute_state);
2204+
LLNearbyVoiceModeration::getInstance()->requestMuteIndividual(userID, !isMuted(userID));
22082205
}
22092206
else
22102207
if ("mute_all" == command)
22112208
{
2212-
// TODO: the SpatialVoiceModerationRequest has an mute_all/unmute_all
2213-
// verb but we do not have an equivalent of LLAvatarActions::toggleMuteVoice(userID);
2214-
// to visually mute all the speaker icons in the conversation floater
2215-
2216-
// Mute visually too
2217-
conversations_widgets_map::const_iterator iter = mConversationsWidgets.begin();
2218-
conversations_widgets_map::const_iterator end = mConversationsWidgets.end();
2219-
const LLUUID * conversation_uuidp = NULL;
2220-
while(iter != end)
2221-
{
2222-
const LLUUID id = (*iter).first;
2223-
++iter;
2224-
}
2225-
22262209
// Send the mute_all request to the server
22272210
const bool mute_state = true;
22282211
LLNearbyVoiceModeration::getInstance()->requestMuteAll(mute_state);
22292212
}
22302213
else
22312214
if ("unmute_all" == command)
22322215
{
2233-
// TODO: same idea as "mute_all" above
2234-
22352216
// Send the unmute_all request to the server
22362217
const bool mute_state = false;
22372218
LLNearbyVoiceModeration::getInstance()->requestMuteAll(mute_state);
@@ -2381,12 +2362,6 @@ bool LLFloaterIMContainer::isNearbyChatSpeakerSelected()
23812362
return conversation_uuidp->isNull();
23822363
}
23832364

2384-
bool LLFloaterIMContainer::isNearbyChatModerator()
2385-
{
2386-
// TODO: Need a better heurestic for determining if this person is a moderator :)
2387-
return true;
2388-
}
2389-
23902365
void LLFloaterIMContainer::toggleAllowTextChat(const LLUUID& participant_uuid)
23912366
{
23922367
LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr*>(getSpeakerMgrForSelectedParticipant());

indra/newview/llfloaterimcontainer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,6 @@ class LLFloaterIMContainer
179179
void openNearbyChat();
180180
bool isParticipantListExpanded();
181181
bool isNearbyChatSpeakerSelected();
182-
bool isNearbyChatModerator();
183182

184183
void idleUpdate(); // for convenience (self) from static idle
185184
void idleProcessEvents();

indra/newview/llnearbyvoicemoderation.cpp

Lines changed: 107 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,29 @@
2626
#include "llviewerprecompiledheaders.h"
2727

2828
#include "llagent.h"
29+
#include "llnotificationsutil.h"
2930
#include "llviewerregion.h"
3031
#include "llvoavatar.h"
32+
#include "llvoiceclient.h"
3133
#include "llviewerobjectlist.h"
3234

3335
#include "llnearbyvoicemoderation.h"
3436

37+
LLNearbyVoiceModeration::LLNearbyVoiceModeration()
38+
{
39+
// TODO: default to false, when appropriate info cap is added
40+
mIsNearbyChatModerator = true;
41+
mParcelCallbackConnection = gAgent.addParcelChangedCallback([this]() { updateModeratorStatus(); });
42+
}
43+
44+
LLNearbyVoiceModeration::~LLNearbyVoiceModeration()
45+
{
46+
if (mParcelCallbackConnection.connected())
47+
{
48+
mParcelCallbackConnection.disconnect();
49+
}
50+
}
51+
3552
LLVOAvatar* LLNearbyVoiceModeration::getVOAvatarFromId(const LLUUID& agent_id)
3653
{
3754
LLViewerObject *obj = gObjectList.findObject(agent_id);
@@ -54,18 +71,12 @@ const std::string LLNearbyVoiceModeration::getCapUrlFromRegion(LLViewerRegion* r
5471
{
5572
if (! region || ! region->capabilitiesReceived())
5673
{
57-
// TODO: Retry if fails since the capabilities may not have been received
58-
// if this is called early into a region entry
59-
LL_INFOS() << "Region or region capabilities unavailable." << LL_ENDL;
6074
return std::string();
6175
}
62-
LL_INFOS() << "Capabilities for region " << region->getName() << " received." << LL_ENDL;
6376

6477
std::string url = region->getCapability("SpatialVoiceModerationRequest");
6578
if (url.empty())
6679
{
67-
// TODO: Retry if fails since URL may not have not be available
68-
// if this is called early into a region entry
6980
LL_INFOS() << "Capability URL for region " << region->getName() << " is empty" << LL_ENDL;
7081
return std::string();
7182
}
@@ -139,3 +150,93 @@ void LLNearbyVoiceModeration::requestMuteAll(bool mute)
139150
failure_msg);
140151
}
141152
}
153+
154+
void LLNearbyVoiceModeration::setMutedInfo(const std::string& channelID, bool mute)
155+
{
156+
auto it = mChannelMuteMap.find(channelID);
157+
if (it == mChannelMuteMap.end())
158+
{
159+
if (mute)
160+
{
161+
// Channel is new and being muted
162+
showMutedNotification(true);
163+
}
164+
mChannelMuteMap[channelID] = mute;
165+
}
166+
else
167+
{
168+
if (it->second != mute)
169+
{
170+
// Flag changed
171+
showMutedNotification(mute);
172+
it->second = mute;
173+
}
174+
}
175+
}
176+
177+
void LLNearbyVoiceModeration::showNotificationIfNeeded()
178+
{
179+
if (LLVoiceClient::getInstance()->inProximalChannel() &&
180+
LLVoiceClient::getInstance()->getIsModeratorMuted(gAgentID))
181+
{
182+
showMutedNotification(true);
183+
}
184+
}
185+
186+
void LLNearbyVoiceModeration::showMutedNotification(bool is_muted)
187+
{
188+
// Check if the current voice channel is nearby chat
189+
if (LLVoiceClient::getInstance()->inProximalChannel())
190+
{
191+
LLNotificationsUtil::add(is_muted ? "NearbyVoiceMutedByModerator" : "NearbyVoiceUnmutedByModerator");
192+
}
193+
}
194+
195+
void LLNearbyVoiceModeration::updateModeratorStatus()
196+
{
197+
LL_WARNS() << "Request moderator status info" << LL_ENDL;
198+
// TODO: Uncomment and set correct capability name, when appropriate info cap is added
199+
/*
200+
if (LLViewerRegion* region = gAgent.getRegion())
201+
{
202+
203+
std::string url = region->getCapability("SpatialVoiceModerationInfoRequest");
204+
if (!url.empty())
205+
{
206+
LLCoros::instance().launch("getModeratorStatusCoro", [url]() { getModeratorStatusCoro(url); });
207+
}
208+
}
209+
*/
210+
}
211+
212+
void LLNearbyVoiceModeration::getModeratorStatusCoro(std::string cap_url)
213+
{
214+
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
215+
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getModeratorStatusCoro", httpPolicy));
216+
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
217+
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
218+
LLCore::HttpHeaders::ptr_t httpHeaders;
219+
220+
httpOpts->setFollowRedirects(true);
221+
222+
LLSD result = httpAdapter->getAndSuspend(httpRequest, cap_url, httpOpts, httpHeaders);
223+
224+
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
225+
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
226+
227+
if (!status)
228+
{
229+
LL_WARNS() << "Failed to get nearby voice moderator info" << LL_ENDL;
230+
return;
231+
}
232+
else if (!result["success"].asBoolean())
233+
{
234+
LL_WARNS() << "Failed to get nearby voice moderator info: " << result["message"] << LL_ENDL;
235+
return;
236+
}
237+
238+
// TODO: update the field, when appropriate info cap is added
239+
bool is_moderator = result["moderator"].asBoolean();
240+
LLNearbyVoiceModeration::getInstance()->setNearbyChatModerator(is_moderator);
241+
}
242+

indra/newview/llnearbyvoicemoderation.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,29 @@
2727

2828
class LLVOAvatar;
2929

30-
class LLNearbyVoiceModeration :
31-
public LLSingleton <LLNearbyVoiceModeration> {
32-
LLSINGLETON(LLNearbyVoiceModeration) {
33-
};
34-
35-
~LLNearbyVoiceModeration() {
36-
};
30+
class LLNearbyVoiceModeration : public LLSingleton <LLNearbyVoiceModeration> {
31+
LLSINGLETON(LLNearbyVoiceModeration);
32+
~LLNearbyVoiceModeration();
3733

3834
public:
39-
LLVOAvatar* getVOAvatarFromId(const LLUUID& id);
4035
void requestMuteIndividual(const LLUUID& userID, bool mute);
4136
void requestMuteAll(bool mute);
4237

38+
void setMutedInfo(const std::string& channelID, bool mute);
39+
void showMutedNotification(bool is_muted);
40+
void showNotificationIfNeeded();
41+
42+
void updateModeratorStatus();
43+
static void getModeratorStatusCoro(std::string cap_url);
44+
45+
bool isNearbyChatModerator() { return mIsNearbyChatModerator; };
46+
void setNearbyChatModerator(bool moderator) { mIsNearbyChatModerator = moderator; }
47+
4348
private:
49+
LLVOAvatar* getVOAvatarFromId(const LLUUID& id);
4450
const std::string getCapUrlFromRegion(LLViewerRegion* region);
51+
52+
boost::signals2::connection mParcelCallbackConnection;
53+
std::map<std::string, bool> mChannelMuteMap;
54+
bool mIsNearbyChatModerator;
4555
};

indra/newview/llviewerregion.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3300,6 +3300,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
33003300
capabilityNames.append("SetDisplayName");
33013301
capabilityNames.append("SimConsoleAsync");
33023302
capabilityNames.append("SimulatorFeatures");
3303+
capabilityNames.append("SpatialVoiceModerationRequest");
33033304
capabilityNames.append("StartGroupProposal");
33043305
capabilityNames.append("TerrainNavMeshProperties");
33053306
capabilityNames.append("TextureStats");

indra/newview/llvoiceclient.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "llagent.h"
4040
#include "lltrans.h"
4141
#include "lluiusage.h"
42+
#include "llnearbyvoicemoderation.h"
4243

4344
const F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f;
4445

@@ -712,6 +713,9 @@ bool LLVoiceClient::getPTTIsToggle()
712713

713714
void LLVoiceClient::inputUserControlState(bool down)
714715
{
716+
if (down && !getUserPTTState())
717+
LLNearbyVoiceModeration::getInstance()->showNotificationIfNeeded();
718+
715719
if(mPTTIsToggle)
716720
{
717721
if(down) // toggle open-mic state on 'down'

indra/newview/llvoicewebrtc.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565

6666
#include "llviewernetwork.h"
6767
#include "llnotificationsutil.h"
68+
#include "llnearbyvoicemoderation.h"
6869

6970
#include "llcorehttputil.h"
7071
#include "lleventfilter.h"
@@ -3194,14 +3195,19 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b
31943195
participant->mIsSpeaking = participant_obj["v"].as_bool();
31953196
}
31963197

3198+
// Currently, viewer doesn't receive this info when the user is muted in Nearby chat,
3199+
// but it *does* receive it when muted in Group chat. A server-side change is required.
31973200
if (participant_obj.contains("m") && participant_obj["m"].is_bool())
31983201
{
31993202
participant->mIsModeratorMuted = participant_obj["m"].as_bool();
3203+
if (isSpatial() && (gAgentID == agent_id))
3204+
{
3205+
LLNearbyVoiceModeration::getInstance()->setMutedInfo(mChannelID, participant->mIsModeratorMuted);
3206+
}
32003207
}
32013208
}
32023209
}
32033210
}
3204-
32053211
// tell the simulator to set the mute and volume data for this
32063212
// participant, if there are any updates.
32073213
boost::json::object root;

indra/newview/skins/default/xui/en/notifications.xml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9192,6 +9192,29 @@ Your voice has been muted by moderator.
91929192
yestext="OK"/>
91939193
</notification>
91949194

9195+
<notification
9196+
icon="alertmodal.tga"
9197+
name="NearbyVoiceMutedByModerator"
9198+
type="alertmodal">
9199+
The moderator has muted your voice chat.
9200+
People in this location will not hear you if you speak.
9201+
<tag>voice</tag>
9202+
<usetemplate
9203+
name="okbutton"
9204+
yestext="OK"/>
9205+
</notification>
9206+
9207+
<notification
9208+
icon="alertmodal.tga"
9209+
name="NearbyVoiceUnmutedByModerator"
9210+
type="alertmodal">
9211+
Your voice chat can now be heard by people in this location.
9212+
<tag>voice</tag>
9213+
<usetemplate
9214+
name="okbutton"
9215+
yestext="OK"/>
9216+
</notification>
9217+
91959218
<notification
91969219
icon="alertmodal.tga"
91979220
name="FailedToGetBenefits"

0 commit comments

Comments
 (0)