mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 20:48:56 +02:00
Merge pull request #9352 from zfox23/PerAvatarVolume
PAL: Per-Avatar Volume Slider; visual tweaks
This commit is contained in:
commit
d2c7342a62
11 changed files with 195 additions and 29 deletions
|
@ -28,6 +28,7 @@
|
||||||
#include <StDev.h>
|
#include <StDev.h>
|
||||||
#include <UUID.h>
|
#include <UUID.h>
|
||||||
|
|
||||||
|
#include "AudioHelpers.h"
|
||||||
#include "AudioRingBuffer.h"
|
#include "AudioRingBuffer.h"
|
||||||
#include "AudioMixerClientData.h"
|
#include "AudioMixerClientData.h"
|
||||||
#include "AvatarAudioStream.h"
|
#include "AvatarAudioStream.h"
|
||||||
|
@ -68,7 +69,8 @@ AudioMixer::AudioMixer(ReceivedMessage& message) :
|
||||||
packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
|
packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
|
||||||
packetReceiver.registerListener(PacketType::NodeMuteRequest, this, "handleNodeMuteRequestPacket");
|
packetReceiver.registerListener(PacketType::NodeMuteRequest, this, "handleNodeMuteRequestPacket");
|
||||||
packetReceiver.registerListener(PacketType::RadiusIgnoreRequest, this, "handleRadiusIgnoreRequestPacket");
|
packetReceiver.registerListener(PacketType::RadiusIgnoreRequest, this, "handleRadiusIgnoreRequestPacket");
|
||||||
packetReceiver.registerListener(PacketType::RequestsDomainListData, this, "handleRequestsDomainListDataPacket");
|
packetReceiver.registerListener(PacketType::RequestsDomainListData, this, "handleRequestsDomainListDataPacket");
|
||||||
|
packetReceiver.registerListener(PacketType::PerAvatarGainSet, this, "handlePerAvatarGainSetDataPacket");
|
||||||
|
|
||||||
connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled);
|
connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled);
|
||||||
}
|
}
|
||||||
|
@ -186,7 +188,8 @@ void AudioMixer::handleNodeKilled(SharedNodePointer killedNode) {
|
||||||
nodeList->eachNode([&killedNode](const SharedNodePointer& node) {
|
nodeList->eachNode([&killedNode](const SharedNodePointer& node) {
|
||||||
auto clientData = dynamic_cast<AudioMixerClientData*>(node->getLinkedData());
|
auto clientData = dynamic_cast<AudioMixerClientData*>(node->getLinkedData());
|
||||||
if (clientData) {
|
if (clientData) {
|
||||||
clientData->removeHRTFsForNode(killedNode->getUUID());
|
QUuid killedUUID = killedNode->getUUID();
|
||||||
|
clientData->removeHRTFsForNode(killedUUID);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -240,6 +243,20 @@ void AudioMixer::handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> p
|
||||||
sendingNode->parseIgnoreRequestMessage(packet);
|
sendingNode->parseIgnoreRequestMessage(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioMixer::handlePerAvatarGainSetDataPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode) {
|
||||||
|
auto clientData = dynamic_cast<AudioMixerClientData*>(sendingNode->getLinkedData());
|
||||||
|
if (clientData) {
|
||||||
|
QUuid listeningNodeUUID = sendingNode->getUUID();
|
||||||
|
// parse the UUID from the packet
|
||||||
|
QUuid audioSourceUUID = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
||||||
|
uint8_t packedGain;
|
||||||
|
packet->readPrimitive(&packedGain);
|
||||||
|
float gain = unpackFloatGainFromByte(packedGain);
|
||||||
|
clientData->hrtfForStream(audioSourceUUID, QUuid()).setGainAdjustment(gain);
|
||||||
|
qDebug() << "Setting gain adjustment for hrtf[" << listeningNodeUUID << "][" << audioSourceUUID << "] to " << gain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AudioMixer::handleRadiusIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode) {
|
void AudioMixer::handleRadiusIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode) {
|
||||||
sendingNode->parseIgnoreRadiusRequestMessage(packet);
|
sendingNode->parseIgnoreRadiusRequestMessage(packet);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ private slots:
|
||||||
void handleRadiusIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
void handleRadiusIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
||||||
void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
||||||
void handleNodeMuteRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
void handleNodeMuteRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
||||||
|
void handlePerAvatarGainSetDataPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void removeHRTFsForFinishedInjector(const QUuid& streamID);
|
void removeHRTFsForFinishedInjector(const QUuid& streamID);
|
||||||
|
|
|
@ -10,35 +10,35 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
import "../styles-uit"
|
import "../styles-uit"
|
||||||
|
|
||||||
Row {
|
Item {
|
||||||
id: thisNameCard
|
id: thisNameCard
|
||||||
// Spacing
|
|
||||||
spacing: 10
|
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: parent.top
|
|
||||||
anchors {
|
anchors {
|
||||||
topMargin: (parent.height - contentHeight)/2
|
verticalCenter: parent.verticalCenter
|
||||||
bottomMargin: (parent.height - contentHeight)/2
|
|
||||||
leftMargin: 10
|
leftMargin: 10
|
||||||
rightMargin: 10
|
rightMargin: 10
|
||||||
}
|
}
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
property int contentHeight: 50
|
property string uuid: ""
|
||||||
property string displayName: ""
|
property string displayName: ""
|
||||||
property string userName: ""
|
property string userName: ""
|
||||||
property int displayTextHeight: 18
|
property int displayTextHeight: 18
|
||||||
property int usernameTextHeight: 12
|
property int usernameTextHeight: 12
|
||||||
property real audioLevel: 0.0
|
property real audioLevel: 0.0
|
||||||
|
property bool isMyCard: false
|
||||||
|
property bool selected: false
|
||||||
|
|
||||||
/* User image commented out for now - will probably be re-introduced later.
|
/* User image commented out for now - will probably be re-introduced later.
|
||||||
Column {
|
Column {
|
||||||
id: avatarImage
|
id: avatarImage
|
||||||
// Size
|
// Size
|
||||||
height: contentHeight
|
height: parent.height
|
||||||
width: height
|
width: height
|
||||||
Image {
|
Image {
|
||||||
id: userImage
|
id: userImage
|
||||||
|
@ -49,12 +49,12 @@ Row {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
Column {
|
Item {
|
||||||
id: textContainer
|
id: textContainer
|
||||||
// Size
|
// Size
|
||||||
width: parent.width - /*avatarImage.width - */parent.anchors.leftMargin - parent.anchors.rightMargin - parent.spacing
|
width: parent.width - /*avatarImage.width - parent.spacing - */parent.anchors.leftMargin - parent.anchors.rightMargin
|
||||||
height: contentHeight
|
height: childrenRect.height
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
// DisplayName Text
|
// DisplayName Text
|
||||||
FiraSansSemiBold {
|
FiraSansSemiBold {
|
||||||
id: displayNameText
|
id: displayNameText
|
||||||
|
@ -63,6 +63,8 @@ Row {
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
// Size
|
// Size
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
// Anchors
|
||||||
|
anchors.top: parent.top
|
||||||
// Text Size
|
// Text Size
|
||||||
size: thisNameCard.displayTextHeight
|
size: thisNameCard.displayTextHeight
|
||||||
// Text Positioning
|
// Text Positioning
|
||||||
|
@ -80,6 +82,8 @@ Row {
|
||||||
visible: thisNameCard.displayName
|
visible: thisNameCard.displayName
|
||||||
// Size
|
// Size
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
// Anchors
|
||||||
|
anchors.top: displayNameText.bottom
|
||||||
// Text Size
|
// Text Size
|
||||||
size: thisNameCard.usernameTextHeight
|
size: thisNameCard.usernameTextHeight
|
||||||
// Text Positioning
|
// Text Positioning
|
||||||
|
@ -90,25 +94,56 @@ Row {
|
||||||
|
|
||||||
// Spacer
|
// Spacer
|
||||||
Item {
|
Item {
|
||||||
|
id: spacer
|
||||||
height: 4
|
height: 4
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
// Anchors
|
||||||
|
anchors.top: userNameText.bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
// VU Meter
|
// VU Meter
|
||||||
Rectangle { // CHANGEME to the appropriate type!
|
Rectangle {
|
||||||
id: nameCardVUMeter
|
id: nameCardVUMeter
|
||||||
// Size
|
// Size
|
||||||
width: parent.width
|
width: ((gainSlider.value - gainSlider.minimumValue)/(gainSlider.maximumValue - gainSlider.minimumValue)) * parent.width
|
||||||
height: 8
|
height: 8
|
||||||
|
// Anchors
|
||||||
|
anchors.top: spacer.bottom
|
||||||
// Style
|
// Style
|
||||||
radius: 4
|
radius: 4
|
||||||
|
color: "#c5c5c5"
|
||||||
|
// Rectangle for the zero-gain point on the VU meter
|
||||||
|
Rectangle {
|
||||||
|
id: vuMeterZeroGain
|
||||||
|
visible: gainSlider.visible
|
||||||
|
// Size
|
||||||
|
width: 4
|
||||||
|
height: 18
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.darkGray
|
||||||
|
// Anchors
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: (-gainSlider.minimumValue)/(gainSlider.maximumValue - gainSlider.minimumValue) * gainSlider.width - 4
|
||||||
|
}
|
||||||
|
// Rectangle for the VU meter line
|
||||||
|
Rectangle {
|
||||||
|
id: vuMeterLine
|
||||||
|
width: gainSlider.width
|
||||||
|
visible: gainSlider.visible
|
||||||
|
// Style
|
||||||
|
color: vuMeterBase.color
|
||||||
|
radius: nameCardVUMeter.radius
|
||||||
|
height: nameCardVUMeter.height / 2
|
||||||
|
anchors.verticalCenter: nameCardVUMeter.verticalCenter
|
||||||
|
}
|
||||||
// Rectangle for the VU meter base
|
// Rectangle for the VU meter base
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: vuMeterBase
|
id: vuMeterBase
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
// Style
|
// Style
|
||||||
color: "#c5c5c5"
|
color: parent.color
|
||||||
radius: parent.radius
|
radius: parent.radius
|
||||||
}
|
}
|
||||||
// Rectangle for the VU meter audio level
|
// Rectangle for the VU meter audio level
|
||||||
|
@ -117,7 +152,7 @@ Row {
|
||||||
// Size
|
// Size
|
||||||
width: (thisNameCard.audioLevel) * parent.width
|
width: (thisNameCard.audioLevel) * parent.width
|
||||||
// Style
|
// Style
|
||||||
color: "#c5c5c5"
|
color: parent.color
|
||||||
radius: parent.radius
|
radius: parent.radius
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
|
@ -138,5 +173,66 @@ Row {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Per-Avatar Gain Slider
|
||||||
|
Slider {
|
||||||
|
id: gainSlider
|
||||||
|
// Size
|
||||||
|
width: parent.width
|
||||||
|
height: 14
|
||||||
|
// Anchors
|
||||||
|
anchors.verticalCenter: nameCardVUMeter.verticalCenter
|
||||||
|
// Properties
|
||||||
|
visible: !isMyCard && selected
|
||||||
|
value: pal.gainSliderValueDB[uuid] ? pal.gainSliderValueDB[uuid] : 0.0
|
||||||
|
minimumValue: -60.0
|
||||||
|
maximumValue: 20.0
|
||||||
|
stepSize: 5
|
||||||
|
updateValueWhileDragging: true
|
||||||
|
onValueChanged: updateGainFromQML(uuid, value)
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onWheel: {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
onDoubleClicked: {
|
||||||
|
gainSlider.value = 0.0
|
||||||
|
}
|
||||||
|
onPressed: {
|
||||||
|
// Pass through to Slider
|
||||||
|
mouse.accepted = false
|
||||||
|
}
|
||||||
|
onReleased: {
|
||||||
|
// Pass through to Slider
|
||||||
|
mouse.accepted = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
style: SliderStyle {
|
||||||
|
groove: Rectangle {
|
||||||
|
color: "#c5c5c5"
|
||||||
|
implicitWidth: gainSlider.width
|
||||||
|
implicitHeight: 4
|
||||||
|
radius: 2
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
handle: Rectangle {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: (control.pressed || control.hovered) ? "#00b4ef" : "#8F8F8F"
|
||||||
|
implicitWidth: 10
|
||||||
|
implicitHeight: 16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateGainFromQML(avatarUuid, sliderValue) {
|
||||||
|
if (pal.gainSliderValueDB[avatarUuid] !== sliderValue) {
|
||||||
|
pal.gainSliderValueDB[avatarUuid] = sliderValue;
|
||||||
|
var data = {
|
||||||
|
sessionId: avatarUuid,
|
||||||
|
gain: sliderValue
|
||||||
|
};
|
||||||
|
pal.sendToScript({method: 'updateGain', params: data});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ Rectangle {
|
||||||
// Style
|
// Style
|
||||||
color: "#E3E3E3"
|
color: "#E3E3E3"
|
||||||
// Properties
|
// Properties
|
||||||
property int myCardHeight: 70
|
property int myCardHeight: 90
|
||||||
property int rowHeight: 70
|
property int rowHeight: 70
|
||||||
property int actionButtonWidth: 75
|
property int actionButtonWidth: 75
|
||||||
property int nameCardWidth: palContainer.width - actionButtonWidth*(iAmAdmin ? 4 : 2) - 4 - hifi.dimensions.scrollbarBackgroundWidth
|
property int nameCardWidth: palContainer.width - actionButtonWidth*(iAmAdmin ? 4 : 2) - 4 - hifi.dimensions.scrollbarBackgroundWidth
|
||||||
|
@ -32,6 +32,9 @@ Rectangle {
|
||||||
property var ignored: ({}); // Keep a local list of ignored avatars & their data. Necessary because HashMap is slow to respond after ignoring.
|
property var ignored: ({}); // Keep a local list of ignored avatars & their data. Necessary because HashMap is slow to respond after ignoring.
|
||||||
property var userModelData: [] // This simple list is essentially a mirror of the userModel listModel without all the extra complexities.
|
property var userModelData: [] // This simple list is essentially a mirror of the userModel listModel without all the extra complexities.
|
||||||
property bool iAmAdmin: false
|
property bool iAmAdmin: false
|
||||||
|
// Keep a local list of per-avatar gainSliderValueDBs. Far faster than fetching this data from the server.
|
||||||
|
// NOTE: if another script modifies the per-avatar gain, this value won't be accurate!
|
||||||
|
property var gainSliderValueDB: ({});
|
||||||
|
|
||||||
// This is the container for the PAL
|
// This is the container for the PAL
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@ -51,7 +54,7 @@ Rectangle {
|
||||||
id: myInfo
|
id: myInfo
|
||||||
// Size
|
// Size
|
||||||
width: palContainer.width
|
width: palContainer.width
|
||||||
height: myCardHeight + 20
|
height: myCardHeight
|
||||||
// Style
|
// Style
|
||||||
color: pal.color
|
color: pal.color
|
||||||
// Anchors
|
// Anchors
|
||||||
|
@ -65,6 +68,7 @@ Rectangle {
|
||||||
displayName: myData.displayName
|
displayName: myData.displayName
|
||||||
userName: myData.userName
|
userName: myData.userName
|
||||||
audioLevel: myData.audioLevel
|
audioLevel: myData.audioLevel
|
||||||
|
isMyCard: true
|
||||||
// Size
|
// Size
|
||||||
width: nameCardWidth
|
width: nameCardWidth
|
||||||
height: parent.height
|
height: parent.height
|
||||||
|
@ -206,6 +210,8 @@ Rectangle {
|
||||||
userName: model && model.userName
|
userName: model && model.userName
|
||||||
audioLevel: model && model.audioLevel
|
audioLevel: model && model.audioLevel
|
||||||
visible: !isCheckBox && !isButton
|
visible: !isCheckBox && !isButton
|
||||||
|
uuid: model && model.sessionId
|
||||||
|
selected: styleData.selected
|
||||||
// Size
|
// Size
|
||||||
width: nameCardWidth
|
width: nameCardWidth
|
||||||
height: parent.height
|
height: parent.height
|
||||||
|
@ -492,8 +498,9 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'clearIgnored':
|
case 'clearLocalQMLData':
|
||||||
ignored = {};
|
ignored = {};
|
||||||
|
gainSliderValueDB = {};
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.log('Unrecognized message:', JSON.stringify(message));
|
console.log('Unrecognized message:', JSON.stringify(message));
|
||||||
|
|
|
@ -45,7 +45,7 @@ public:
|
||||||
void renderSilent(int16_t* input, float* output, int index, float azimuth, float distance, float gain, int numFrames);
|
void renderSilent(int16_t* input, float* output, int index, float azimuth, float distance, float gain, int numFrames);
|
||||||
|
|
||||||
//
|
//
|
||||||
// HRTF local gain adjustment
|
// HRTF local gain adjustment in amplitude (1.0 == unity)
|
||||||
//
|
//
|
||||||
void setGainAdjustment(float gain) { _gainAdjust = HRTF_GAIN * gain; };
|
void setGainAdjustment(float gain) { _gainAdjust = HRTF_GAIN * gain; };
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "AccountManager.h"
|
#include "AccountManager.h"
|
||||||
#include "AddressManager.h"
|
#include "AddressManager.h"
|
||||||
#include "Assignment.h"
|
#include "Assignment.h"
|
||||||
|
#include "AudioHelpers.h"
|
||||||
#include "HifiSockAddr.h"
|
#include "HifiSockAddr.h"
|
||||||
#include "FingerprintUtils.h"
|
#include "FingerprintUtils.h"
|
||||||
|
|
||||||
|
@ -951,6 +952,30 @@ void NodeList::maybeSendIgnoreSetToNode(SharedNodePointer newNode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeList::setAvatarGain(const QUuid& nodeID, float gain) {
|
||||||
|
// cannot set gain of yourself or nobody
|
||||||
|
if (!nodeID.isNull() && _sessionUUID != nodeID) {
|
||||||
|
auto audioMixer = soloNodeOfType(NodeType::AudioMixer);
|
||||||
|
if (audioMixer) {
|
||||||
|
// setup the packet
|
||||||
|
auto setAvatarGainPacket = NLPacket::create(PacketType::PerAvatarGainSet, NUM_BYTES_RFC4122_UUID + sizeof(float), true);
|
||||||
|
|
||||||
|
// write the node ID to the packet
|
||||||
|
setAvatarGainPacket->write(nodeID.toRfc4122());
|
||||||
|
// We need to convert the gain in dB (from the script) to an amplitude before packing it.
|
||||||
|
setAvatarGainPacket->writePrimitive(packFloatGainToByte(fastExp2f(gain / 6.0206f)));
|
||||||
|
|
||||||
|
qCDebug(networking) << "Sending Set Avatar Gain packet UUID: " << uuidStringWithoutCurlyBraces(nodeID) << "Gain:" << gain;
|
||||||
|
|
||||||
|
sendPacket(std::move(setAvatarGainPacket), *audioMixer);
|
||||||
|
} else {
|
||||||
|
qWarning() << "Couldn't find audio mixer to send set gain request";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qWarning() << "NodeList::setAvatarGain called with an invalid ID or an ID which matches the current session ID:" << nodeID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NodeList::kickNodeBySessionID(const QUuid& nodeID) {
|
void NodeList::kickNodeBySessionID(const QUuid& nodeID) {
|
||||||
// send a request to domain-server to kick the node with the given session ID
|
// 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)
|
// the domain-server will handle the persistence of the kick (via username or IP)
|
||||||
|
|
|
@ -82,6 +82,7 @@ public:
|
||||||
bool isIgnoringNode(const QUuid& nodeID) const;
|
bool isIgnoringNode(const QUuid& nodeID) const;
|
||||||
void personalMuteNodeBySessionID(const QUuid& nodeID, bool muteEnabled);
|
void personalMuteNodeBySessionID(const QUuid& nodeID, bool muteEnabled);
|
||||||
bool isPersonalMutingNode(const QUuid& nodeID) const;
|
bool isPersonalMutingNode(const QUuid& nodeID) const;
|
||||||
|
void setAvatarGain(const QUuid& nodeID, float gain);
|
||||||
|
|
||||||
void kickNodeBySessionID(const QUuid& nodeID);
|
void kickNodeBySessionID(const QUuid& nodeID);
|
||||||
void muteNodeBySessionID(const QUuid& nodeID);
|
void muteNodeBySessionID(const QUuid& nodeID);
|
||||||
|
|
|
@ -106,7 +106,8 @@ public:
|
||||||
ViewFrustum,
|
ViewFrustum,
|
||||||
RequestsDomainListData,
|
RequestsDomainListData,
|
||||||
ExitingSpaceBubble,
|
ExitingSpaceBubble,
|
||||||
LAST_PACKET_TYPE = ExitingSpaceBubble
|
PerAvatarGainSet,
|
||||||
|
LAST_PACKET_TYPE = PerAvatarGainSet
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,11 @@ bool UsersScriptingInterface::getPersonalMuteStatus(const QUuid& nodeID) {
|
||||||
return DependencyManager::get<NodeList>()->isPersonalMutingNode(nodeID);
|
return DependencyManager::get<NodeList>()->isPersonalMutingNode(nodeID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UsersScriptingInterface::setAvatarGain(const QUuid& nodeID, float gain) {
|
||||||
|
// ask the NodeList to set the gain of the specified avatar
|
||||||
|
DependencyManager::get<NodeList>()->setAvatarGain(nodeID, gain);
|
||||||
|
}
|
||||||
|
|
||||||
void UsersScriptingInterface::kick(const QUuid& nodeID) {
|
void UsersScriptingInterface::kick(const QUuid& nodeID) {
|
||||||
// ask the NodeList to kick the user with the given session ID
|
// ask the NodeList to kick the user with the given session ID
|
||||||
DependencyManager::get<NodeList>()->kickNodeBySessionID(nodeID);
|
DependencyManager::get<NodeList>()->kickNodeBySessionID(nodeID);
|
||||||
|
|
|
@ -61,6 +61,15 @@ public slots:
|
||||||
*/
|
*/
|
||||||
bool getPersonalMuteStatus(const QUuid& nodeID);
|
bool getPersonalMuteStatus(const QUuid& nodeID);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Sets an avatar's gain for you and you only.
|
||||||
|
* Units are Decibels (dB)
|
||||||
|
* @function Users.setAvatarGain
|
||||||
|
* @param {nodeID} nodeID The node or session ID of the user whose gain you want to modify.
|
||||||
|
* @param {float} gain The gain of the avatar you'd like to set. Units are dB.
|
||||||
|
*/
|
||||||
|
void setAvatarGain(const QUuid& nodeID, float gain);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Kick another user.
|
* Kick another user.
|
||||||
* @function Users.kick
|
* @function Users.kick
|
||||||
|
|
|
@ -233,6 +233,10 @@ pal.fromQml.connect(function (message) { // messages are {method, params}, like
|
||||||
removeOverlays();
|
removeOverlays();
|
||||||
populateUserList();
|
populateUserList();
|
||||||
break;
|
break;
|
||||||
|
case 'updateGain':
|
||||||
|
data = message.params;
|
||||||
|
Users.setAvatarGain(data['sessionId'], data['gain']);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
print('Unrecognized message from Pal.qml:', JSON.stringify(message));
|
print('Unrecognized message from Pal.qml:', JSON.stringify(message));
|
||||||
}
|
}
|
||||||
|
@ -582,14 +586,14 @@ button.clicked.connect(onClicked);
|
||||||
pal.visibleChanged.connect(onVisibleChanged);
|
pal.visibleChanged.connect(onVisibleChanged);
|
||||||
pal.closed.connect(off);
|
pal.closed.connect(off);
|
||||||
Users.usernameFromIDReply.connect(usernameFromIDReply);
|
Users.usernameFromIDReply.connect(usernameFromIDReply);
|
||||||
function clearIgnoredInQMLAndClosePAL() {
|
function clearLocalQMLDataAndClosePAL() {
|
||||||
pal.sendToQml({ method: 'clearIgnored' });
|
pal.sendToQml({ method: 'clearLocalQMLData' });
|
||||||
if (pal.visible) {
|
if (pal.visible) {
|
||||||
onClicked(); // Close the PAL
|
onClicked(); // Close the PAL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Window.domainChanged.connect(clearIgnoredInQMLAndClosePAL);
|
Window.domainChanged.connect(clearLocalQMLDataAndClosePAL);
|
||||||
Window.domainConnectionRefused.connect(clearIgnoredInQMLAndClosePAL);
|
Window.domainConnectionRefused.connect(clearLocalQMLDataAndClosePAL);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Cleanup.
|
// Cleanup.
|
||||||
|
@ -600,8 +604,8 @@ Script.scriptEnding.connect(function () {
|
||||||
pal.visibleChanged.disconnect(onVisibleChanged);
|
pal.visibleChanged.disconnect(onVisibleChanged);
|
||||||
pal.closed.disconnect(off);
|
pal.closed.disconnect(off);
|
||||||
Users.usernameFromIDReply.disconnect(usernameFromIDReply);
|
Users.usernameFromIDReply.disconnect(usernameFromIDReply);
|
||||||
Window.domainChanged.disconnect(clearIgnoredInQMLAndClosePAL);
|
Window.domainChanged.disconnect(clearLocalQMLDataAndClosePAL);
|
||||||
Window.domainConnectionRefused.disconnect(clearIgnoredInQMLAndClosePAL);
|
Window.domainConnectionRefused.disconnect(clearLocalQMLDataAndClosePAL);
|
||||||
Messages.unsubscribe(CHANNEL);
|
Messages.unsubscribe(CHANNEL);
|
||||||
Messages.messageReceived.disconnect(receiveMessage);
|
Messages.messageReceived.disconnect(receiveMessage);
|
||||||
off();
|
off();
|
||||||
|
|
Loading…
Reference in a new issue