overte-JulianGro/interface/resources/qml/hifi/audio/Audio.qml
2021-03-16 21:22:19 +13:00

929 lines
35 KiB
QML

//
// Audio.qml
// qml/hifi/audio
//
// Audio setup
//
// Created by Vlad Stelmahovsky on 03/22/2017
// Copyright 2017 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.10
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0
import stylesUit 1.0
import controlsUit 1.0 as HifiControlsUit
import "../../windows"
import "./" as AudioControls
Rectangle {
id: root;
HifiConstants { id: hifi; }
property var eventBridge;
// leave as blank, this is user's volume for the avatar mixer
property var myAvatarUuid: ""
property string title: "Audio Settings"
property int switchHeight: 16
property int switchWidth: 40
property bool pushToTalk: (bar.currentIndex === 0) ? AudioScriptingInterface.pushToTalkDesktop : AudioScriptingInterface.pushToTalkHMD;
property bool muted: (bar.currentIndex === 0) ? AudioScriptingInterface.mutedDesktop : AudioScriptingInterface.mutedHMD;
readonly property real verticalScrollWidth: 10
readonly property real verticalScrollShaft: 8
signal sendToScript(var message);
color: hifi.colors.baseGray;
// only show the title if loaded through a "loader"
function showTitle() {
return (root.parent !== null) && root.parent.objectName == "loader";
}
property bool isVR: AudioScriptingInterface.context === "VR"
property real rightMostInputLevelPos: root.width
//placeholder for control sizes and paddings
//recalculates dynamically in case of UI size is changed
QtObject {
id: margins
property real paddings: root.width / 20.25
property real sizeCheckBox: root.width / 13.5
property real sizeText: root.width / 2.5
property real sizeLevel: root.width / 5.8
property real sizeDesktop: root.width / 5.8
property real sizeVR: root.width / 13.5
}
TabBar {
id: bar
spacing: 0
width: parent.width
height: 28;
currentIndex: isVR ? 1 : 0;
AudioControls.AudioTabButton {
height: parent.height
text: qsTr("Desktop")
}
AudioControls.AudioTabButton {
height: parent.height
text: qsTr("VR")
}
}
property bool showPeaks: true;
function enablePeakValues() {
AudioScriptingInterface.devices.input.peakValuesEnabled = true;
AudioScriptingInterface.devices.input.peakValuesEnabledChanged.connect(function(enabled) {
if (!enabled && root.showPeaks) {
AudioScriptingInterface.devices.input.peakValuesEnabled = true;
}
});
}
function updateMyAvatarGainFromQML(sliderValue, isReleased) {
if (AudioScriptingInterface.getAvatarGain() != sliderValue) {
AudioScriptingInterface.setAvatarGain(sliderValue);
}
}
function updateInjectorGainFromQML(sliderValue, isReleased) {
if (AudioScriptingInterface.getInjectorGain() != sliderValue) {
AudioScriptingInterface.setInjectorGain(sliderValue); // server side
AudioScriptingInterface.setLocalInjectorGain(sliderValue); // client side
}
}
function updateSystemInjectorGainFromQML(sliderValue, isReleased) {
if (AudioScriptingInterface.getSystemInjectorGain() != sliderValue) {
AudioScriptingInterface.setSystemInjectorGain(sliderValue);
}
}
function updateNoiseReductionThresholdFromQML(sliderValue) {
if (AudioScriptingInterface.getNoiseReductionThreshold() !== sliderValue) {
AudioScriptingInterface.setNoiseReductionThreshold(sliderValue);
}
}
Component.onCompleted: {
enablePeakValues();
}
Flickable {
id: flickView;
anchors.top: bar.bottom;
anchors.left: parent.left;
anchors.bottom: parent.bottom;
width: parent.width;
contentWidth: parent.width;
contentHeight: contentItem.childrenRect.height;
boundsBehavior: Flickable.DragOverBounds;
flickableDirection: Flickable.VerticalFlick;
property bool isScrolling: (contentHeight - height) > 10 ? true : false;
clip: true;
ScrollBar.vertical: ScrollBar {
policy: flickView.isScrolling ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff;
parent: flickView.parent;
anchors.top: flickView.top;
anchors.right: flickView.right;
anchors.bottom: flickView.bottom;
z: 100 // Display over top of separators.
background: Item {
implicitWidth: verticalScrollWidth;
Rectangle {
color: hifi.colors.baseGrayShadow
radius: 4;
anchors {
fill: parent;
topMargin: 2 // Finess position
}
}
}
contentItem: Item {
implicitWidth: verticalScrollShaft;
Rectangle {
radius: verticalScrollShaft/2;
color: hifi.colors.white30;
anchors {
fill: parent;
topMargin: 1; // Finesse position.
}
}
}
}
Separator {
id: firstSeparator;
anchors.top: parent.top;
}
Item {
id: switchesContainer;
x: 2 * margins.paddings;
width: parent.width;
// switch heights + 2 * top margins
height: (bar.currentIndex === 0) ? (root.switchHeight) * 2 + 48 : (root.switchHeight) * 4 + 48;
anchors.top: firstSeparator.bottom;
anchors.topMargin: 10;
Item {
id: switchContainer;
x: margins.paddings;
width: parent.width / 2;
height: parent.height;
anchors.top: parent.top
anchors.left: parent.left;
HifiControlsUit.Switch {
id: muteMic;
height: root.switchHeight;
switchWidth: root.switchWidth;
labelTextOn: "Mute microphone";
labelTextSize: 16;
backgroundOnColor: "#E3E3E3";
checked: muted;
onClicked: {
if (bar.currentIndex === 0) {
AudioScriptingInterface.mutedDesktop = checked;
}
else {
AudioScriptingInterface.mutedHMD = checked;
}
}
}
HifiControlsUit.Switch {
id: pttSwitch
height: root.switchHeight;
switchWidth: root.switchWidth;
anchors.top: muteMic.bottom;
anchors.topMargin: 24
anchors.left: parent.left
labelTextOn: (bar.currentIndex === 0) ? qsTr("Push To Talk (T)") : qsTr("Push To Talk");
labelTextSize: 16;
backgroundOnColor: "#E3E3E3";
checked: (bar.currentIndex === 0) ? AudioScriptingInterface.pushToTalkDesktop : AudioScriptingInterface.pushToTalkHMD;
onCheckedChanged: {
if (bar.currentIndex === 0) {
AudioScriptingInterface.pushToTalkDesktop = checked;
} else {
AudioScriptingInterface.pushToTalkHMD = checked;
}
}
}
}
Item {
id: additionalSwitchContainer
width: switchContainer.width - margins.paddings;
height: parent.height;
anchors.top: parent.top
anchors.left: switchContainer.right;
HifiControlsUit.Switch {
id: warnMutedSwitch
height: root.switchHeight;
switchWidth: root.switchWidth;
anchors.top: parent.top
anchors.left: parent.left
labelTextOn: qsTr("HMD Mute Warning");
labelTextSize: 16;
backgroundOnColor: "#E3E3E3";
checked: AudioScriptingInterface.warnWhenMuted;
visible: bar.currentIndex !== 0;
onClicked: {
AudioScriptingInterface.warnWhenMuted = checked;
checked = Qt.binding(function() { return AudioScriptingInterface.warnWhenMuted; }); // restore binding
}
}
HifiControlsUit.Switch {
id: audioLevelSwitch
height: root.switchHeight;
switchWidth: root.switchWidth;
anchors.top: warnMutedSwitch.visible ? warnMutedSwitch.bottom : parent.top
anchors.topMargin: bar.currentIndex === 0 ? 0 : 24
anchors.left: parent.left
labelTextOn: qsTr("Audio Level Meter");
labelTextSize: 16;
backgroundOnColor: "#E3E3E3";
checked: AvatarInputs.showAudioTools;
onCheckedChanged: {
AvatarInputs.showAudioTools = checked;
checked = Qt.binding(function() { return AvatarInputs.showAudioTools; }); // restore binding
}
}
HifiControlsUit.Switch {
id: stereoInput;
height: root.switchHeight;
switchWidth: root.switchWidth;
anchors.top: audioLevelSwitch.bottom
anchors.topMargin: 24
anchors.left: parent.left
labelTextOn: qsTr("Stereo input");
labelTextSize: 16;
backgroundOnColor: "#E3E3E3";
checked: AudioScriptingInterface.isStereoInput;
onCheckedChanged: {
AudioScriptingInterface.isStereoInput = checked;
checked = Qt.binding(function() { return AudioScriptingInterface.isStereoInput; }); // restore binding
}
}
}
}
Item {
id: pttTextContainer
anchors.top: switchesContainer.bottom;
anchors.topMargin: 10;
anchors.left: parent.left;
width: rightMostInputLevelPos;
height: pttText.height;
RalewayRegular {
id: pttText;
x: margins.paddings;
color: hifi.colors.white;
width: rightMostInputLevelPos;
height: paintedHeight;
wrapMode: Text.WordWrap;
font.italic: true;
size: 16;
text: (bar.currentIndex === 0) ? qsTr("Press and hold the button \"T\" to talk.") :
qsTr("Press and hold grip triggers on both controllers to talk.");
}
}
Item {
id: avatarGainContainer
x: margins.paddings;
anchors.top: pttTextContainer.bottom;
anchors.topMargin: 10;
width: parent.width - margins.paddings*2
height: avatarGainSliderTextMetrics.height
HifiControlsUit.Slider {
id: avatarGainSlider
anchors.right: parent.right
height: parent.height
width: 200
minimumValue: -60.0
maximumValue: 20.0
stepSize: 5
value: AudioScriptingInterface.getAvatarGain()
onValueChanged: {
updateMyAvatarGainFromQML(value, false);
}
onPressedChanged: {
if (!pressed) {
updateMyAvatarGainFromQML(value, false);
}
}
MouseArea {
anchors.fill: parent
onWheel: {
// Do nothing.
}
onDoubleClicked: {
avatarGainSlider.value = 0.0
}
onPressed: {
// Pass through to Slider
mouse.accepted = false
}
onReleased: {
// the above mouse.accepted seems to make this
// never get called, nonetheless...
mouse.accepted = false
}
}
}
TextMetrics {
id: avatarGainSliderTextMetrics
text: avatarGainSliderText.text
font: avatarGainSliderText.font
}
RalewayRegular {
// The slider for my card is special, it controls the master gain
id: avatarGainSliderText;
text: "People volume";
size: 16;
anchors.left: parent.left;
color: hifi.colors.white;
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignTop;
}
}
Item {
id: injectorGainContainer
x: margins.paddings;
width: parent.width - margins.paddings*2
height: injectorGainSliderTextMetrics.height
anchors.top: avatarGainContainer.bottom;
anchors.topMargin: 10;
HifiControlsUit.Slider {
id: injectorGainSlider
anchors.right: parent.right
height: parent.height
width: 200
minimumValue: -60.0
maximumValue: 20.0
stepSize: 5
value: AudioScriptingInterface.getInjectorGain()
onValueChanged: {
updateInjectorGainFromQML(value, false);
}
onPressedChanged: {
if (!pressed) {
updateInjectorGainFromQML(value, false);
}
}
MouseArea {
anchors.fill: parent
onWheel: {
// Do nothing.
}
onDoubleClicked: {
injectorGainSlider.value = 0.0
}
onPressed: {
// Pass through to Slider
mouse.accepted = false
}
onReleased: {
// the above mouse.accepted seems to make this
// never get called, nonetheless...
mouse.accepted = false
}
}
}
TextMetrics {
id: injectorGainSliderTextMetrics
text: injectorGainSliderText.text
font: injectorGainSliderText.font
}
RalewayRegular {
id: injectorGainSliderText;
text: "Environment volume";
size: 16;
anchors.left: parent.left;
color: hifi.colors.white;
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignTop;
}
}
Item {
id: systemInjectorGainContainer
x: margins.paddings;
width: parent.width - margins.paddings*2
height: systemInjectorGainSliderTextMetrics.height
anchors.top: injectorGainContainer.bottom;
anchors.topMargin: 10;
HifiControlsUit.Slider {
id: systemInjectorGainSlider
anchors.right: parent.right
height: parent.height
width: 200
minimumValue: -60.0
maximumValue: 20.0
stepSize: 5
value: AudioScriptingInterface.getSystemInjectorGain()
onValueChanged: {
updateSystemInjectorGainFromQML(value, false);
}
onPressedChanged: {
if (!pressed) {
updateSystemInjectorGainFromQML(value, false);
}
}
MouseArea {
anchors.fill: parent
onWheel: {
// Do nothing.
}
onDoubleClicked: {
systemInjectorGainSlider.value = 0.0
}
onPressed: {
// Pass through to Slider
mouse.accepted = false
}
onReleased: {
// the above mouse.accepted seems to make this
// never get called, nonetheless...
mouse.accepted = false
}
}
}
TextMetrics {
id: systemInjectorGainSliderTextMetrics
text: systemInjectorGainSliderText.text
font: systemInjectorGainSliderText.font
}
RalewayRegular {
id: systemInjectorGainSliderText;
text: "UI FX volume";
size: 16;
anchors.left: parent.left;
color: hifi.colors.white;
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignTop;
}
}
Separator {
id: secondSeparator;
anchors.top: systemInjectorGainContainer.bottom;
anchors.topMargin: 10;
}
Item {
id: noiseReductionHeader
x: margins.paddings;
width: parent.width - margins.paddings * 2;
height: 36;
anchors.top: secondSeparator.bottom;
anchors.topMargin: 10;
HiFiGlyphs {
width: margins.sizeCheckBox;
text: hifi.glyphs.mic;
color: hifi.colors.white;
anchors.left: parent.left;
anchors.leftMargin: -size / 4; // The glyph has empty space at left about 25%
anchors.verticalCenter: parent.verticalCenter;
size: 30;
}
RalewayRegular {
anchors.verticalCenter: parent.verticalCenter;
width: margins.sizeText + margins.sizeLevel;
anchors.left: parent.left;
anchors.leftMargin: margins.sizeCheckBox;
size: 22;
color: hifi.colors.white;
text: qsTr("Noise Reduction");
}
}
Item {
id: noiseReductionSwitches;
x: 2 * margins.paddings;
width: parent.width;
// switch heights + 2 * top margins
height: (root.switchHeight) * 5 + 48;
anchors.top: noiseReductionHeader.bottom;
anchors.topMargin: 0;
Item {
id: noiseReductionSwitchContainer;
x: margins.paddings;
width: parent.width / 2;
height: parent.height;
anchors.top: parent.top;
anchors.left: parent.left;
HifiControlsUit.Switch {
id: acousticEchoCancellationSwitch;
height: root.switchHeight;
switchWidth: root.switchWidth;
anchors.top: noiseReductionSwitchContainer.top
anchors.topMargin: 24
anchors.left: parent.left
labelTextOn: "Echo Cancellation";
labelTextSize: 16;
backgroundOnColor: "#E3E3E3";
checked: AudioScriptingInterface.acousticEchoCancellation;
onCheckedChanged: {
AudioScriptingInterface.acousticEchoCancellation = checked;
checked = Qt.binding(function () { return AudioScriptingInterface.acousticEchoCancellation; });
}
}
HifiControlsUit.Switch {
id: noiseReductionSwitch;
height: root.switchHeight;
switchWidth: root.switchWidth;
anchors.top: acousticEchoCancellationSwitch.bottom;
anchors.topMargin: 24
anchors.left: parent.left
labelTextOn: "Noise Reduction";
labelTextSize: 16;
backgroundOnColor: "#E3E3E3";
checked: AudioScriptingInterface.noiseReduction;
onCheckedChanged: {
AudioScriptingInterface.noiseReduction = checked;
checked = Qt.binding(function () { return AudioScriptingInterface.noiseReduction; }); // restore binding
}
}
HifiControlsUit.Switch {
id: noiseReductionAutomaticSwitch;
height: root.switchHeight;
switchWidth: root.switchWidth;
anchors.top: noiseReductionSwitch.bottom;
anchors.topMargin: 24;
anchors.left: parent.left;
labelTextOn: "Manual Noise Reduction";
labelTextSize: 16;
backgroundOnColor: "#E3E3E3";
checked: !AudioScriptingInterface.noiseReductionAutomatic;
visible: AudioScriptingInterface.noiseReduction;
onCheckedChanged: {
AudioScriptingInterface.noiseReductionAutomatic = !checked;
checked = Qt.binding(function () { return !AudioScriptingInterface.noiseReductionAutomatic; }); // restore binding
}
}
}
}
Item {
id: noiseReductionThresholdContainer
x: margins.paddings;
anchors.top: noiseReductionSwitches.bottom;
anchors.topMargin: 16;
width: parent.width - margins.paddings * 2;
height: avatarGainSliderTextMetrics.height + 10;
visible: AudioScriptingInterface.noiseReduction && !AudioScriptingInterface.noiseReductionAutomatic;
HifiControlsUit.Slider {
id: noiseReductionThresholdSlider
anchors.right: parent.right
height: noiseReductionThresholdSliderTextMetrics.height
width: 200
minimumValue: 0.0
maximumValue: 1.0
stepSize: 0.05
value: AudioScriptingInterface.getNoiseReductionThreshold()
onValueChanged: {
updateNoiseReductionThresholdFromQML(value);
}
onPressedChanged: {
if (!pressed) {
updateNoiseReductionThresholdFromQML(value);
}
}
MouseArea {
anchors.fill: parent
onWheel: {
// Do nothing.
}
onDoubleClicked: {
noiseReductionThresholdSlider.value = 0.0;
}
onPressed: {
// Pass through to Slider
mouse.accepted = false;
}
onReleased: {
// the above mouse.accepted seems to make this
// never get called, nonetheless...
mouse.accepted = false;
}
}
}
TextMetrics {
id: noiseReductionThresholdSliderTextMetrics
text: noiseReductionThresholdSliderText.text
font: noiseReductionThresholdSliderText.font
}
RalewayRegular {
// The slider for my card is special, it controls the master gain
id: noiseReductionThresholdSliderText;
text: "Audio input threshold";
size: 16;
anchors.left: parent.left;
color: hifi.colors.white;
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignTop;
}
Item {
id: noisePeak
anchors.right: parent.right
anchors.rightMargin: 5;
anchors.top: noiseReductionThresholdSlider.bottom;
width: noiseReductionThresholdSlider.width - 10;
height: 8;
Text {
id: status;
anchors {
horizontalCenter: parent.horizontalCenter;
verticalCenter: parent.verticalCenter;
}
visible: AudioScriptingInterface.muted;
color: "#E2334D";
text: "MUTED";
font.pointSize: 10;
}
Item {
id: noiseBar;
property bool gated: false;
property var level: AudioScriptingInterface.inputLevel;
width: parent.width;
height: parent.height;
anchors { fill: parent }
visible: !status.visible;
function onNoiseGateOpened() {
noiseBar.gated = false;
}
function onNoiseGateClosed() {
noiseBar.gated = true;
}
function onInputLevelChanged(level) {
noiseBar.level = level;
}
Component.onCompleted: {
AudioScriptingInterface.noiseGateOpened.connect(onNoiseGateOpened);
AudioScriptingInterface.noiseGateClosed.connect(onNoiseGateClosed);
AudioScriptingInterface.inputLevelChanged.connect(onInputLevelChanged);
}
Component.onDestruction: {
AudioScriptingInterface.noiseGateOpened.disconnect(onNoiseGateOpened);
AudioScriptingInterface.noiseGateClosed.disconnect(onNoiseGateClosed);
AudioScriptingInterface.inputLevelChanged.disconnect(onInputLevelChanged);
}
Rectangle { // base
radius: 4;
anchors { fill: parent }
color: colors.gutter;
}
Rectangle { // noiseMask
id: noiseMask;
width: parent.width * noiseBar.level;
radius: 5;
anchors {
bottom: parent.bottom;
bottomMargin: 0;
top: parent.top;
topMargin: 0;
left: parent.left;
leftMargin: 0;
}
}
LinearGradient {
anchors { fill: noiseMask }
source: noiseMask
start: Qt.point(0, 0);
end: Qt.point(noiseBar.width, 0);
gradient: Gradient {
GradientStop {
position: 0;
color: noiseBar.gated ? "#E2334D" : "#39A38F";
}
GradientStop {
position: 1;
color: noiseBar.gated ? "#E2334D" : "#39A38F";
}
}
}
}
}
}
Separator {
id: thirdSeparator;
anchors.top: noiseReductionThresholdContainer.bottom;
anchors.topMargin: 14;
}
Item {
id: inputDeviceHeader
x: margins.paddings;
width: parent.width - margins.paddings*2;
height: 36;
anchors.top: thirdSeparator.bottom;
anchors.topMargin: 10;
HiFiGlyphs {
width: margins.sizeCheckBox;
text: hifi.glyphs.mic;
color: hifi.colors.white;
anchors.left: parent.left;
anchors.leftMargin: -size/4; //the glyph has empty space at left about 25%
anchors.verticalCenter: parent.verticalCenter;
size: 30;
}
RalewayRegular {
anchors.verticalCenter: parent.verticalCenter;
width: margins.sizeText + margins.sizeLevel;
anchors.left: parent.left;
anchors.leftMargin: margins.sizeCheckBox;
size: 22;
color: hifi.colors.white;
text: qsTr("Choose input device");
}
}
AudioControls.LoopbackAudio {
id: loopbackAudio
x: margins.paddings
anchors.top: inputDeviceHeader.bottom;
anchors.topMargin: 10;
visible: (bar.currentIndex === 1 && isVR) ||
(bar.currentIndex === 0 && !isVR);
anchors { left: parent.left; leftMargin: margins.paddings }
}
ListView {
id: inputView;
width: rightMostInputLevelPos;
anchors.top: loopbackAudio.visible ? loopbackAudio.bottom : inputDeviceHeader.bottom;
anchors.topMargin: 10;
x: margins.paddings
interactive: false;
height: contentHeight;
clip: true;
model: AudioScriptingInterface.devices.input;
delegate: Item {
width: rightMostInputLevelPos - margins.paddings*2
height: ((type != "hmd" && bar.currentIndex === 0) || (type != "desktop" && bar.currentIndex === 1)) ?
(margins.sizeCheckBox > checkBoxInput.implicitHeight ? margins.sizeCheckBox + 4 : checkBoxInput.implicitHeight + 4) : 0
visible: (type != "hmd" && bar.currentIndex === 0) || (type != "desktop" && bar.currentIndex === 1)
AudioControls.CheckBox {
id: checkBoxInput
anchors.left: parent.left
spacing: margins.sizeCheckBox - boxSize
anchors.verticalCenter: parent.verticalCenter
width: parent.width - inputLevel.width
clip: true
checkable: !checked
checked: bar.currentIndex === 0 ? selectedDesktop : selectedHMD;
boxSize: margins.sizeCheckBox / 2
isRound: true
text: devicename
fontSize: 16;
onPressed: {
if (!checked) {
stereoInput.checked = false;
AudioScriptingInterface.setStereoInput(false); // the next selected audio device might not support stereo
AudioScriptingInterface.setInputDevice(info, bar.currentIndex === 1);
}
}
}
AudioControls.InputPeak {
id: inputLevel
anchors.right: parent.right
peak: model.peak;
anchors.verticalCenter: parent.verticalCenter
visible: ((bar.currentIndex === 1 && isVR) ||
(bar.currentIndex === 0 && !isVR)) &&
AudioScriptingInterface.devices.input.peakValuesAvailable;
}
}
}
Separator {
id: fourthSeparator;
anchors.top: inputView.bottom;
anchors.topMargin: 10;
}
Item {
id: outputDeviceHeader;
anchors.topMargin: 10;
anchors.top: fourthSeparator.bottom;
x: margins.paddings;
width: parent.width - margins.paddings*2
height: 36
HiFiGlyphs {
anchors.left: parent.left
anchors.leftMargin: -size/4 //the glyph has empty space at left about 25%
anchors.verticalCenter: parent.verticalCenter;
width: margins.sizeCheckBox
text: hifi.glyphs.unmuted;
color: hifi.colors.white;
size: 36;
}
RalewayRegular {
width: margins.sizeText + margins.sizeLevel
anchors.left: parent.left
anchors.leftMargin: margins.sizeCheckBox
anchors.verticalCenter: parent.verticalCenter;
size: 22;
color: hifi.colors.white;
text: qsTr("Choose output device");
}
}
AudioControls.PlaySampleSound {
id: playSampleSound
x: margins.paddings
anchors.top: outputDeviceHeader.bottom;
anchors.topMargin: 10;
}
ListView {
id: outputView
width: parent.width - margins.paddings*2
x: margins.paddings;
interactive: false;
height: contentHeight + 10;
anchors.top: playSampleSound.bottom;
anchors.topMargin: 10;
clip: true;
model: AudioScriptingInterface.devices.output;
delegate: Item {
width: rightMostInputLevelPos
height: ((type != "hmd" && bar.currentIndex === 0) || (type != "desktop" && bar.currentIndex === 1)) ?
(margins.sizeCheckBox > checkBoxOutput.implicitHeight ? margins.sizeCheckBox + 4 : checkBoxOutput.implicitHeight + 4) : 0
visible: (type != "hmd" && bar.currentIndex === 0) || (type != "desktop" && bar.currentIndex === 1)
AudioControls.CheckBox {
id: checkBoxOutput
width: parent.width
spacing: margins.sizeCheckBox - boxSize
boxSize: margins.sizeCheckBox / 2
isRound: true
checked: bar.currentIndex === 0 ? selectedDesktop : selectedHMD;
checkable: !checked
text: devicename
fontSize: 16
onPressed: {
if (!checked) {
AudioScriptingInterface.setOutputDevice(info, bar.currentIndex === 1);
}
}
}
}
}
}
}