summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/llfloaterimcontainer.cpp35
-rw-r--r--indra/newview/llfloaterimcontainer.h1
-rw-r--r--indra/newview/llnearbyvoicemoderation.cpp113
-rw-r--r--indra/newview/llnearbyvoicemoderation.h26
-rwxr-xr-xindra/newview/llviewerregion.cpp1
-rw-r--r--indra/newview/llvoiceclient.cpp4
-rw-r--r--indra/newview/llvoicewebrtc.cpp8
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml23
8 files changed, 165 insertions, 46 deletions
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index c25fbdcc51..ac8234bf24 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -92,6 +92,7 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param
mAutoResize = false;
LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);
+ LLNearbyVoiceModeration::getInstance();
}
LLFloaterIMContainer::~LLFloaterIMContainer()
@@ -543,7 +544,7 @@ void LLFloaterIMContainer::idleUpdate()
dynamic_cast<LLConversationItemParticipant*>((*current_participant_model).get());
if (participant_model)
{
- participant_model->setModeratorOptionsVisible(isNearbyChatModerator());
+ participant_model->setModeratorOptionsVisible(LLNearbyVoiceModeration::getInstance()->isNearbyChatModerator());
}
current_participant_model++;
@@ -2037,7 +2038,7 @@ LLConversationViewParticipant* LLFloaterIMContainer::createConversationViewParti
bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& userdata, bool is_self)
{
- if (isNearbyChatModerator() && isNearbyChatSpeakerSelected())
+ if (LLNearbyVoiceModeration::getInstance()->isNearbyChatModerator() && isNearbyChatSpeakerSelected())
{
// Determine here which actions are allowed
if ("can_moderate_voice" == userdata)
@@ -2046,7 +2047,7 @@ bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& user
}
else if (("can_mute" == userdata))
{
- return true;
+ return !is_self;
}
else if ("can_unmute" == userdata)
{
@@ -2199,30 +2200,12 @@ void LLFloaterIMContainer::moderateVoice(const std::string& command, const LLUUI
{
if ("selected" == command)
{
- // Toggle the voice icon display
- LLAvatarActions::toggleMuteVoice(userID);
-
// Request a mute/unmute using a capability request via the simulator
- const bool mute_state = LLAvatarActions::isVoiceMuted(userID);
- LLNearbyVoiceModeration::getInstance()->requestMuteIndividual(userID, mute_state);
+ LLNearbyVoiceModeration::getInstance()->requestMuteIndividual(userID, !isMuted(userID));
}
else
if ("mute_all" == command)
{
- // TODO: the SpatialVoiceModerationRequest has an mute_all/unmute_all
- // verb but we do not have an equivalent of LLAvatarActions::toggleMuteVoice(userID);
- // to visually mute all the speaker icons in the conversation floater
-
- // Mute visually too
- conversations_widgets_map::const_iterator iter = mConversationsWidgets.begin();
- conversations_widgets_map::const_iterator end = mConversationsWidgets.end();
- const LLUUID * conversation_uuidp = NULL;
- while(iter != end)
- {
- const LLUUID id = (*iter).first;
- ++iter;
- }
-
// Send the mute_all request to the server
const bool mute_state = true;
LLNearbyVoiceModeration::getInstance()->requestMuteAll(mute_state);
@@ -2230,8 +2213,6 @@ void LLFloaterIMContainer::moderateVoice(const std::string& command, const LLUUI
else
if ("unmute_all" == command)
{
- // TODO: same idea as "mute_all" above
-
// Send the unmute_all request to the server
const bool mute_state = false;
LLNearbyVoiceModeration::getInstance()->requestMuteAll(mute_state);
@@ -2381,12 +2362,6 @@ bool LLFloaterIMContainer::isNearbyChatSpeakerSelected()
return conversation_uuidp->isNull();
}
-bool LLFloaterIMContainer::isNearbyChatModerator()
-{
- // TODO: Need a better heurestic for determining if this person is a moderator :)
- return true;
-}
-
void LLFloaterIMContainer::toggleAllowTextChat(const LLUUID& participant_uuid)
{
LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr*>(getSpeakerMgrForSelectedParticipant());
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index c91093c107..9f1690a9b9 100644
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -179,7 +179,6 @@ private:
void openNearbyChat();
bool isParticipantListExpanded();
bool isNearbyChatSpeakerSelected();
- bool isNearbyChatModerator();
void idleUpdate(); // for convenience (self) from static idle
void idleProcessEvents();
diff --git a/indra/newview/llnearbyvoicemoderation.cpp b/indra/newview/llnearbyvoicemoderation.cpp
index 5ae8feba08..ec0e1c0431 100644
--- a/indra/newview/llnearbyvoicemoderation.cpp
+++ b/indra/newview/llnearbyvoicemoderation.cpp
@@ -26,12 +26,29 @@
#include "llviewerprecompiledheaders.h"
#include "llagent.h"
+#include "llnotificationsutil.h"
#include "llviewerregion.h"
#include "llvoavatar.h"
+#include "llvoiceclient.h"
#include "llviewerobjectlist.h"
#include "llnearbyvoicemoderation.h"
+LLNearbyVoiceModeration::LLNearbyVoiceModeration()
+{
+ // TODO: default to false, when appropriate info cap is added
+ mIsNearbyChatModerator = true;
+ mParcelCallbackConnection = gAgent.addParcelChangedCallback([this]() { updateModeratorStatus(); });
+}
+
+LLNearbyVoiceModeration::~LLNearbyVoiceModeration()
+{
+ if (mParcelCallbackConnection.connected())
+ {
+ mParcelCallbackConnection.disconnect();
+ }
+}
+
LLVOAvatar* LLNearbyVoiceModeration::getVOAvatarFromId(const LLUUID& agent_id)
{
LLViewerObject *obj = gObjectList.findObject(agent_id);
@@ -54,18 +71,12 @@ const std::string LLNearbyVoiceModeration::getCapUrlFromRegion(LLViewerRegion* r
{
if (! region || ! region->capabilitiesReceived())
{
- // TODO: Retry if fails since the capabilities may not have been received
- // if this is called early into a region entry
- LL_INFOS() << "Region or region capabilities unavailable." << LL_ENDL;
return std::string();
}
- LL_INFOS() << "Capabilities for region " << region->getName() << " received." << LL_ENDL;
std::string url = region->getCapability("SpatialVoiceModerationRequest");
if (url.empty())
{
- // TODO: Retry if fails since URL may not have not be available
- // if this is called early into a region entry
LL_INFOS() << "Capability URL for region " << region->getName() << " is empty" << LL_ENDL;
return std::string();
}
@@ -139,3 +150,93 @@ void LLNearbyVoiceModeration::requestMuteAll(bool mute)
failure_msg);
}
}
+
+void LLNearbyVoiceModeration::setMutedInfo(const std::string& channelID, bool mute)
+{
+ auto it = mChannelMuteMap.find(channelID);
+ if (it == mChannelMuteMap.end())
+ {
+ if (mute)
+ {
+ // Channel is new and being muted
+ showMutedNotification(true);
+ }
+ mChannelMuteMap[channelID] = mute;
+ }
+ else
+ {
+ if (it->second != mute)
+ {
+ // Flag changed
+ showMutedNotification(mute);
+ it->second = mute;
+ }
+ }
+}
+
+void LLNearbyVoiceModeration::showNotificationIfNeeded()
+{
+ if (LLVoiceClient::getInstance()->inProximalChannel() &&
+ LLVoiceClient::getInstance()->getIsModeratorMuted(gAgentID))
+ {
+ showMutedNotification(true);
+ }
+}
+
+void LLNearbyVoiceModeration::showMutedNotification(bool is_muted)
+{
+ // Check if the current voice channel is nearby chat
+ if (LLVoiceClient::getInstance()->inProximalChannel())
+ {
+ LLNotificationsUtil::add(is_muted ? "NearbyVoiceMutedByModerator" : "NearbyVoiceUnmutedByModerator");
+ }
+}
+
+void LLNearbyVoiceModeration::updateModeratorStatus()
+{
+ LL_WARNS() << "Request moderator status info" << LL_ENDL;
+ // TODO: Uncomment and set correct capability name, when appropriate info cap is added
+ /*
+ if (LLViewerRegion* region = gAgent.getRegion())
+ {
+
+ std::string url = region->getCapability("SpatialVoiceModerationInfoRequest");
+ if (!url.empty())
+ {
+ LLCoros::instance().launch("getModeratorStatusCoro", [url]() { getModeratorStatusCoro(url); });
+ }
+ }
+ */
+}
+
+void LLNearbyVoiceModeration::getModeratorStatusCoro(std::string cap_url)
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getModeratorStatusCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+ LLCore::HttpHeaders::ptr_t httpHeaders;
+
+ httpOpts->setFollowRedirects(true);
+
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, cap_url, httpOpts, httpHeaders);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ LL_WARNS() << "Failed to get nearby voice moderator info" << LL_ENDL;
+ return;
+ }
+ else if (!result["success"].asBoolean())
+ {
+ LL_WARNS() << "Failed to get nearby voice moderator info: " << result["message"] << LL_ENDL;
+ return;
+ }
+
+ // TODO: update the field, when appropriate info cap is added
+ bool is_moderator = result["moderator"].asBoolean();
+ LLNearbyVoiceModeration::getInstance()->setNearbyChatModerator(is_moderator);
+}
+
diff --git a/indra/newview/llnearbyvoicemoderation.h b/indra/newview/llnearbyvoicemoderation.h
index 8a1ca5af6b..21d185db54 100644
--- a/indra/newview/llnearbyvoicemoderation.h
+++ b/indra/newview/llnearbyvoicemoderation.h
@@ -27,19 +27,29 @@
class LLVOAvatar;
-class LLNearbyVoiceModeration :
- public LLSingleton <LLNearbyVoiceModeration> {
- LLSINGLETON(LLNearbyVoiceModeration) {
- };
-
- ~LLNearbyVoiceModeration() {
- };
+class LLNearbyVoiceModeration : public LLSingleton <LLNearbyVoiceModeration> {
+ LLSINGLETON(LLNearbyVoiceModeration);
+ ~LLNearbyVoiceModeration();
public:
- LLVOAvatar* getVOAvatarFromId(const LLUUID& id);
void requestMuteIndividual(const LLUUID& userID, bool mute);
void requestMuteAll(bool mute);
+ void setMutedInfo(const std::string& channelID, bool mute);
+ void showMutedNotification(bool is_muted);
+ void showNotificationIfNeeded();
+
+ void updateModeratorStatus();
+ static void getModeratorStatusCoro(std::string cap_url);
+
+ bool isNearbyChatModerator() { return mIsNearbyChatModerator; };
+ void setNearbyChatModerator(bool moderator) { mIsNearbyChatModerator = moderator; }
+
private:
+ LLVOAvatar* getVOAvatarFromId(const LLUUID& id);
const std::string getCapUrlFromRegion(LLViewerRegion* region);
+
+ boost::signals2::connection mParcelCallbackConnection;
+ std::map<std::string, bool> mChannelMuteMap;
+ bool mIsNearbyChatModerator;
};
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index a085bc4d91..fa60c36834 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -3300,6 +3300,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("SetDisplayName");
capabilityNames.append("SimConsoleAsync");
capabilityNames.append("SimulatorFeatures");
+ capabilityNames.append("SpatialVoiceModerationRequest");
capabilityNames.append("StartGroupProposal");
capabilityNames.append("TerrainNavMeshProperties");
capabilityNames.append("TextureStats");
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 71a9e71a9f..5a2ef248ba 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -39,6 +39,7 @@
#include "llagent.h"
#include "lltrans.h"
#include "lluiusage.h"
+#include "llnearbyvoicemoderation.h"
const F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f;
@@ -712,6 +713,9 @@ bool LLVoiceClient::getPTTIsToggle()
void LLVoiceClient::inputUserControlState(bool down)
{
+ if (down && !getUserPTTState())
+ LLNearbyVoiceModeration::getInstance()->showNotificationIfNeeded();
+
if(mPTTIsToggle)
{
if(down) // toggle open-mic state on 'down'
diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp
index 93f8f0d14a..1d78ca002a 100644
--- a/indra/newview/llvoicewebrtc.cpp
+++ b/indra/newview/llvoicewebrtc.cpp
@@ -65,6 +65,7 @@
#include "llviewernetwork.h"
#include "llnotificationsutil.h"
+#include "llnearbyvoicemoderation.h"
#include "llcorehttputil.h"
#include "lleventfilter.h"
@@ -3194,14 +3195,19 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b
participant->mIsSpeaking = participant_obj["v"].as_bool();
}
+ // Currently, viewer doesn't receive this info when the user is muted in Nearby chat,
+ // but it *does* receive it when muted in Group chat. A server-side change is required.
if (participant_obj.contains("m") && participant_obj["m"].is_bool())
{
participant->mIsModeratorMuted = participant_obj["m"].as_bool();
+ if (isSpatial() && (gAgentID == agent_id))
+ {
+ LLNearbyVoiceModeration::getInstance()->setMutedInfo(mChannelID, participant->mIsModeratorMuted);
+ }
}
}
}
}
-
// tell the simulator to set the mute and volume data for this
// participant, if there are any updates.
boost::json::object root;
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index dbd513afe8..3f9a2ba13e 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -9193,6 +9193,29 @@ Your voice has been muted by moderator.
</notification>
<notification
+ icon="alertmodal.tga"
+ name="NearbyVoiceMutedByModerator"
+ type="alertmodal">
+ The moderator has muted your voice chat.
+People in this location will not hear you if you speak.
+ <tag>voice</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="NearbyVoiceUnmutedByModerator"
+ type="alertmodal">
+ Your voice chat can now be heard by people in this location.
+ <tag>voice</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
icon="alertmodal.tga"
name="FailedToGetBenefits"
type="alertmodal">