From 10b5b957f276ac468cc42c59576647383fa49186 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 29 Dec 2016 13:09:40 -0800 Subject: [PATCH] Ahh...It's beautiful and simple now. --- assignment-client/src/audio/AudioMixer.cpp | 51 ------- assignment-client/src/audio/AudioMixer.h | 2 - interface/resources/qml/hifi/Pal.qml | 14 +- libraries/networking/src/NodeList.cpp | 137 ++++++++++-------- libraries/networking/src/NodeList.h | 6 +- libraries/networking/src/udt/PacketHeaders.h | 5 +- .../src/UsersScriptingInterface.cpp | 7 +- .../src/UsersScriptingInterface.h | 8 +- scripts/system/pal.js | 12 +- 9 files changed, 88 insertions(+), 154 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index d1f7abf379..01715497b1 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -65,8 +65,6 @@ AudioMixer::AudioMixer(ReceivedMessage& message) : packetReceiver.registerListener(PacketType::NegotiateAudioFormat, this, "handleNegotiateAudioFormat"); packetReceiver.registerListener(PacketType::MuteEnvironment, this, "handleMuteEnvironmentPacket"); packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket"); - packetReceiver.registerListener(PacketType::NodePersonalMuteRequest, this, "handleNodePersonalMuteRequestPacket"); - packetReceiver.registerListener(PacketType::NodePersonalMuteStatusRequest, this, "handleNodePersonalMuteStatusRequestPacket"); packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket"); packetReceiver.registerListener(PacketType::NodeMuteRequest, this, "handleNodeMuteRequestPacket"); packetReceiver.registerListener(PacketType::RadiusIgnoreRequest, this, "handleRadiusIgnoreRequestPacket"); @@ -227,55 +225,6 @@ void AudioMixer::handleNodeIgnoreRequestPacket(QSharedPointer p sendingNode->parseIgnoreRequestMessage(packet); } -void AudioMixer::handleNodePersonalMuteRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode) { - // parse out the UUID being muted from the packet - QUuid ignoredUUID = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); - bool enabled; - packet->readPrimitive(&enabled); - - if (!ignoredUUID.isNull() && ignoredUUID != _uuid) { - if (enabled) { - qDebug() << "Adding" << uuidStringWithoutCurlyBraces(ignoredUUID) << "to personally muted set for" - << uuidStringWithoutCurlyBraces(_uuid); - - // Add the session UUID to the set of personally muted ones for this listening node - sendingNode->addIgnoredNode(ignoredUUID); - } else { - qDebug() << "Removing" << uuidStringWithoutCurlyBraces(ignoredUUID) << "from personally muted set for" - << uuidStringWithoutCurlyBraces(_uuid); - - // Remove the session UUID to the set of personally muted ones for this listening node - sendingNode->removeIgnoredNode(ignoredUUID); - } - } else { - qWarning() << "Node::handlePersonalMutedNode called with null ID or ID of personal muting node."; - } -} - -void AudioMixer::handleNodePersonalMuteStatusRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode) { - // parse out the UUID whose personal mute status is being requested from the packet - QUuid UUIDToCheck = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); - - if (!UUIDToCheck.isNull()) { - // First, make sure we actually have a node with this UUID - auto limitedNodeList = DependencyManager::get(); - auto matchingNode = limitedNodeList->nodeWithUUID(UUIDToCheck); - - // If we do have a matching node... - if (matchingNode) { - auto personalMuteStatusPacket = NLPacket::create(PacketType::NodePersonalMuteStatusReply, NUM_BYTES_RFC4122_UUID + sizeof(bool), true); - bool isMuted = sendingNode->isIgnoringNodeWithID(UUIDToCheck); - - // write the node ID to the packet - personalMuteStatusPacket->write(UUIDToCheck.toRfc4122()); - personalMuteStatusPacket->writePrimitive(isMuted); - - qDebug() << "Personal Mute Status: node" << uuidStringWithoutCurlyBraces(UUIDToCheck) << "mute status:" << isMuted; - - limitedNodeList->sendPacket(std::move(personalMuteStatusPacket), *sendingNode); - } - } -} void AudioMixer::handleRadiusIgnoreRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode) { sendingNode->parseIgnoreRadiusRequestMessage(packet); } diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 5c98475790..59cdec7732 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -62,8 +62,6 @@ private slots: void handleNegotiateAudioFormat(QSharedPointer message, SharedNodePointer sendingNode); void handleNodeKilled(SharedNodePointer killedNode); void handleNodeIgnoreRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); - void handleNodePersonalMuteRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); - void handleNodePersonalMuteStatusRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); void handleRadiusIgnoreRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); void handleKillAvatarPacket(QSharedPointer packet, SharedNodePointer sendingNode); void handleNodeMuteRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 2c75e8f049..e6a762ecd8 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -202,7 +202,7 @@ Item { // This CheckBox belongs in the columns that contain the action buttons ("Mute", "Ban", etc) HifiControls.CheckBox { - visible: isCheckBox + visible: styleData.role === "personalMute" ? (model["ignore"] === true ? false : true) : isCheckBox anchors.centerIn: parent checked: model[styleData.role] boxSize: 24 @@ -211,7 +211,10 @@ Item { var datum = userData[model.userIndex] datum[styleData.role] = model[styleData.role] = newValue if (styleData.role === "personalMute" || styleData.role === "ignore") { - Users[styleData.role](model.sessionId, newValue) + Users[styleData.role](model.sessionId, newValue) + if (styleData.role === "ignore") { + datum["personalMute"] = model["personalMute"] = newValue + } } else { Users[styleData.role](model.sessionId) // Just for now, while we cannot undo things: @@ -404,13 +407,6 @@ Item { } } break; - case 'updatePersonalMutedStatus': - var userId = message.params[0]; - var enabled = message.params[1]; - var userIndex = findSessionIndex(userId); - userModel.setProperty(userIndex, "personalMute", enabled); - userData[userIndex].personalMute.property = enabled; // Defensive programming - break; default: console.log('Unrecognized message:', JSON.stringify(message)); } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 0657b2c5ac..8b4cb41cc9 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -129,7 +129,6 @@ NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort) packetReceiver.registerListener(PacketType::DomainServerPathResponse, this, "processDomainServerPathResponse"); packetReceiver.registerListener(PacketType::DomainServerRemovedNode, this, "processDomainServerRemovedNode"); packetReceiver.registerListener(PacketType::UsernameFromIDReply, this, "processUsernameFromIDReply"); - packetReceiver.registerListener(PacketType::NodePersonalMuteStatusReply, this, "processPersonalMuteStatusReply"); } qint64 NodeList::sendStats(QJsonObject statsObject, HifiSockAddr destination) { @@ -802,14 +801,18 @@ void NodeList::ignoreNodeBySessionID(const QUuid& nodeID, bool ignoreEnabled) { sendPacket(std::move(ignorePacket), *destinationNode); }); - QReadLocker setLocker { &_ignoredSetLock }; // write lock for insert and unsafe_erase + QReadLocker ignoredSetLocker { &_ignoredSetLock }; // write lock for insert and unsafe_erase + QReadLocker personalMutedSetLocker{ &_personalMutedSetLock }; // write lock for insert and unsafe_erase if (ignoreEnabled) { // add this nodeID to our set of ignored IDs _ignoredNodeIDs.insert(nodeID); + // add this nodeID to our set of personal muted IDs + _personalMutedNodeIDs.insert(nodeID); emit ignoredNode(nodeID); } else { _ignoredNodeIDs.unsafe_erase(nodeID); + _personalMutedNodeIDs.unsafe_erase(nodeID); emit unignoredNode(nodeID); } @@ -819,16 +822,82 @@ void NodeList::ignoreNodeBySessionID(const QUuid& nodeID, bool ignoreEnabled) { } bool NodeList::isIgnoringNode(const QUuid& nodeID) const { - QReadLocker setLocker { &_ignoredSetLock }; + QReadLocker ignoredSetLocker{ &_ignoredSetLock }; return _ignoredNodeIDs.find(nodeID) != _ignoredNodeIDs.cend(); } +void NodeList::personalMuteNodeBySessionID(const QUuid& nodeID, bool muteEnabled) { + // cannot personal mute yourself, or nobody + if (!nodeID.isNull() && _sessionUUID != nodeID) { + auto audioMixer = soloNodeOfType(NodeType::AudioMixer); + if (audioMixer) { + if (isIgnoringNode(nodeID)) { + qCDebug(networking) << "You can't personally mute or unmute a node you're already ignoring."; + } + else { + // setup the packet + auto personalMutePacket = NLPacket::create(PacketType::NodeIgnoreRequest, NUM_BYTES_RFC4122_UUID + sizeof(bool), true); + + // write the node ID to the packet + personalMutePacket->write(nodeID.toRfc4122()); + personalMutePacket->writePrimitive(muteEnabled); + + qCDebug(networking) << "Sending Personal Mute Packet to" << (muteEnabled ? "mute" : "unmute") << "node" << uuidStringWithoutCurlyBraces(nodeID); + + sendPacket(std::move(personalMutePacket), *audioMixer); + + QReadLocker personalMutedSetLocker{ &_personalMutedSetLock }; // write lock for insert and unsafe_erase + + if (muteEnabled) { + // add this nodeID to our set of personal muted IDs + _personalMutedNodeIDs.insert(nodeID); + } else { + _personalMutedNodeIDs.unsafe_erase(nodeID); + } + } + } else { + qWarning() << "Couldn't find audio mixer to send node personal mute request"; + } + } else { + qWarning() << "NodeList::personalMuteNodeBySessionID called with an invalid ID or an ID which matches the current session ID."; + } +} + +bool NodeList::isPersonalMutingNode(const QUuid& nodeID) const { + QReadLocker personalMutedSetLocker{ &_personalMutedSetLock }; + return _personalMutedNodeIDs.find(nodeID) != _personalMutedNodeIDs.cend(); +} + void NodeList::maybeSendIgnoreSetToNode(SharedNodePointer newNode) { - if (newNode->getType() == NodeType::AudioMixer || newNode->getType() == NodeType::AvatarMixer) { + if (newNode->getType() == NodeType::AudioMixer) { // this is a mixer that we just added - it's unlikely it knows who we were previously ignoring in this session, // so send that list along now (assuming it isn't empty) - QReadLocker setLocker { &_ignoredSetLock }; + QReadLocker personalMutedSetLocker{ &_personalMutedSetLock }; + + if (_personalMutedNodeIDs.size() > 0) { + // setup a packet list so we can send the stream of ignore IDs + auto personalMutePacketList = NLPacketList::create(PacketType::NodeIgnoreRequest, QByteArray(), true); + + // enumerate the ignored IDs and write them to the packet list + auto it = _personalMutedNodeIDs.cbegin(); + while (it != _personalMutedNodeIDs.end()) { + personalMutePacketList->write(it->toRfc4122()); + ++it; + } + + // send this NLPacketList to the new node + sendPacketList(std::move(personalMutePacketList), *newNode); + } + + // also send them the current ignore radius state. + sendIgnoreRadiusStateToNode(newNode); + } + if (newNode->getType() == NodeType::AvatarMixer) { + // this is a mixer that we just added - it's unlikely it knows who we were previously ignoring in this session, + // so send that list along now (assuming it isn't empty) + + QReadLocker ignoredSetLocker{ &_ignoredSetLock }; if (_ignoredNodeIDs.size() > 0) { // setup a packet list so we can send the stream of ignore IDs @@ -850,64 +919,6 @@ void NodeList::maybeSendIgnoreSetToNode(SharedNodePointer newNode) { } } -void NodeList::personalMuteNodeBySessionID(const QUuid& nodeID, bool muteEnabled) { - // cannot personal mute yourself, or nobody - if (!nodeID.isNull() && _sessionUUID != nodeID) { - auto audioMixer = soloNodeOfType(NodeType::AudioMixer); - if (audioMixer) { - // setup the packet - auto personalMutePacket = NLPacket::create(PacketType::NodePersonalMuteRequest, NUM_BYTES_RFC4122_UUID + sizeof(bool), true); - - // write the node ID to the packet - personalMutePacket->write(nodeID.toRfc4122()); - personalMutePacket->writePrimitive(muteEnabled); - - qCDebug(networking) << "Sending Personal Mute Packet to" << (muteEnabled ? "mute" : "unmute") << "node" << uuidStringWithoutCurlyBraces(nodeID); - - sendPacket(std::move(personalMutePacket), *audioMixer); - } else { - qWarning() << "Couldn't find audio mixer to send node personal mute request"; - } - } else { - qWarning() << "NodeList::personalMuteNodeBySessionID called with an invalid ID or an ID which matches the current session ID."; - } -} - -void NodeList::requestPersonalMuteStatus(const QUuid& nodeID) { - // cannot personal mute yourself, or nobody; don't bother checking the status - if (!nodeID.isNull() && _sessionUUID != nodeID) { - auto audioMixer = soloNodeOfType(NodeType::AudioMixer); - if (audioMixer) { - // send a request to the audio mixer to get the personal mute status associated with the given session ID - // setup the packet - auto personalMuteStatusPacket = NLPacket::create(PacketType::NodePersonalMuteStatusRequest, NUM_BYTES_RFC4122_UUID, true); - - // write the node ID to the packet - personalMuteStatusPacket->write(nodeID.toRfc4122()); - - qCDebug(networking) << "Sending Personal Mute Status Request Packet for node" << uuidStringWithoutCurlyBraces(nodeID); - - sendPacket(std::move(personalMuteStatusPacket), *audioMixer); - } else { - qWarning() << "Couldn't find audio mixer to send node personal mute status request"; - } - } else { - qWarning() << "NodeList::requestPersonalMuteStatus called with an invalid ID or an ID which matches the current session ID."; - } -} - -void NodeList::processPersonalMuteStatusReply(QSharedPointer message) { - // read the UUID from the packet - QString nodeUUIDString = (QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID))).toString(); - // read the personal mute status - bool isPersonalMuted; - message->readPrimitive(&isPersonalMuted); - - qCDebug(networking) << "Got personal muted status" << isPersonalMuted << "for node" << nodeUUIDString; - - emit personalMuteStatusReply(nodeUUIDString, isPersonalMuted); -} - void NodeList::kickNodeBySessionID(const QUuid& nodeID) { // send a request to domain-server to kick the node with the given session ID // the domain-server will handle the persistence of the kick (via username or IP) diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 1e0a7fa8d1..ba19f56f9f 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -79,7 +79,7 @@ public: void ignoreNodeBySessionID(const QUuid& nodeID, bool ignoreEnabled); bool isIgnoringNode(const QUuid& nodeID) const; void personalMuteNodeBySessionID(const QUuid& nodeID, bool muteEnabled); - void requestPersonalMuteStatus(const QUuid& nodeID); + bool isPersonalMutingNode(const QUuid& nodeID) const; void kickNodeBySessionID(const QUuid& nodeID); void muteNodeBySessionID(const QUuid& nodeID); @@ -105,7 +105,6 @@ public slots: void processICEPingPacket(QSharedPointer message); void processUsernameFromIDReply(QSharedPointer message); - void processPersonalMuteStatusReply(QSharedPointer message); #if (PR_BUILD || DEV_BUILD) void toggleSendNewerDSConnectVersion(bool shouldSendNewerVersion) { _shouldSendNewerVersion = shouldSendNewerVersion; } @@ -118,7 +117,6 @@ signals: void unignoredNode(const QUuid& nodeID); void ignoreRadiusEnabledChanged(bool isIgnored); void usernameFromIDReply(const QString& nodeID, const QString& username, const QString& machineFingerprint); - void personalMuteStatusReply(const QString& nodeID, bool isPersonalMuted); private slots: void stopKeepalivePingTimer(); @@ -164,6 +162,8 @@ private: mutable QReadWriteLock _ignoredSetLock; tbb::concurrent_unordered_set _ignoredNodeIDs; + mutable QReadWriteLock _personalMutedSetLock; + tbb::concurrent_unordered_set _personalMutedNodeIDs; void sendIgnoreRadiusStateToNode(const SharedNodePointer& destinationNode); Setting::Handle _ignoreRadiusEnabled { "IgnoreRadiusEnabled", true }; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 78ae1e7ff0..1867d2193c 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -105,10 +105,7 @@ public: UsernameFromIDReply, ViewFrustum, RequestsDomainListData, - NodePersonalMuteRequest, - NodePersonalMuteStatusRequest, - NodePersonalMuteStatusReply, - LAST_PACKET_TYPE = NodePersonalMuteStatusReply + LAST_PACKET_TYPE = RequestsDomainListData }; }; diff --git a/libraries/script-engine/src/UsersScriptingInterface.cpp b/libraries/script-engine/src/UsersScriptingInterface.cpp index f18eef27cb..58680b944d 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.cpp +++ b/libraries/script-engine/src/UsersScriptingInterface.cpp @@ -21,7 +21,6 @@ UsersScriptingInterface::UsersScriptingInterface() { connect(nodeList.data(), &NodeList::usernameFromIDReply, this, &UsersScriptingInterface::usernameFromIDReply); connect(nodeList.data(), &NodeList::ignoredNode, this, &UsersScriptingInterface::ignoredNode); connect(nodeList.data(), &NodeList::unignoredNode, this, &UsersScriptingInterface::unignoredNode); - connect(nodeList.data(), &NodeList::personalMuteStatusReply, this, &UsersScriptingInterface::personalMuteStatusReply); } void UsersScriptingInterface::ignore(const QUuid& nodeID, bool ignoreEnabled) { @@ -40,9 +39,9 @@ void UsersScriptingInterface::personalMute(const QUuid& nodeID, bool muteEnabled DependencyManager::get()->personalMuteNodeBySessionID(nodeID, muteEnabled); } -void UsersScriptingInterface::requestPersonalMuteStatus(const QUuid& nodeID) { - // ask the Audio Mixer via the NodeList for the Personal Mute status associated with the given session ID - DependencyManager::get()->requestPersonalMuteStatus(nodeID); +bool UsersScriptingInterface::getPersonalMuteStatus(const QUuid& nodeID) { + // ask the NodeList for the Personal Mute status associated with the given session ID + return DependencyManager::get()->isPersonalMutingNode(nodeID); } void UsersScriptingInterface::kick(const QUuid& nodeID) { diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index f7b25a72c2..223ddb879b 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -59,7 +59,7 @@ public slots: * @function Users.requestPersonalMuteStatus * @param {nodeID} nodeID The node or session ID of the user whose personal mute status you want. */ - void requestPersonalMuteStatus(const QUuid& nodeID); + bool getPersonalMuteStatus(const QUuid& nodeID); /**jsdoc * Kick another user. @@ -132,12 +132,6 @@ signals: */ void usernameFromIDReply(const QString& nodeID, const QString& username, const QString& machineFingerprint); - /**jsdoc - * Notifies scripts of the Personal Mute status associated with a UUID. - * @function Users.usernameFromIDReply - */ - void personalMuteStatusReply(const QString& nodeID, bool isPersonalMuted); - private: bool getRequestsDomainListData(); void setRequestsDomainListData(bool requests); diff --git a/scripts/system/pal.js b/scripts/system/pal.js index a21eb8c6ef..d2312e9ed4 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -136,7 +136,7 @@ function populateUserList() { // and ignore status from AudioMixer/AvatarMixer // (as long as we're not requesting it for our own ID) if (id) { - Users.requestPersonalMuteStatus(id); + avatarPalDatum['personalMute'] = Users.getPersonalMuteStatus(id); avatarPalDatum['ignore'] = Users.getIgnoreStatus(id); } data.push(avatarPalDatum); @@ -165,14 +165,6 @@ function usernameFromIDReply(id, username, machineFingerprint) { pal.sendToQml({ method: 'updateUsername', params: data }); } -// The function that handles the personal muted status from the AudioMixer -function personalMuteStatusReply(id, isPersonalMuted) { - var data = [id, isPersonalMuted]; - print('Personal Muted Status Data:', JSON.stringify(data)); - // Ship the data off to QML - pal.sendToQml({ method: 'updatePersonalMutedStatus', params: data }); -} - var pingPong = true; function updateOverlays() { var eye = Camera.position; @@ -343,7 +335,6 @@ button.clicked.connect(onClicked); pal.visibleChanged.connect(onVisibleChanged); pal.closed.connect(off); Users.usernameFromIDReply.connect(usernameFromIDReply); -Users.personalMuteStatusReply.connect(personalMuteStatusReply); function onIgnore(sessionId) { // make it go away in the usual way, since we'll still get data keeping it live // Why doesn't this work from .qml? (crashes) @@ -361,7 +352,6 @@ Script.scriptEnding.connect(function () { pal.closed.disconnect(off); Users.usernameFromIDReply.disconnect(usernameFromIDReply); Users.ignoredNode.disconnect(onIgnore); - Users.personalMuteStatusReply.disconnect(personalMuteStatusReply); off(); });