From 9b5f19399c6512d92ee1e79fdb1913e482e02253 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Tue, 25 Apr 2017 00:45:06 +0100 Subject: [PATCH 01/27] create tablet-raiseHand.js --- .../icons/tablet-icons/raise-hand-a.svg | 70 ++++++++++++ .../icons/tablet-icons/raise-hand-i.svg | 60 +++++++++++ .../tablet-raiseHand/tablet-raiseHand.js | 102 ++++++++++++++++++ 3 files changed, 232 insertions(+) create mode 100644 interface/resources/icons/tablet-icons/raise-hand-a.svg create mode 100644 interface/resources/icons/tablet-icons/raise-hand-i.svg create mode 100644 unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js diff --git a/interface/resources/icons/tablet-icons/raise-hand-a.svg b/interface/resources/icons/tablet-icons/raise-hand-a.svg new file mode 100644 index 0000000000..fd35073332 --- /dev/null +++ b/interface/resources/icons/tablet-icons/raise-hand-a.svg @@ -0,0 +1,70 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/interface/resources/icons/tablet-icons/raise-hand-i.svg b/interface/resources/icons/tablet-icons/raise-hand-i.svg new file mode 100644 index 0000000000..50a6aa2606 --- /dev/null +++ b/interface/resources/icons/tablet-icons/raise-hand-i.svg @@ -0,0 +1,60 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js b/unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js new file mode 100644 index 0000000000..f7702053a4 --- /dev/null +++ b/unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js @@ -0,0 +1,102 @@ +"use strict"; +// +// tablet-raiseHand.js +// +// client script that creates a tablet button to raise hand +// +// Created by Triplelexx on 17/04/22 +// Copyright 2017 High Fidelity, Inc. +// +// Hand icons adapted from https://linearicons.com, created by Perxis https://perxis.com CC BY-SA 4.0 license. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { // BEGIN LOCAL_SCOPE + var BUTTON_NAME = "RAISE\nHAND"; + var USERCONNECTION_MESSAGE_CHANNEL = "io.highfidelity.makeUserConnection"; + var DEBUG_PREFIX = "TABLET RAISE HAND: "; + var isRaiseHandButtonActive = false; + var animHandlerId; + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + text: BUTTON_NAME, + icon: "icons/tablet-icons/raise-hand-i.svg", + activeIcon: "icons/tablet-icons/raise-hand-a.svg" + }); + + function onClicked() { + isRaiseHandButtonActive = !isRaiseHandButtonActive; + button.editProperties({ isActive: isRaiseHandButtonActive }); + if (isRaiseHandButtonActive) { + removeAnimation(); + animHandlerId = MyAvatar.addAnimationStateHandler(raiseHandAnimation, []); + Messages.subscribe(USERCONNECTION_MESSAGE_CHANNEL); + Messages.messageReceived.connect(messageHandler); + } else { + removeAnimation(); + Messages.unsubscribe(USERCONNECTION_MESSAGE_CHANNEL); + Messages.messageReceived.disconnect(messageHandler); + } + } + + function removeAnimation() { + if (animHandlerId) { + animHandlerId = MyAvatar.removeAnimationStateHandler(animHandlerId); + } + } + + function raiseHandAnimation(animationProperties) { + // all we are doing here is moving the right hand to a spot that is above the hips. + var headIndex = MyAvatar.getJointIndex("Head"); + var offset = 0.0; + var result = {}; + if (headIndex) { + offset = 0.85 * MyAvatar.getAbsoluteJointTranslationInObjectFrame(headIndex).y; + } + var handPos = Vec3.multiply(offset, { x: -0.7, y: 1.25, z: 0.25 }); + result.rightHandPosition = handPos; + result.rightHandRotation = Quat.fromPitchYawRollDegrees(0, 0, 0); + return result; + } + + function messageHandler(channel, messageString, senderID) { + if (channel !== USERCONNECTION_MESSAGE_CHANNEL && senderID !== MyAvatar.sessionUUID) { + return; + } + var message = {}; + try { + message = JSON.parse(messageString); + } catch (e) { + print(DEBUG_PREFIX + "messageHandler error: " + e); + } + switch (message.key) { + case "waiting": + case "connecting": + case "connectionAck": + case "connectionRequest": + case "done": + removeAnimation(); + if (isRaiseHandButtonActive) { + isRaiseHandButtonActive = false; + button.editProperties({ isActive: isRaiseHandButtonActive }); + } + break; + default: + print(DEBUG_PREFIX + "messageHandler unknown message: " + message); + break; + } + } + + button.clicked.connect(onClicked); + + Script.scriptEnding.connect(function() { + Messages.unsubscribe(USERCONNECTION_MESSAGE_CHANNEL); + Messages.messageReceived.disconnect(messageHandler); + button.clicked.disconnect(onClicked); + tablet.removeButton(button); + removeAnimation(); + }); +}()); // END LOCAL_SCOPE From d18ac6dd498991b0fd16cfa7a6e0664ec705030c Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Fri, 28 Apr 2017 23:02:28 +0200 Subject: [PATCH 02/27] Reimplemented Tablet Audio screen using C++ model --- interface/resources/qml/hifi/Audio.qml | 83 ++++++------- .../qml/hifi/components/AudioCheckbox.qml | 2 + .../AudioDeviceScriptingInterface.cpp | 115 +++++++++++++++++- .../scripting/AudioDeviceScriptingInterface.h | 33 ++++- libraries/audio-client/src/AudioClient.cpp | 5 +- libraries/audio-client/src/AudioClient.h | 3 + scripts/system/selectAudioDevice.js | 15 ++- 7 files changed, 208 insertions(+), 48 deletions(-) diff --git a/interface/resources/qml/hifi/Audio.qml b/interface/resources/qml/hifi/Audio.qml index d0c3122100..adb0cd4cba 100644 --- a/interface/resources/qml/hifi/Audio.qml +++ b/interface/resources/qml/hifi/Audio.qml @@ -35,11 +35,6 @@ Rectangle { property string title: "Audio Options" signal sendToScript(var message); - //set models after Components is shown - Component.onCompleted: { - refreshTimer.start() - refreshTimerOutput.start() - } Component { id: separator @@ -138,30 +133,34 @@ Rectangle { } ListView { - Timer { - id: refreshTimer - interval: 1 - repeat: false - onTriggered: { - //refresh model - inputAudioListView.model = undefined - inputAudioListView.model = AudioDevice.inputAudioDevices - } - } id: inputAudioListView anchors { left: parent.left; right: parent.right; leftMargin: 70 } height: 125 - spacing: 16 + spacing: 0 clip: true snapMode: ListView.SnapToItem - delegate: AudioCheckbox { + model: AudioDevice + delegate: Item { width: parent.width - checkbox.checked: (modelData === AudioDevice.getInputDevice()) - text.text: modelData - onCheckBoxClicked: { - if (checked) { - AudioDevice.setInputDevice(modelData) - refreshTimer.start() + visible: devicemode === 0 + height: visible ? 36 : 0 + + AudioCheckbox { + id: cbin + anchors.verticalCenter: parent.verticalCenter + Binding { + target: cbin.checkbox + property: 'checked' + value: devicechecked + } + + width: parent.width + cbchecked: devicechecked + text.text: devicename + onCheckBoxClicked: { + if (checked) { + AudioDevice.setInputDeviceAsync(devicename) + } } } } @@ -191,31 +190,33 @@ Rectangle { text: qsTr("CHOOSE OUTPUT DEVICE") } } + ListView { id: outputAudioListView - Timer { - id: refreshTimerOutput - interval: 1 - repeat: false - onTriggered: { - //refresh model - outputAudioListView.model = undefined - outputAudioListView.model = AudioDevice.outputAudioDevices - } - } anchors { left: parent.left; right: parent.right; leftMargin: 70 } height: 250 - spacing: 16 + spacing: 0 clip: true snapMode: ListView.SnapToItem - delegate: AudioCheckbox { + model: AudioDevice + delegate: Item { width: parent.width - checkbox.checked: (modelData === AudioDevice.getOutputDevice()) - text.text: modelData - onCheckBoxClicked: { - if (checked) { - AudioDevice.setOutputDevice(modelData) - refreshTimerOutput.start() + visible: devicemode === 1 + height: visible ? 36 : 0 + AudioCheckbox { + id: cbout + width: parent.width + anchors.verticalCenter: parent.verticalCenter + Binding { + target: cbout.checkbox + property: 'checked' + value: devicechecked + } + text.text: devicename + onCheckBoxClicked: { + if (checked) { + AudioDevice.setOutputDeviceAsync(devicename) + } } } } diff --git a/interface/resources/qml/hifi/components/AudioCheckbox.qml b/interface/resources/qml/hifi/components/AudioCheckbox.qml index a8e0441e0a..b23c9b42fe 100644 --- a/interface/resources/qml/hifi/components/AudioCheckbox.qml +++ b/interface/resources/qml/hifi/components/AudioCheckbox.qml @@ -8,6 +8,7 @@ Row { id: row spacing: 16 property alias checkbox: cb + property alias cbchecked: cb.checked property alias text: txt signal checkBoxClicked(bool checked) @@ -17,6 +18,7 @@ Row { colorScheme: hifi.colorSchemes.dark anchors.verticalCenter: parent.verticalCenter onClicked: checkBoxClicked(cb.checked) + onCheckedChanged: console.log("checked", checked, "device ",txt.text) } RalewayBold { id: txt diff --git a/interface/src/scripting/AudioDeviceScriptingInterface.cpp b/interface/src/scripting/AudioDeviceScriptingInterface.cpp index cbb08c0af0..4cec75074f 100644 --- a/interface/src/scripting/AudioDeviceScriptingInterface.cpp +++ b/interface/src/scripting/AudioDeviceScriptingInterface.cpp @@ -33,11 +33,17 @@ bool AudioDeviceScriptingInterface::muted() return getMuted(); } -AudioDeviceScriptingInterface::AudioDeviceScriptingInterface() { +AudioDeviceScriptingInterface::AudioDeviceScriptingInterface(): QAbstractListModel(nullptr) { connect(DependencyManager::get().data(), &AudioClient::muteToggled, this, &AudioDeviceScriptingInterface::muteToggled); connect(DependencyManager::get().data(), &AudioClient::deviceChanged, - this, &AudioDeviceScriptingInterface::deviceChanged); + this, &AudioDeviceScriptingInterface::onDeviceChanged, Qt::QueuedConnection); + connect(DependencyManager::get().data(), &AudioClient::currentInputDeviceChanged, + this, &AudioDeviceScriptingInterface::onCurrentInputDeviceChanged, Qt::QueuedConnection); + connect(DependencyManager::get().data(), &AudioClient::currentOutputDeviceChanged, + this, &AudioDeviceScriptingInterface::onCurrentOutputDeviceChanged, Qt::QueuedConnection); + //fill up model + onDeviceChanged(); } bool AudioDeviceScriptingInterface::setInputDevice(const QString& deviceName) { @@ -51,13 +57,27 @@ bool AudioDeviceScriptingInterface::setInputDevice(const QString& deviceName) { bool AudioDeviceScriptingInterface::setOutputDevice(const QString& deviceName) { bool result; + QTime a; a.start(); QMetaObject::invokeMethod(DependencyManager::get().data(), "switchOutputToAudioDevice", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, result), Q_ARG(const QString&, deviceName)); + qDebug() << "switching to" << deviceName << "elapsed" << a.elapsed(); return result; } +void AudioDeviceScriptingInterface::setInputDeviceAsync(const QString& deviceName) { + QMetaObject::invokeMethod(DependencyManager::get().data(), "switchInputToAudioDevice", + Qt::QueuedConnection, + Q_ARG(const QString&, deviceName)); +} + +void AudioDeviceScriptingInterface::setOutputDeviceAsync(const QString& deviceName) { + QMetaObject::invokeMethod(DependencyManager::get().data(), "switchOutputToAudioDevice", + Qt::QueuedConnection, + Q_ARG(const QString&, deviceName)); +} + QString AudioDeviceScriptingInterface::getInputDevice() { return DependencyManager::get()->getDeviceName(QAudio::AudioInput); } @@ -116,3 +136,94 @@ void AudioDeviceScriptingInterface::setMuted(bool muted) bool AudioDeviceScriptingInterface::getMuted() { return DependencyManager::get()->isMuted(); } + +QVariant AudioDeviceScriptingInterface::data(const QModelIndex& index, int role) const { + //sanity + if (!index.isValid() || index.row() >= _devices.size()) + return QVariant(); + + + if (role == Qt::DisplayRole || role == DisplayNameRole) { + return _devices.at(index.row()).name; + } else if (role == SelectedRole) { + return _devices.at(index.row()).selected; + } else if (role == AudioModeRole) { + return (int)_devices.at(index.row()).mode; + } + return QVariant(); +} + +int AudioDeviceScriptingInterface::rowCount(const QModelIndex& parent) const { + Q_UNUSED(parent) + return _devices.size(); +} + +QHash AudioDeviceScriptingInterface::roleNames() const { + QHash roles; + roles.insert(DisplayNameRole, "devicename"); + roles.insert(SelectedRole, "devicechecked"); + roles.insert(AudioModeRole, "devicemode"); + return roles; +} + +void AudioDeviceScriptingInterface::onDeviceChanged() +{ + beginResetModel(); + _devices.clear(); + const QString &outDevice = getOutputDevice(); + for (QString name: getOutputDevices()) { + AudioDeviceInfo di; + di.name = name; + di.selected = (name == outDevice); + di.mode = QAudio::AudioOutput; + _devices.append(di); + } + const QString &inDevice = getInputDevice(); + for (QString name: getInputDevices()) { + AudioDeviceInfo di; + di.name = name; + di.selected = (name == inDevice); + di.mode = QAudio::AudioInput; + _devices.append(di); + } + + endResetModel(); + emit deviceChanged(); +} + +void AudioDeviceScriptingInterface::onCurrentInputDeviceChanged() +{ + currentDeviceUpdate(getInputDevice(), QAudio::AudioInput); + emit currentInputDeviceChanged(); +} + +void AudioDeviceScriptingInterface::onCurrentOutputDeviceChanged() +{ + currentDeviceUpdate(getOutputDevice(), QAudio::AudioOutput); + emit currentOutputDeviceChanged(); +} + +void AudioDeviceScriptingInterface::currentDeviceUpdate(const QString &name, QAudio::Mode mode) +{ + QVector role; + role.append(SelectedRole); + + qDebug() << "device update" << name << mode; + + for (int i = 0; i < _devices.size(); i++) { + AudioDeviceInfo di = _devices.at(i); + if (di.mode != mode) + continue; + if (di.selected && di.name != name ) { + di.selected = false; + _devices[i] = di; + emit dataChanged(index(i, 0), index(i, 0), role); + } + if (di.name == name) { + di.selected = true; + _devices[i] = di; + emit dataChanged(index(i, 0), index(i, 0), role); + qDebug() << "device updated" << di.name << i; + } + } +} diff --git a/interface/src/scripting/AudioDeviceScriptingInterface.h b/interface/src/scripting/AudioDeviceScriptingInterface.h index 4d1d47dcba..cadbe88d4d 100644 --- a/interface/src/scripting/AudioDeviceScriptingInterface.h +++ b/interface/src/scripting/AudioDeviceScriptingInterface.h @@ -15,10 +15,18 @@ #include #include #include +#include +#include class AudioEffectOptions; -class AudioDeviceScriptingInterface : public QObject { +struct AudioDeviceInfo { + QString name; + bool selected; + QAudio::Mode mode; +}; + +class AudioDeviceScriptingInterface : public QAbstractListModel { Q_OBJECT Q_PROPERTY(QStringList inputAudioDevices READ inputAudioDevices NOTIFY inputAudioDevicesChanged) @@ -32,6 +40,22 @@ public: QStringList outputAudioDevices() const; bool muted(); + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QHash roleNames() const override; + + enum Roles { + DisplayNameRole = Qt::UserRole, + SelectedRole, + AudioModeRole + }; + +private slots: + void onDeviceChanged(); + void onCurrentInputDeviceChanged(); + void onCurrentOutputDeviceChanged(); + void currentDeviceUpdate(const QString &name, QAudio::Mode mode); + public slots: bool setInputDevice(const QString& deviceName); bool setOutputDevice(const QString& deviceName); @@ -55,15 +79,22 @@ public slots: void setMuted(bool muted); + void setInputDeviceAsync(const QString &deviceName); + void setOutputDeviceAsync(const QString &deviceName); private: AudioDeviceScriptingInterface(); signals: void muteToggled(); void deviceChanged(); + void currentInputDeviceChanged(); + void currentOutputDeviceChanged(); void mutedChanged(bool muted); void inputAudioDevicesChanged(QStringList inputAudioDevices); void outputAudioDevicesChanged(QStringList outputAudioDevices); + +private: + QVector _devices; }; #endif // hifi_AudioDeviceScriptingInterface_h diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index b684aac89c..6e0feb3b20 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -769,7 +769,8 @@ QString AudioClient::getDefaultDeviceName(QAudio::Mode mode) { QVector AudioClient::getDeviceNames(QAudio::Mode mode) { QVector deviceNames; - foreach(QAudioDeviceInfo audioDevice, getAvailableDevices(mode)) { + const QList &availableDevice = getAvailableDevices(mode); + foreach(const QAudioDeviceInfo &audioDevice, availableDevice) { deviceNames << audioDevice.deviceName().trimmed(); } return deviceNames; @@ -1371,6 +1372,7 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceIn if (!inputDeviceInfo.isNull()) { qCDebug(audioclient) << "The audio input device " << inputDeviceInfo.deviceName() << "is available."; _inputAudioDeviceName = inputDeviceInfo.deviceName().trimmed(); + emit currentInputDeviceChanged(); if (adjustedFormatForAudioDevice(inputDeviceInfo, _desiredInputFormat, _inputFormat)) { qCDebug(audioclient) << "The format to be used for audio input is" << _inputFormat; @@ -1488,6 +1490,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice if (!outputDeviceInfo.isNull()) { qCDebug(audioclient) << "The audio output device " << outputDeviceInfo.deviceName() << "is available."; _outputAudioDeviceName = outputDeviceInfo.deviceName().trimmed(); + emit currentOutputDeviceChanged(); if (adjustedFormatForAudioDevice(outputDeviceInfo, _desiredOutputFormat, _outputFormat)) { qCDebug(audioclient) << "The format to be used for audio output is" << _outputFormat; diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 139749e8e8..acd96c395e 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -240,6 +240,9 @@ signals: void muteEnvironmentRequested(glm::vec3 position, float radius); + void currentOutputDeviceChanged(); + void currentInputDeviceChanged(); + protected: AudioClient(); ~AudioClient(); diff --git a/scripts/system/selectAudioDevice.js b/scripts/system/selectAudioDevice.js index 2dd426932f..61862ad67b 100644 --- a/scripts/system/selectAudioDevice.js +++ b/scripts/system/selectAudioDevice.js @@ -64,13 +64,14 @@ function setupAudioMenus() { // Setup audio input devices Menu.addSeparator("Audio", "Input Audio Device"); var inputDevices = AudioDevice.getInputDevices(); + var currentInputDevice = AudioDevice.getInputDevice() for (var i = 0; i < inputDevices.length; i++) { var audioDeviceMenuString = "Use " + inputDevices[i] + " for Input"; Menu.addMenuItem({ menuName: "Audio", menuItemName: audioDeviceMenuString, isCheckable: true, - isChecked: inputDevices[i] == AudioDevice.getInputDevice() + isChecked: inputDevices[i] == currentInputDevice }); audioDevicesList.push(audioDeviceMenuString); } @@ -78,13 +79,14 @@ function setupAudioMenus() { // Setup audio output devices Menu.addSeparator("Audio", "Output Audio Device"); var outputDevices = AudioDevice.getOutputDevices(); + var currentOutputDevice = AudioDevice.getOutputDevice() for (var i = 0; i < outputDevices.length; i++) { var audioDeviceMenuString = "Use " + outputDevices[i] + " for Output"; Menu.addMenuItem({ menuName: "Audio", menuItemName: audioDeviceMenuString, isCheckable: true, - isChecked: outputDevices[i] == AudioDevice.getOutputDevice() + isChecked: outputDevices[i] == currentOutputDevice }); audioDevicesList.push(audioDeviceMenuString); } @@ -133,6 +135,11 @@ function onMenuEvent(audioDeviceMenuString) { } } +function onCurrentDeviceChanged() { + debug("System audio device switched. "); + setupAudioMenus() +} + function switchAudioDevice(audioDeviceMenuString) { // if the device is not plugged in, short-circuit if (!~audioDevicesList.indexOf(audioDeviceMenuString)) { @@ -254,7 +261,9 @@ function checkHMDAudio() { // Wait for the C++ systems to fire up before trying to do anything with audio devices Script.setTimeout(function () { debug("Connecting deviceChanged(), displayModeChanged(), and switchAudioDevice()..."); - AudioDevice.deviceChanged.connect(onDevicechanged); +// AudioDevice.deviceChanged.connect(onDevicechanged); +// AudioDevice.currentInputDeviceChanged.connect(onCurrentDeviceChanged); +// AudioDevice.currentOutputDeviceChanged.connect(onCurrentDeviceChanged); HMD.displayModeChanged.connect(checkHMDAudio); Menu.menuItemEvent.connect(onMenuEvent); debug("Setting up Audio I/O menu for the first time..."); From 3fe8675b0cbc306a5509f392f8769850584ad1c7 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Sun, 30 Apr 2017 12:39:36 +0200 Subject: [PATCH 03/27] Sync Tablet Audio and Desktop Audio menus --- scripts/system/selectAudioDevice.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/selectAudioDevice.js b/scripts/system/selectAudioDevice.js index 61862ad67b..eb20dc0c92 100644 --- a/scripts/system/selectAudioDevice.js +++ b/scripts/system/selectAudioDevice.js @@ -261,9 +261,9 @@ function checkHMDAudio() { // Wait for the C++ systems to fire up before trying to do anything with audio devices Script.setTimeout(function () { debug("Connecting deviceChanged(), displayModeChanged(), and switchAudioDevice()..."); -// AudioDevice.deviceChanged.connect(onDevicechanged); -// AudioDevice.currentInputDeviceChanged.connect(onCurrentDeviceChanged); -// AudioDevice.currentOutputDeviceChanged.connect(onCurrentDeviceChanged); + AudioDevice.deviceChanged.connect(onDevicechanged); + AudioDevice.currentInputDeviceChanged.connect(onCurrentDeviceChanged); + AudioDevice.currentOutputDeviceChanged.connect(onCurrentDeviceChanged); HMD.displayModeChanged.connect(checkHMDAudio); Menu.menuItemEvent.connect(onMenuEvent); debug("Setting up Audio I/O menu for the first time..."); From 28447cde0b4a4295fe7515c089eee021f52a540c Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Mon, 1 May 2017 18:41:38 +0200 Subject: [PATCH 04/27] Get rid of QML errors in HMD mode. Sync Audio menu in Tablet/HMD without recreating menu items --- interface/resources/qml/hifi/Audio.qml | 8 +++++--- .../resources/qml/hifi/components/AudioCheckbox.qml | 1 - interface/src/Application.cpp | 2 ++ scripts/system/selectAudioDevice.js | 13 ++++++++++++- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/hifi/Audio.qml b/interface/resources/qml/hifi/Audio.qml index adb0cd4cba..09075e6fb5 100644 --- a/interface/resources/qml/hifi/Audio.qml +++ b/interface/resources/qml/hifi/Audio.qml @@ -79,7 +79,7 @@ Rectangle { } Connections { - target: AvatarInputs + target: AvatarInputs !== undefined ? AvatarInputs : null onShowAudioToolsChanged: { audioTools.checkbox.checked = showAudioTools } @@ -100,10 +100,12 @@ Rectangle { id: audioTools width: parent.width anchors { left: parent.left; right: parent.right; leftMargin: 30 } - checkbox.checked: AvatarInputs.showAudioTools + checkbox.checked: AvatarInputs !== undefined ? AvatarInputs.showAudioTools : false text.text: qsTr("Show audio level meter") onCheckBoxClicked: { - AvatarInputs.showAudioTools = checked + if (AvatarInputs !== undefined) { + AvatarInputs.showAudioTools = checked + } } } diff --git a/interface/resources/qml/hifi/components/AudioCheckbox.qml b/interface/resources/qml/hifi/components/AudioCheckbox.qml index b23c9b42fe..b037fe4c7d 100644 --- a/interface/resources/qml/hifi/components/AudioCheckbox.qml +++ b/interface/resources/qml/hifi/components/AudioCheckbox.qml @@ -18,7 +18,6 @@ Row { colorScheme: hifi.colorSchemes.dark anchors.verticalCenter: parent.verticalCenter onClicked: checkBoxClicked(cb.checked) - onCheckedChanged: console.log("checked", checked, "device ",txt.text) } RalewayBold { id: txt diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 171c755101..4cf97ed6b1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2057,6 +2057,8 @@ void Application::initializeUi() { rootContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor()); + rootContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance()); + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { rootContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get())); } diff --git a/scripts/system/selectAudioDevice.js b/scripts/system/selectAudioDevice.js index eb20dc0c92..9dcfb86ea5 100644 --- a/scripts/system/selectAudioDevice.js +++ b/scripts/system/selectAudioDevice.js @@ -137,7 +137,16 @@ function onMenuEvent(audioDeviceMenuString) { function onCurrentDeviceChanged() { debug("System audio device switched. "); - setupAudioMenus() + var interfaceInputDevice = "Use " + AudioDevice.getInputDevice() + " for Input"; + var interfaceOutputDevice = "Use " + AudioDevice.getOutputDevice() + " for Output"; + for (var index = 0; index < audioDevicesList.length; index++) { + if (audioDevicesList[index] === interfaceInputDevice || + audioDevicesList[index] === interfaceOutputDevice) { + Menu.setIsOptionChecked(audioDevicesList[index], true); + } else { + Menu.setIsOptionChecked(audioDevicesList[index], false); + } + } } function switchAudioDevice(audioDeviceMenuString) { @@ -279,6 +288,8 @@ Script.scriptEnding.connect(function () { removeAudioMenus(); Menu.menuItemEvent.disconnect(onMenuEvent); HMD.displayModeChanged.disconnect(checkHMDAudio); + AudioDevice.currentInputDeviceChanged.disconnect(onCurrentDeviceChanged); + AudioDevice.currentOutputDeviceChanged.disconnect(onCurrentDeviceChanged); AudioDevice.deviceChanged.disconnect(onDevicechanged); }); From d522864141bf3e53a8dbf6fa15899d5645a5fd43 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Thu, 4 May 2017 21:16:58 +0200 Subject: [PATCH 05/27] Remove debug prints --- interface/src/scripting/AudioDeviceScriptingInterface.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/interface/src/scripting/AudioDeviceScriptingInterface.cpp b/interface/src/scripting/AudioDeviceScriptingInterface.cpp index 4cec75074f..e5a419b7a2 100644 --- a/interface/src/scripting/AudioDeviceScriptingInterface.cpp +++ b/interface/src/scripting/AudioDeviceScriptingInterface.cpp @@ -57,12 +57,10 @@ bool AudioDeviceScriptingInterface::setInputDevice(const QString& deviceName) { bool AudioDeviceScriptingInterface::setOutputDevice(const QString& deviceName) { bool result; - QTime a; a.start(); QMetaObject::invokeMethod(DependencyManager::get().data(), "switchOutputToAudioDevice", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, result), Q_ARG(const QString&, deviceName)); - qDebug() << "switching to" << deviceName << "elapsed" << a.elapsed(); return result; } @@ -208,8 +206,6 @@ void AudioDeviceScriptingInterface::currentDeviceUpdate(const QString &name, QAu QVector role; role.append(SelectedRole); - qDebug() << "device update" << name << mode; - for (int i = 0; i < _devices.size(); i++) { AudioDeviceInfo di = _devices.at(i); if (di.mode != mode) @@ -223,7 +219,6 @@ void AudioDeviceScriptingInterface::currentDeviceUpdate(const QString &name, QAu di.selected = true; _devices[i] = di; emit dataChanged(index(i, 0), index(i, 0), role); - qDebug() << "device updated" << di.name << i; } } } From fa9a4053cabc9847218625bc952ba4367e39e719 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Mon, 8 May 2017 21:24:46 +0200 Subject: [PATCH 06/27] Save selected device in settings to make sure it will not be changed back in Menu --- interface/resources/qml/hifi/Audio.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/resources/qml/hifi/Audio.qml b/interface/resources/qml/hifi/Audio.qml index 09075e6fb5..b497edf58a 100644 --- a/interface/resources/qml/hifi/Audio.qml +++ b/interface/resources/qml/hifi/Audio.qml @@ -162,6 +162,7 @@ Rectangle { onCheckBoxClicked: { if (checked) { AudioDevice.setInputDeviceAsync(devicename) + Settings.setValue("audio_input_device", devicename); } } } @@ -218,6 +219,7 @@ Rectangle { onCheckBoxClicked: { if (checked) { AudioDevice.setOutputDeviceAsync(devicename) + Settings.setValue("audio_output_device", devicename); } } } From 9ab643c41684000e526921d04c22cd5164b4cb15 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 5 May 2017 16:47:08 -0700 Subject: [PATCH 07/27] I think this is all that must be done. --- libraries/avatars/src/AvatarData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index cb819c6b20..c4d72efa43 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1497,7 +1497,7 @@ QUrl AvatarData::cannonicalSkeletonModelURL(const QUrl& emptyURL) const { void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged) { - if (identity.updatedAt < _identityUpdatedAt) { + if (identity.updatedAt < _identityUpdatedAt && !(DependencyManager::get()->getRequestsDomainListData())) { qCDebug(avatars) << "Ignoring late identity packet for avatar " << getSessionUUID() << "identity.updatedAt:" << identity.updatedAt << "_identityUpdatedAt:" << _identityUpdatedAt; return; From d7e4f022911afa2460f8a164ba5859716caf56d9 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 9 May 2017 12:23:40 -0700 Subject: [PATCH 08/27] This is a better method. --- assignment-client/src/avatars/AvatarMixer.cpp | 2 +- libraries/avatars/src/AvatarData.cpp | 6 +++--- libraries/avatars/src/AvatarData.h | 2 +- libraries/avatars/src/AvatarHashMap.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 05dbfee912..b4d0864581 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -402,7 +402,7 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer mes AvatarData::parseAvatarIdentityPacket(message->getMessage(), identity); bool identityChanged = false; bool displayNameChanged = false; - avatar.processAvatarIdentity(identity, identityChanged, displayNameChanged); + avatar.processAvatarIdentity(identity, identityChanged, displayNameChanged, 0); if (identityChanged) { QMutexLocker nodeDataLocker(&nodeData->getMutex()); nodeData->flagIdentityChange(); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index c4d72efa43..5d5455327c 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1495,11 +1495,11 @@ QUrl AvatarData::cannonicalSkeletonModelURL(const QUrl& emptyURL) const { return _skeletonModelURL.scheme() == "file" ? emptyURL : _skeletonModelURL; } -void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged) { +void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged, const qint64 clockSkew) { - if (identity.updatedAt < _identityUpdatedAt && !(DependencyManager::get()->getRequestsDomainListData())) { + if (identity.updatedAt < _identityUpdatedAt + clockSkew) { qCDebug(avatars) << "Ignoring late identity packet for avatar " << getSessionUUID() - << "identity.updatedAt:" << identity.updatedAt << "_identityUpdatedAt:" << _identityUpdatedAt; + << "identity.updatedAt:" << identity.updatedAt << "_identityUpdatedAt:" << _identityUpdatedAt << "clockSkew:" << clockSkew; return; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 6d801793b7..e6e0571878 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -538,7 +538,7 @@ public: // identityChanged returns true if identity has changed, false otherwise. // displayNameChanged returns true if displayName has changed, false otherwise. - void processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged); + void processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged, const qint64 clockSkew); QByteArray identityByteArray() const; diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 0d341c684e..f4dc30a10c 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -148,7 +148,7 @@ void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer auto avatar = newOrExistingAvatar(identity.uuid, sendingNode); bool identityChanged = false; bool displayNameChanged = false; - avatar->processAvatarIdentity(identity, identityChanged, displayNameChanged); + avatar->processAvatarIdentity(identity, identityChanged, displayNameChanged, sendingNode->getClockSkewUsec()); } } From 2d46f9d30e640ed995692ce8157f4d1324ed1dc0 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Wed, 10 May 2017 21:21:39 +0200 Subject: [PATCH 09/27] Move most of the logic to C++ model, speed up initialization. Reduce number of AudioClient blocking calls to minimum --- interface/resources/qml/hifi/Audio.qml | 2 - .../AudioDeviceScriptingInterface.cpp | 86 ++++++++--- .../scripting/AudioDeviceScriptingInterface.h | 19 ++- libraries/audio-client/src/AudioClient.cpp | 4 +- libraries/audio-client/src/AudioClient.h | 4 +- .../src/AudioScriptingInterface.h | 1 + scripts/system/selectAudioDevice.js | 135 ++++-------------- 7 files changed, 109 insertions(+), 142 deletions(-) diff --git a/interface/resources/qml/hifi/Audio.qml b/interface/resources/qml/hifi/Audio.qml index b497edf58a..09075e6fb5 100644 --- a/interface/resources/qml/hifi/Audio.qml +++ b/interface/resources/qml/hifi/Audio.qml @@ -162,7 +162,6 @@ Rectangle { onCheckBoxClicked: { if (checked) { AudioDevice.setInputDeviceAsync(devicename) - Settings.setValue("audio_input_device", devicename); } } } @@ -219,7 +218,6 @@ Rectangle { onCheckBoxClicked: { if (checked) { AudioDevice.setOutputDeviceAsync(devicename) - Settings.setValue("audio_output_device", devicename); } } } diff --git a/interface/src/scripting/AudioDeviceScriptingInterface.cpp b/interface/src/scripting/AudioDeviceScriptingInterface.cpp index e5a419b7a2..d76a37dbe0 100644 --- a/interface/src/scripting/AudioDeviceScriptingInterface.cpp +++ b/interface/src/scripting/AudioDeviceScriptingInterface.cpp @@ -11,21 +11,19 @@ #include "AudioClient.h" #include "AudioDeviceScriptingInterface.h" - +#include "SettingsScriptingInterface.h" AudioDeviceScriptingInterface* AudioDeviceScriptingInterface::getInstance() { static AudioDeviceScriptingInterface sharedInstance; return &sharedInstance; } -QStringList AudioDeviceScriptingInterface::inputAudioDevices() const -{ - return DependencyManager::get()->getDeviceNames(QAudio::AudioInput).toList();; +QStringList AudioDeviceScriptingInterface::inputAudioDevices() const { + return _inputAudioDevices; } -QStringList AudioDeviceScriptingInterface::outputAudioDevices() const -{ - return DependencyManager::get()->getDeviceNames(QAudio::AudioOutput).toList();; +QStringList AudioDeviceScriptingInterface::outputAudioDevices() const { + return _outputAudioDevices; } bool AudioDeviceScriptingInterface::muted() @@ -44,6 +42,16 @@ AudioDeviceScriptingInterface::AudioDeviceScriptingInterface(): QAbstractListMod this, &AudioDeviceScriptingInterface::onCurrentOutputDeviceChanged, Qt::QueuedConnection); //fill up model onDeviceChanged(); + //set up previously saved device + SettingsScriptingInterface *settings = SettingsScriptingInterface::getInstance(); + const QString inDevice = settings->getValue("audio_input_device").toString(); + if (inDevice != _currentInputDevice) { + setInputDeviceAsync(inDevice); + } + const QString outDevice = settings->getValue("audio_output_device").toString(); + if (outDevice != _currentOutputDevice) { + setOutputDeviceAsync(outDevice); + } } bool AudioDeviceScriptingInterface::setInputDevice(const QString& deviceName) { @@ -64,6 +72,31 @@ bool AudioDeviceScriptingInterface::setOutputDevice(const QString& deviceName) { return result; } +bool AudioDeviceScriptingInterface::setDeviceFromMenu(const QString &deviceMenuName) { + QAudio::Mode mode; + + if (deviceMenuName.indexOf("for Output") != -1) { + mode = QAudio::AudioOutput; + } else if (deviceMenuName.indexOf("for Input") != -1) { + mode = QAudio::AudioInput; + } else { + return false; + } + + for (ScriptingAudioDeviceInfo di: _devices) { + if (mode == di.mode && deviceMenuName.contains(di.name)) { + if (mode == QAudio::AudioOutput) { + setOutputDeviceAsync(di.name); + } else { + setInputDeviceAsync(di.name); + } + return true; + } + } + + return false; +} + void AudioDeviceScriptingInterface::setInputDeviceAsync(const QString& deviceName) { QMetaObject::invokeMethod(DependencyManager::get().data(), "switchInputToAudioDevice", Qt::QueuedConnection, @@ -167,38 +200,51 @@ QHash AudioDeviceScriptingInterface::roleNames() const { void AudioDeviceScriptingInterface::onDeviceChanged() { beginResetModel(); + _outputAudioDevices.clear(); _devices.clear(); - const QString &outDevice = getOutputDevice(); + _currentOutputDevice = getOutputDevice(); for (QString name: getOutputDevices()) { - AudioDeviceInfo di; + ScriptingAudioDeviceInfo di; di.name = name; - di.selected = (name == outDevice); + di.selected = (name == _currentOutputDevice); di.mode = QAudio::AudioOutput; _devices.append(di); + _outputAudioDevices.append(name); } - const QString &inDevice = getInputDevice(); + emit outputAudioDevicesChanged(_outputAudioDevices); + + _inputAudioDevices.clear(); + _currentInputDevice = getInputDevice(); for (QString name: getInputDevices()) { - AudioDeviceInfo di; + ScriptingAudioDeviceInfo di; di.name = name; - di.selected = (name == inDevice); + di.selected = (name == _currentInputDevice); di.mode = QAudio::AudioInput; _devices.append(di); + _inputAudioDevices.append(name); } + emit inputAudioDevicesChanged(_inputAudioDevices); endResetModel(); emit deviceChanged(); } -void AudioDeviceScriptingInterface::onCurrentInputDeviceChanged() +void AudioDeviceScriptingInterface::onCurrentInputDeviceChanged(const QString &name) { - currentDeviceUpdate(getInputDevice(), QAudio::AudioInput); - emit currentInputDeviceChanged(); + currentDeviceUpdate(name, QAudio::AudioInput); + //we got a signal that device changed. Save it now + SettingsScriptingInterface *settings = SettingsScriptingInterface::getInstance(); + settings->setValue("audio_input_device", name); + emit currentInputDeviceChanged(name); } -void AudioDeviceScriptingInterface::onCurrentOutputDeviceChanged() +void AudioDeviceScriptingInterface::onCurrentOutputDeviceChanged(const QString &name) { - currentDeviceUpdate(getOutputDevice(), QAudio::AudioOutput); - emit currentOutputDeviceChanged(); + currentDeviceUpdate(name, QAudio::AudioOutput); + //we got a signal that device changed. Save it now + SettingsScriptingInterface *settings = SettingsScriptingInterface::getInstance(); + settings->setValue("audio_output_device", name); + emit currentOutputDeviceChanged(name); } void AudioDeviceScriptingInterface::currentDeviceUpdate(const QString &name, QAudio::Mode mode) @@ -207,7 +253,7 @@ void AudioDeviceScriptingInterface::currentDeviceUpdate(const QString &name, QAu role.append(SelectedRole); for (int i = 0; i < _devices.size(); i++) { - AudioDeviceInfo di = _devices.at(i); + ScriptingAudioDeviceInfo di = _devices.at(i); if (di.mode != mode) continue; if (di.selected && di.name != name ) { diff --git a/interface/src/scripting/AudioDeviceScriptingInterface.h b/interface/src/scripting/AudioDeviceScriptingInterface.h index cadbe88d4d..133069d6f3 100644 --- a/interface/src/scripting/AudioDeviceScriptingInterface.h +++ b/interface/src/scripting/AudioDeviceScriptingInterface.h @@ -20,7 +20,7 @@ class AudioEffectOptions; -struct AudioDeviceInfo { +struct ScriptingAudioDeviceInfo { QString name; bool selected; QAudio::Mode mode; @@ -52,13 +52,14 @@ public: private slots: void onDeviceChanged(); - void onCurrentInputDeviceChanged(); - void onCurrentOutputDeviceChanged(); + void onCurrentInputDeviceChanged(const QString &name); + void onCurrentOutputDeviceChanged(const QString &name); void currentDeviceUpdate(const QString &name, QAudio::Mode mode); public slots: bool setInputDevice(const QString& deviceName); bool setOutputDevice(const QString& deviceName); + bool setDeviceFromMenu(const QString& deviceMenuName); QString getInputDevice(); QString getOutputDevice(); @@ -87,14 +88,20 @@ private: signals: void muteToggled(); void deviceChanged(); - void currentInputDeviceChanged(); - void currentOutputDeviceChanged(); + void currentInputDeviceChanged(const QString &name); + void currentOutputDeviceChanged(const QString &name); void mutedChanged(bool muted); void inputAudioDevicesChanged(QStringList inputAudioDevices); void outputAudioDevicesChanged(QStringList outputAudioDevices); private: - QVector _devices; + QVector _devices; + + QStringList _inputAudioDevices; + QStringList _outputAudioDevices; + + QString _currentInputDevice; + QString _currentOutputDevice; }; #endif // hifi_AudioDeviceScriptingInterface_h diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index adb100d6b7..e9134b3bd7 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1375,7 +1375,7 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceIn if (!inputDeviceInfo.isNull()) { qCDebug(audioclient) << "The audio input device " << inputDeviceInfo.deviceName() << "is available."; _inputAudioDeviceName = inputDeviceInfo.deviceName().trimmed(); - emit currentInputDeviceChanged(); + emit currentInputDeviceChanged(_inputAudioDeviceName); if (adjustedFormatForAudioDevice(inputDeviceInfo, _desiredInputFormat, _inputFormat)) { qCDebug(audioclient) << "The format to be used for audio input is" << _inputFormat; @@ -1493,7 +1493,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice if (!outputDeviceInfo.isNull()) { qCDebug(audioclient) << "The audio output device " << outputDeviceInfo.deviceName() << "is available."; _outputAudioDeviceName = outputDeviceInfo.deviceName().trimmed(); - emit currentOutputDeviceChanged(); + emit currentOutputDeviceChanged(_outputAudioDeviceName); if (adjustedFormatForAudioDevice(outputDeviceInfo, _desiredOutputFormat, _outputFormat)) { qCDebug(audioclient) << "The format to be used for audio output is" << _outputFormat; diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 8f2e5fcffd..89ba3db14f 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -238,8 +238,8 @@ signals: void muteEnvironmentRequested(glm::vec3 position, float radius); - void currentOutputDeviceChanged(); - void currentInputDeviceChanged(); + void currentOutputDeviceChanged(const QString &name); + void currentInputDeviceChanged(const QString &name); protected: AudioClient(); diff --git a/libraries/script-engine/src/AudioScriptingInterface.h b/libraries/script-engine/src/AudioScriptingInterface.h index e97bc329c6..cfc149f59e 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.h +++ b/libraries/script-engine/src/AudioScriptingInterface.h @@ -24,6 +24,7 @@ class AudioScriptingInterface : public QObject, public Dependency { SINGLETON_DEPENDENCY public: + virtual ~AudioScriptingInterface() {} void setLocalAudioInterface(AbstractAudioInterface* audioInterface) { _localAudioInterface = audioInterface; } protected: diff --git a/scripts/system/selectAudioDevice.js b/scripts/system/selectAudioDevice.js index 9dcfb86ea5..1ecd5d23ed 100644 --- a/scripts/system/selectAudioDevice.js +++ b/scripts/system/selectAudioDevice.js @@ -17,18 +17,6 @@ const INPUT = "Input"; const OUTPUT = "Output"; -function parseMenuItem(item) { - const USE = "Use "; - const FOR_INPUT = " for " + INPUT; - const FOR_OUTPUT = " for " + OUTPUT; - if (item.slice(0, USE.length) == USE) { - if (item.slice(-FOR_INPUT.length) == FOR_INPUT) { - return { device: item.slice(USE.length, -FOR_INPUT.length), mode: INPUT }; - } else if (item.slice(-FOR_OUTPUT.length) == FOR_OUTPUT) { - return { device: item.slice(USE.length, -FOR_OUTPUT.length), mode: OUTPUT }; - } - } -} // // VAR DEFINITIONS @@ -36,13 +24,15 @@ function parseMenuItem(item) { var debugPrintStatements = true; const INPUT_DEVICE_SETTING = "audio_input_device"; const OUTPUT_DEVICE_SETTING = "audio_output_device"; -var audioDevicesList = []; +var audioDevicesList = []; // placeholder for menu items var wasHmdActive = false; // assume it's not active to start var switchedAudioInputToHMD = false; var switchedAudioOutputToHMD = false; var previousSelectedInputAudioDevice = ""; var previousSelectedOutputAudioDevice = ""; -var skipMenuEvents = true; + +var interfaceInputDevice = ""; +var interfaceOutputDevice = ""; // // BEGIN FUNCTION DEFINITIONS @@ -56,58 +46,37 @@ function debug() { function setupAudioMenus() { // menu events can be triggered asynchronously; skip them for 200ms to avoid recursion and false switches - skipMenuEvents = true; - Script.setTimeout(function() { skipMenuEvents = false; }, 200); - removeAudioMenus(); // Setup audio input devices Menu.addSeparator("Audio", "Input Audio Device"); - var inputDevices = AudioDevice.getInputDevices(); var currentInputDevice = AudioDevice.getInputDevice() - for (var i = 0; i < inputDevices.length; i++) { - var audioDeviceMenuString = "Use " + inputDevices[i] + " for Input"; + for (var i = 0; i < AudioDevice.inputAudioDevices.length; i++) { + var audioDeviceMenuString = "Use " + AudioDevice.inputAudioDevices[i] + " for Input"; Menu.addMenuItem({ menuName: "Audio", menuItemName: audioDeviceMenuString, isCheckable: true, - isChecked: inputDevices[i] == currentInputDevice + isChecked: AudioDevice.inputAudioDevices[i] == currentInputDevice }); audioDevicesList.push(audioDeviceMenuString); } // Setup audio output devices Menu.addSeparator("Audio", "Output Audio Device"); - var outputDevices = AudioDevice.getOutputDevices(); var currentOutputDevice = AudioDevice.getOutputDevice() - for (var i = 0; i < outputDevices.length; i++) { - var audioDeviceMenuString = "Use " + outputDevices[i] + " for Output"; + for (var i = 0; i < AudioDevice.outputAudioDevices.length; i++) { + var audioDeviceMenuString = "Use " + AudioDevice.outputAudioDevices[i] + " for Output"; Menu.addMenuItem({ menuName: "Audio", menuItemName: audioDeviceMenuString, isCheckable: true, - isChecked: outputDevices[i] == currentOutputDevice + isChecked: AudioDevice.outputAudioDevices[i] == currentOutputDevice }); audioDevicesList.push(audioDeviceMenuString); } } -function checkDeviceMismatch() { - var inputDeviceSetting = Settings.getValue(INPUT_DEVICE_SETTING); - var interfaceInputDevice = AudioDevice.getInputDevice(); - if (interfaceInputDevice != inputDeviceSetting) { - debug("Input Setting & Device mismatch! Input SETTING: " + inputDeviceSetting + "Input DEVICE IN USE: " + interfaceInputDevice); - switchAudioDevice("Use " + inputDeviceSetting + " for Input"); - } - - var outputDeviceSetting = Settings.getValue(OUTPUT_DEVICE_SETTING); - var interfaceOutputDevice = AudioDevice.getOutputDevice(); - if (interfaceOutputDevice != outputDeviceSetting) { - debug("Output Setting & Device mismatch! Output SETTING: " + outputDeviceSetting + "Output DEVICE IN USE: " + interfaceOutputDevice); - switchAudioDevice("Use " + outputDeviceSetting + " for Output"); - } -} - function removeAudioMenus() { Menu.removeSeparator("Audio", "Input Audio Device"); Menu.removeSeparator("Audio", "Output Audio Device"); @@ -126,81 +95,28 @@ function removeAudioMenus() { function onDevicechanged() { debug("System audio devices changed. Removing and replacing Audio Menus..."); setupAudioMenus(); - checkDeviceMismatch(); } function onMenuEvent(audioDeviceMenuString) { - if (!skipMenuEvents) { - switchAudioDevice(audioDeviceMenuString); + if (Menu.isOptionChecked(audioDeviceMenuString) && + (audioDeviceMenuString !== interfaceInputDevice && + audioDeviceMenuString !== interfaceOutputDevice)) { + AudioDevice.setDeviceFromMenu(audioDeviceMenuString) } } function onCurrentDeviceChanged() { debug("System audio device switched. "); - var interfaceInputDevice = "Use " + AudioDevice.getInputDevice() + " for Input"; - var interfaceOutputDevice = "Use " + AudioDevice.getOutputDevice() + " for Output"; + interfaceInputDevice = "Use " + AudioDevice.getInputDevice() + " for Input"; + interfaceOutputDevice = "Use " + AudioDevice.getOutputDevice() + " for Output"; for (var index = 0; index < audioDevicesList.length; index++) { if (audioDevicesList[index] === interfaceInputDevice || audioDevicesList[index] === interfaceOutputDevice) { - Menu.setIsOptionChecked(audioDevicesList[index], true); + if (Menu.isOptionChecked(audioDevicesList[index]) === false) + Menu.setIsOptionChecked(audioDevicesList[index], true); } else { - Menu.setIsOptionChecked(audioDevicesList[index], false); - } - } -} - -function switchAudioDevice(audioDeviceMenuString) { - // if the device is not plugged in, short-circuit - if (!~audioDevicesList.indexOf(audioDeviceMenuString)) { - return; - } - - var selection = parseMenuItem(audioDeviceMenuString); - if (!selection) { - debug("Invalid Audio audioDeviceMenuString! Doesn't end with 'for Input' or 'for Output'"); - return; - } - - // menu events can be triggered asynchronously; skip them for 200ms to avoid recursion and false switches - skipMenuEvents = true; - Script.setTimeout(function() { skipMenuEvents = false; }, 200); - - var selectedDevice = selection.device; - if (selection.mode == INPUT) { - var currentInputDevice = AudioDevice.getInputDevice(); - if (selectedDevice != currentInputDevice) { - debug("Switching audio INPUT device from " + currentInputDevice + " to " + selectedDevice); - Menu.setIsOptionChecked("Use " + currentInputDevice + " for Input", false); - if (AudioDevice.setInputDevice(selectedDevice)) { - Settings.setValue(INPUT_DEVICE_SETTING, selectedDevice); - Menu.setIsOptionChecked(audioDeviceMenuString, true); - } else { - debug("Error setting audio input device!") - Menu.setIsOptionChecked(audioDeviceMenuString, false); - } - } else { - debug("Selected input device is the same as the current input device!") - Settings.setValue(INPUT_DEVICE_SETTING, selectedDevice); - Menu.setIsOptionChecked(audioDeviceMenuString, true); - AudioDevice.setInputDevice(selectedDevice); // Still try to force-set the device (in case the user's trying to forcefully debug an issue) - } - } else if (selection.mode == OUTPUT) { - var currentOutputDevice = AudioDevice.getOutputDevice(); - if (selectedDevice != currentOutputDevice) { - debug("Switching audio OUTPUT device from " + currentOutputDevice + " to " + selectedDevice); - Menu.setIsOptionChecked("Use " + currentOutputDevice + " for Output", false); - if (AudioDevice.setOutputDevice(selectedDevice)) { - Settings.setValue(OUTPUT_DEVICE_SETTING, selectedDevice); - Menu.setIsOptionChecked(audioDeviceMenuString, true); - } else { - debug("Error setting audio output device!") - Menu.setIsOptionChecked(audioDeviceMenuString, false); - } - } else { - debug("Selected output device is the same as the current output device!") - Settings.setValue(OUTPUT_DEVICE_SETTING, selectedDevice); - Menu.setIsOptionChecked(audioDeviceMenuString, true); - AudioDevice.setOutputDevice(selectedDevice); // Still try to force-set the device (in case the user's trying to forcefully debug an issue) + if (Menu.isOptionChecked(audioDevicesList[index]) === true) + Menu.setIsOptionChecked(audioDevicesList[index], false); } } } @@ -208,12 +124,12 @@ function switchAudioDevice(audioDeviceMenuString) { function restoreAudio() { if (switchedAudioInputToHMD) { debug("Switching back from HMD preferred audio input to: " + previousSelectedInputAudioDevice); - switchAudioDevice("Use " + previousSelectedInputAudioDevice + " for Input"); + AudioDevice.setInputDeviceAsync(previousSelectedInputAudioDevice) switchedAudioInputToHMD = false; } if (switchedAudioOutputToHMD) { debug("Switching back from HMD preferred audio output to: " + previousSelectedOutputAudioDevice); - switchAudioDevice("Use " + previousSelectedOutputAudioDevice + " for Output"); + AudioDevice.setOutputDeviceAsync(previousSelectedOutputAudioDevice) switchedAudioOutputToHMD = false; } } @@ -240,7 +156,7 @@ function checkHMDAudio() { debug("previousSelectedInputAudioDevice: " + previousSelectedInputAudioDevice); if (hmdPreferredAudioInput != previousSelectedInputAudioDevice) { switchedAudioInputToHMD = true; - switchAudioDevice("Use " + hmdPreferredAudioInput + " for Input"); + AudioDevice.setInputDeviceAsync(hmdPreferredAudioInput) } } if (hmdPreferredAudioOutput !== "") { @@ -249,7 +165,7 @@ function checkHMDAudio() { debug("previousSelectedOutputAudioDevice: " + previousSelectedOutputAudioDevice); if (hmdPreferredAudioOutput != previousSelectedOutputAudioDevice) { switchedAudioOutputToHMD = true; - switchAudioDevice("Use " + hmdPreferredAudioOutput + " for Output"); + AudioDevice.setOutputDeviceAsync(hmdPreferredAudioOutput) } } } else { @@ -277,10 +193,9 @@ Script.setTimeout(function () { Menu.menuItemEvent.connect(onMenuEvent); debug("Setting up Audio I/O menu for the first time..."); setupAudioMenus(); - checkDeviceMismatch(); debug("Checking HMD audio status...") checkHMDAudio(); -}, 3000); +}, 300); debug("Connecting scriptEnding()"); Script.scriptEnding.connect(function () { From 43659074624096d9757d508d6b793882f04b5b59 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 10 May 2017 22:12:11 +0100 Subject: [PATCH 10/27] drop down puck configuration for gernal settings --- .../hifi/tablet/TabletGeneralPreferences.qml | 2 +- .../tabletWindows/TabletPreferencesDialog.qml | 4 +- plugins/openvr/src/ViveControllerManager.cpp | 99 +++++++++++++++++-- plugins/openvr/src/ViveControllerManager.h | 13 ++- 4 files changed, 102 insertions(+), 16 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml index 85377aaeda..17d3f1b959 100644 --- a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml +++ b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml @@ -33,6 +33,6 @@ StackView { TabletPreferencesDialog { id: root objectName: "TabletGeneralPreferences" - showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers", "Perception Neuron", "Kinect"] + showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers", "Perception Neuron", "Kinect", "Vive Pucks Configuration"] } } diff --git a/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml b/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml index 2c8f6d9ea0..3e497b053e 100644 --- a/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml +++ b/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml @@ -136,8 +136,8 @@ Item { for (var i = 0; i < sections.length; i++) { totalHeight += sections[i].height + sections[i].getPreferencesHeight(); } - console.log(totalHeight); - return totalHeight; + var bottomPadding = 100; + return (totalHeight + bottomPadding); } } } diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 6e5697730b..5dd4c71194 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include @@ -262,14 +264,21 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr glm::mat4 defaultToReferenceMat = currentHead * glm::inverse(inputCalibration.defaultHeadMat); int puckCount = (int)_validTrackedObjects.size(); - if (puckCount == MIN_PUCK_COUNT) { - _config = Config::Feet; - } else if (puckCount == MIN_FEET_AND_HIPS) { - _config = Config::FeetAndHips; - } else if (puckCount >= MIN_FEET_HIPS_CHEST) { - _config = Config::FeetHipsAndChest; - } else { + _config = _preferedConfig; + if (_config != Config::Auto && puckCount < MIN_PUCK_COUNT) { + uncalibrate(); return; + } else if (_config == Config::Auto){ + if (puckCount == MIN_PUCK_COUNT) { + _config = Config::Feet; + } else if (puckCount == MIN_FEET_AND_HIPS) { + _config = Config::FeetAndHips; + } else if (puckCount >= MIN_FEET_HIPS_CHEST) { + _config = Config::FeetHipsAndChest; + } else { + uncalibrate(); + return; + } } std::sort(_validTrackedObjects.begin(), _validTrackedObjects.end(), sortPucksYPosition); @@ -296,19 +305,23 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr if (_config == Config::Feet) { // done - } else if (_config == Config::FeetAndHips) { + } else if (_config == Config::FeetAndHips && puckCount >= MIN_FEET_AND_HIPS) { _jointToPuckMap[controller::HIPS] = _validTrackedObjects[HIP].first; _pucksOffset[_validTrackedObjects[HIP].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[HIP].second); - } else if (_config == Config::FeetHipsAndChest) { + } else if (_config == Config::FeetHipsAndChest && puckCount >= MIN_FEET_HIPS_CHEST) { _jointToPuckMap[controller::HIPS] = _validTrackedObjects[HIP].first; _pucksOffset[_validTrackedObjects[HIP].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[HIP].second); _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[CHEST].first; _pucksOffset[_validTrackedObjects[CHEST].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultSpine2, _validTrackedObjects[CHEST].second); + } else { + uncalibrate(); + return; } _calibrated = true; } void ViveControllerManager::InputDevice::uncalibrate() { + _config = Config::Auto; _pucksOffset.clear(); _jointToPuckMap.clear(); _calibrated = false; @@ -544,6 +557,74 @@ void ViveControllerManager::InputDevice::hapticsHelper(float deltaTime, bool lef } } +void ViveControllerManager::InputDevice::loadSettings() { + Settings settings; + settings.beginGroup("PUCK_CONFIG"); + { + _preferedConfig = (Config)settings.value("configuration", QVariant((int)Config::Auto)).toInt(); + } + settings.endGroup(); +} + +void ViveControllerManager::InputDevice::saveSettings() const { + Settings settings; + settings.beginGroup("PUCK_CONFIG"); + { + settings.setValue(QString("configuration"), (int)_preferedConfig); + } + settings.endGroup(); +} + +QString ViveControllerManager::InputDevice::configToString() { + QString currentConfig = ""; + switch (_preferedConfig) { + case Config::Auto: + currentConfig = "Auto"; + break; + + case Config::Feet: + currentConfig = "Feet"; + break; + + case Config::FeetAndHips: + currentConfig = "FeetAndHips"; + break; + + case Config::FeetHipsAndChest: + currentConfig = "FeetHipsAndChest"; + break; + } + return currentConfig; +} + +void ViveControllerManager::InputDevice::setConfigFromString(const QString& value) { + if (value == "Auto") { + _preferedConfig = Config::Auto; + } else if (value == "Feet") { + _preferedConfig = Config::Feet; + } else if (value == "FeetAndHips") { + _preferedConfig = Config::FeetAndHips; + } else if (value == "FeetHipsAndChest") { + _preferedConfig = Config::FeetHipsAndChest; + } +} + +void ViveControllerManager::InputDevice::createPreferences() { + loadSettings(); + auto preferences = DependencyManager::get(); + static const QString VIVE_PUCKS_CONFIG { "Vive Pucks Configuration" }; + + { + auto getter = [this]()->QString { return configToString(); }; + auto setter = [this](const QString& value) { setConfigFromString(value); saveSettings(); }; + auto preference = new ComboBoxPreference(VIVE_PUCKS_CONFIG, "Configuration", getter, setter); + QStringList list = (QStringList() << "Auto" << "Feet" << "FeetAndHips" << "FeetHipsAndChest"); + preference->setItems(list); + preferences->addPreference(preference); + + } +} + controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableInputs() const { using namespace controller; QVector availableInputs{ diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 4e8b2b3a04..9920fb003a 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -50,14 +50,14 @@ public: private: class InputDevice : public controller::InputDevice { public: - InputDevice(vr::IVRSystem*& system) : controller::InputDevice("Vive"), _system(system) {} + InputDevice(vr::IVRSystem*& system) : controller::InputDevice("Vive"), _system(system) { createPreferences(); } private: // Device functions controller::Input::NamedVector getAvailableInputs() const override; QString getDefaultMappingConfig() const override; void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; void focusOutEvent() override; - + void createPreferences(); bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override; void hapticsHelper(float deltaTime, bool leftHand); void calibrateOrUncalibrate(const controller::InputCalibrationData& inputCalibration); @@ -100,8 +100,9 @@ private: float _timer { 0.0f }; glm::vec2 _stick { 0.0f, 0.0f }; }; - enum class Config { Feet, FeetAndHips, FeetHipsAndChest, NoConfig }; - Config _config { Config::NoConfig }; + enum class Config { Feet, FeetAndHips, FeetHipsAndChest, Auto }; + Config _config { Config::Auto }; + Config _preferedConfig { Config::Auto }; FilteredStick _filteredLeftStick; FilteredStick _filteredRightStick; @@ -125,6 +126,10 @@ private: bool _timeTilCalibrationSet { false }; mutable std::recursive_mutex _lock; + QString configToString(); + void setConfigFromString(const QString& value); + void loadSettings(); + void saveSettings() const; friend class ViveControllerManager; }; From ae983658becf18702d6cd957016f84bda0ab3141 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 10 May 2017 14:46:14 -0700 Subject: [PATCH 11/27] Finally, the actual fix? --- assignment-client/src/avatars/AvatarMixer.cpp | 2 +- libraries/avatars/src/AvatarData.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index b4d0864581..998799f5e6 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -402,7 +402,7 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer mes AvatarData::parseAvatarIdentityPacket(message->getMessage(), identity); bool identityChanged = false; bool displayNameChanged = false; - avatar.processAvatarIdentity(identity, identityChanged, displayNameChanged, 0); + avatar.processAvatarIdentity(identity, identityChanged, displayNameChanged, senderNode->getClockSkewUsec()); if (identityChanged) { QMutexLocker nodeDataLocker(&nodeData->getMutex()); nodeData->flagIdentityChange(); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 5d5455327c..ec36a81a43 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1497,9 +1497,9 @@ QUrl AvatarData::cannonicalSkeletonModelURL(const QUrl& emptyURL) const { void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged, const qint64 clockSkew) { - if (identity.updatedAt < _identityUpdatedAt + clockSkew) { + if ((_identityUpdatedAt > identity.updatedAt - clockSkew) && (_identityUpdatedAt != 0)) { qCDebug(avatars) << "Ignoring late identity packet for avatar " << getSessionUUID() - << "identity.updatedAt:" << identity.updatedAt << "_identityUpdatedAt:" << _identityUpdatedAt << "clockSkew:" << clockSkew; + << "_identityUpdatedAt (" << _identityUpdatedAt << ") is greater than identity.updatedAt - clockSkew (" << identity.updatedAt << "-" << clockSkew << ")"; return; } @@ -1535,7 +1535,7 @@ void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityC // use the timestamp from this identity, since we want to honor the updated times in "server clock" // this will overwrite any changes we made locally to this AvatarData's _identityUpdatedAt - _identityUpdatedAt = identity.updatedAt; + _identityUpdatedAt = identity.updatedAt - clockSkew; } QByteArray AvatarData::identityByteArray() const { From 7687617e912719c4de3455992492dcb73e688c16 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 11 May 2017 00:32:42 +0100 Subject: [PATCH 12/27] made requested changes --- plugins/openvr/src/ViveControllerManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 5dd4c71194..e5cd7ffecc 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -576,7 +576,7 @@ void ViveControllerManager::InputDevice::saveSettings() const { } QString ViveControllerManager::InputDevice::configToString() { - QString currentConfig = ""; + QString currentConfig; switch (_preferedConfig) { case Config::Auto: currentConfig = "Auto"; @@ -601,7 +601,7 @@ void ViveControllerManager::InputDevice::setConfigFromString(const QString& valu if (value == "Auto") { _preferedConfig = Config::Auto; } else if (value == "Feet") { - _preferedConfig = Config::Feet; + _preferedConfig = Config::Feet; } else if (value == "FeetAndHips") { _preferedConfig = Config::FeetAndHips; } else if (value == "FeetHipsAndChest") { @@ -612,7 +612,7 @@ void ViveControllerManager::InputDevice::setConfigFromString(const QString& valu void ViveControllerManager::InputDevice::createPreferences() { loadSettings(); auto preferences = DependencyManager::get(); - static const QString VIVE_PUCKS_CONFIG { "Vive Pucks Configuration" }; + static const QString VIVE_PUCKS_CONFIG = "Vive Pucks Configuration"; { auto getter = [this]()->QString { return configToString(); }; From 3b06b03e0129bd2b60012bc087d3e0295e0faaf1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 11 May 2017 16:46:36 +1200 Subject: [PATCH 13/27] Rename blendshapes variables in preparation for repurposing --- libraries/avatars/src/AvatarData.cpp | 2 +- libraries/avatars/src/HeadData.cpp | 29 ++++++++++++++-------------- libraries/avatars/src/HeadData.h | 4 ++-- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index cb819c6b20..57d085a02c 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -965,7 +965,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { const int coefficientsSize = sizeof(float) * numCoefficients; PACKET_READ_CHECK(FaceTrackerCoefficients, coefficientsSize); _headData->_blendshapeCoefficients.resize(numCoefficients); // make sure there's room for the copy! - _headData->_baseBlendshapeCoefficients.resize(numCoefficients); + _headData->_transientBlendshapeCoefficients.resize(numCoefficients); memcpy(_headData->_blendshapeCoefficients.data(), sourceBuffer, coefficientsSize); sourceBuffer += coefficientsSize; int numBytesRead = sourceBuffer - startSection; diff --git a/libraries/avatars/src/HeadData.cpp b/libraries/avatars/src/HeadData.cpp index b55be7c156..d88b98b77e 100644 --- a/libraries/avatars/src/HeadData.cpp +++ b/libraries/avatars/src/HeadData.cpp @@ -34,8 +34,9 @@ HeadData::HeadData(AvatarData* owningAvatar) : _rightEyeBlink(0.0f), _averageLoudness(0.0f), _browAudioLift(0.0f), - _baseBlendshapeCoefficients(QVector(0, 0.0f)), - _currBlendShapeCoefficients(QVector(0, 0.0f)), + _blendshapeCoefficients(QVector(0, 0.0f)), + _transientBlendshapeCoefficients(QVector(0, 0.0f)), + _currentBlendshapeCoefficients(QVector(0, 0.0f)), _owningAvatar(owningAvatar) { @@ -85,22 +86,22 @@ static const QMap& getBlendshapesLookupMap() { } const QVector& HeadData::getSummedBlendshapeCoefficients() { - int maxSize = std::max(_baseBlendshapeCoefficients.size(), _blendshapeCoefficients.size()); - if (_currBlendShapeCoefficients.size() != maxSize) { - _currBlendShapeCoefficients.resize(maxSize); + int maxSize = std::max(_blendshapeCoefficients.size(), _transientBlendshapeCoefficients.size()); + if (_currentBlendshapeCoefficients.size() != maxSize) { + _currentBlendshapeCoefficients.resize(maxSize); } for (int i = 0; i < maxSize; i++) { - if (i >= _baseBlendshapeCoefficients.size()) { - _currBlendShapeCoefficients[i] = _blendshapeCoefficients[i]; - } else if (i >= _blendshapeCoefficients.size()) { - _currBlendShapeCoefficients[i] = _baseBlendshapeCoefficients[i]; + if (i >= _blendshapeCoefficients.size()) { + _currentBlendshapeCoefficients[i] = _transientBlendshapeCoefficients[i]; + } else if (i >= _transientBlendshapeCoefficients.size()) { + _currentBlendshapeCoefficients[i] = _blendshapeCoefficients[i]; } else { - _currBlendShapeCoefficients[i] = _baseBlendshapeCoefficients[i] + _blendshapeCoefficients[i]; + _currentBlendshapeCoefficients[i] = _blendshapeCoefficients[i] + _transientBlendshapeCoefficients[i]; } } - return _currBlendShapeCoefficients; + return _currentBlendshapeCoefficients; } void HeadData::setBlendshape(QString name, float val) { @@ -112,10 +113,10 @@ void HeadData::setBlendshape(QString name, float val) { if (_blendshapeCoefficients.size() <= it.value()) { _blendshapeCoefficients.resize(it.value() + 1); } - if (_baseBlendshapeCoefficients.size() <= it.value()) { - _baseBlendshapeCoefficients.resize(it.value() + 1); + if (_transientBlendshapeCoefficients.size() <= it.value()) { + _transientBlendshapeCoefficients.resize(it.value() + 1); } - _baseBlendshapeCoefficients[it.value()] = val; + _blendshapeCoefficients[it.value()] = val; } } diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index dbed0a6a65..758128f6ca 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -93,8 +93,8 @@ protected: float _browAudioLift; QVector _blendshapeCoefficients; - QVector _baseBlendshapeCoefficients; - QVector _currBlendShapeCoefficients; + QVector _transientBlendshapeCoefficients; + QVector _currentBlendshapeCoefficients; AvatarData* _owningAvatar; private: From 1b855f2c6b86d41b3a87af2b3ff9b74a7ef43ba1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 11 May 2017 18:15:38 +1200 Subject: [PATCH 14/27] Voice modulation and facetrackers write to transient blendshapes --- interface/src/avatar/MyHead.cpp | 12 ++++++------ .../avatars-renderer/src/avatars-renderer/Head.cpp | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/interface/src/avatar/MyHead.cpp b/interface/src/avatar/MyHead.cpp index c41fff3bb5..34a75c5461 100644 --- a/interface/src/avatar/MyHead.cpp +++ b/interface/src/avatar/MyHead.cpp @@ -48,7 +48,7 @@ void MyHead::simulate(float deltaTime) { FaceTracker* faceTracker = qApp->getActiveFaceTracker(); _isFaceTrackerConnected = faceTracker != NULL && !faceTracker->isMuted(); if (_isFaceTrackerConnected) { - _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); + _transientBlendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); if (typeid(*faceTracker) == typeid(DdeFaceTracker)) { @@ -60,11 +60,11 @@ void MyHead::simulate(float deltaTime) { const int FUNNEL_BLENDSHAPE = 40; const int SMILE_LEFT_BLENDSHAPE = 28; const int SMILE_RIGHT_BLENDSHAPE = 29; - _blendshapeCoefficients[JAW_OPEN_BLENDSHAPE] += _audioJawOpen; - _blendshapeCoefficients[SMILE_LEFT_BLENDSHAPE] += _mouth4; - _blendshapeCoefficients[SMILE_RIGHT_BLENDSHAPE] += _mouth4; - _blendshapeCoefficients[MMMM_BLENDSHAPE] += _mouth2; - _blendshapeCoefficients[FUNNEL_BLENDSHAPE] += _mouth3; + _transientBlendshapeCoefficients[JAW_OPEN_BLENDSHAPE] += _audioJawOpen; + _transientBlendshapeCoefficients[SMILE_LEFT_BLENDSHAPE] += _mouth4; + _transientBlendshapeCoefficients[SMILE_RIGHT_BLENDSHAPE] += _mouth4; + _transientBlendshapeCoefficients[MMMM_BLENDSHAPE] += _mouth2; + _transientBlendshapeCoefficients[FUNNEL_BLENDSHAPE] += _mouth3; } applyEyelidOffset(getFinalOrientationInWorldFrame()); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index 1c54ea269a..d7f7a402cf 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -151,7 +151,7 @@ void Head::simulate(float deltaTime) { _mouth2, _mouth3, _mouth4, - _blendshapeCoefficients); + _transientBlendshapeCoefficients); applyEyelidOffset(getOrientation()); @@ -227,15 +227,15 @@ void Head::applyEyelidOffset(glm::quat headOrientation) { for (int i = 0; i < 2; i++) { const int LEFT_EYE = 8; - float eyeCoefficient = _blendshapeCoefficients[i] - _blendshapeCoefficients[LEFT_EYE + i]; // Raw value + float eyeCoefficient = _transientBlendshapeCoefficients[i] - _transientBlendshapeCoefficients[LEFT_EYE + i]; eyeCoefficient = glm::clamp(eyelidOffset + eyeCoefficient * (1.0f - eyelidOffset), -1.0f, 1.0f); if (eyeCoefficient > 0.0f) { - _blendshapeCoefficients[i] = eyeCoefficient; - _blendshapeCoefficients[LEFT_EYE + i] = 0.0f; + _transientBlendshapeCoefficients[i] = eyeCoefficient; + _transientBlendshapeCoefficients[LEFT_EYE + i] = 0.0f; } else { - _blendshapeCoefficients[i] = 0.0f; - _blendshapeCoefficients[LEFT_EYE + i] = -eyeCoefficient; + _transientBlendshapeCoefficients[i] = 0.0f; + _transientBlendshapeCoefficients[LEFT_EYE + i] = -eyeCoefficient; } } } From 21f9594f81faf25a65c163ba1214ffa239f820c6 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 11 May 2017 18:17:12 +1200 Subject: [PATCH 15/27] Sum of blendshapes is used for recording --- libraries/avatars/src/HeadData.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libraries/avatars/src/HeadData.cpp b/libraries/avatars/src/HeadData.cpp index d88b98b77e..78e87d7757 100644 --- a/libraries/avatars/src/HeadData.cpp +++ b/libraries/avatars/src/HeadData.cpp @@ -132,14 +132,16 @@ QJsonObject HeadData::toJson() const { QJsonObject blendshapesJson; for (auto name : blendshapeLookupMap.keys()) { auto index = blendshapeLookupMap[name]; - if (index >= _blendshapeCoefficients.size()) { - continue; + float value = 0.0f; + if (index < _blendshapeCoefficients.size()) { + value += _blendshapeCoefficients[index]; } - auto value = _blendshapeCoefficients[index]; - if (value == 0.0f) { - continue; + if (index < _transientBlendshapeCoefficients.size()) { + value += _transientBlendshapeCoefficients[index]; + } + if (value != 0.0f) { + blendshapesJson[name] = value; } - blendshapesJson[name] = value; } if (!blendshapesJson.isEmpty()) { headJson[JSON_AVATAR_HEAD_BLENDSHAPE_COEFFICIENTS] = blendshapesJson; @@ -164,8 +166,8 @@ void HeadData::fromJson(const QJsonObject& json) { QJsonArray blendshapeCoefficientsJson = jsonValue.toArray(); for (const auto& blendshapeCoefficient : blendshapeCoefficientsJson) { blendshapeCoefficients.push_back((float)blendshapeCoefficient.toDouble()); - setBlendshapeCoefficients(blendshapeCoefficients); } + setBlendshapeCoefficients(blendshapeCoefficients); } else if (jsonValue.isObject()) { QJsonObject blendshapeCoefficientsJson = jsonValue.toObject(); for (const QString& name : blendshapeCoefficientsJson.keys()) { From 98b943269bb49116feded6f3efe313b1f70a460e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 11 May 2017 18:17:35 +1200 Subject: [PATCH 16/27] Sum of blendshapes is used sent through avatar mixer --- libraries/avatars/src/AvatarData.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 57d085a02c..51b69711dc 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -445,17 +445,17 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent if (hasFaceTrackerInfo) { auto startSection = destinationBuffer; auto faceTrackerInfo = reinterpret_cast(destinationBuffer); + auto blendshapeCoefficients = _headData->getSummedBlendshapeCoefficients(); faceTrackerInfo->leftEyeBlink = _headData->_leftEyeBlink; faceTrackerInfo->rightEyeBlink = _headData->_rightEyeBlink; faceTrackerInfo->averageLoudness = _headData->_averageLoudness; faceTrackerInfo->browAudioLift = _headData->_browAudioLift; - faceTrackerInfo->numBlendshapeCoefficients = _headData->_blendshapeCoefficients.size(); + faceTrackerInfo->numBlendshapeCoefficients = blendshapeCoefficients.size(); destinationBuffer += sizeof(AvatarDataPacket::FaceTrackerInfo); - // followed by a variable number of float coefficients - memcpy(destinationBuffer, _headData->_blendshapeCoefficients.data(), _headData->_blendshapeCoefficients.size() * sizeof(float)); - destinationBuffer += _headData->_blendshapeCoefficients.size() * sizeof(float); + memcpy(destinationBuffer, blendshapeCoefficients.data(), blendshapeCoefficients.size() * sizeof(float)); + destinationBuffer += blendshapeCoefficients.size() * sizeof(float); int numBytes = destinationBuffer - startSection; if (outboundDataRateOut) { From e426d70437bc214263ae0e53992da125398dc668 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 11 May 2017 18:37:23 +1200 Subject: [PATCH 17/27] Improve variable name --- libraries/avatars/src/HeadData.cpp | 14 +++++++------- libraries/avatars/src/HeadData.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/avatars/src/HeadData.cpp b/libraries/avatars/src/HeadData.cpp index 78e87d7757..2e4eec73a8 100644 --- a/libraries/avatars/src/HeadData.cpp +++ b/libraries/avatars/src/HeadData.cpp @@ -36,7 +36,7 @@ HeadData::HeadData(AvatarData* owningAvatar) : _browAudioLift(0.0f), _blendshapeCoefficients(QVector(0, 0.0f)), _transientBlendshapeCoefficients(QVector(0, 0.0f)), - _currentBlendshapeCoefficients(QVector(0, 0.0f)), + _summedBlendshapeCoefficients(QVector(0, 0.0f)), _owningAvatar(owningAvatar) { @@ -87,21 +87,21 @@ static const QMap& getBlendshapesLookupMap() { const QVector& HeadData::getSummedBlendshapeCoefficients() { int maxSize = std::max(_blendshapeCoefficients.size(), _transientBlendshapeCoefficients.size()); - if (_currentBlendshapeCoefficients.size() != maxSize) { - _currentBlendshapeCoefficients.resize(maxSize); + if (_summedBlendshapeCoefficients.size() != maxSize) { + _summedBlendshapeCoefficients.resize(maxSize); } for (int i = 0; i < maxSize; i++) { if (i >= _blendshapeCoefficients.size()) { - _currentBlendshapeCoefficients[i] = _transientBlendshapeCoefficients[i]; + _summedBlendshapeCoefficients[i] = _transientBlendshapeCoefficients[i]; } else if (i >= _transientBlendshapeCoefficients.size()) { - _currentBlendshapeCoefficients[i] = _blendshapeCoefficients[i]; + _summedBlendshapeCoefficients[i] = _blendshapeCoefficients[i]; } else { - _currentBlendshapeCoefficients[i] = _blendshapeCoefficients[i] + _transientBlendshapeCoefficients[i]; + _summedBlendshapeCoefficients[i] = _blendshapeCoefficients[i] + _transientBlendshapeCoefficients[i]; } } - return _currentBlendshapeCoefficients; + return _summedBlendshapeCoefficients; } void HeadData::setBlendshape(QString name, float val) { diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index 758128f6ca..9b28616b3f 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -94,7 +94,7 @@ protected: QVector _blendshapeCoefficients; QVector _transientBlendshapeCoefficients; - QVector _currentBlendshapeCoefficients; + QVector _summedBlendshapeCoefficients; AvatarData* _owningAvatar; private: From e4d9772bbc50094c22eec423fe35cdc64ed5eeb3 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Thu, 11 May 2017 15:20:36 +0200 Subject: [PATCH 18/27] Fixed crashes/freezes on audio switch --- libraries/audio-client/src/AudioClient.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 225ef69ae3..e8f50e3281 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1508,11 +1508,13 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice if (_audioOutput) { _audioOutput->stop(); - delete _audioOutput; + //must be deleted in next eventloop cycle when its called from notify() + _audioOutput->deleteLater(); _audioOutput = NULL; _loopbackOutputDevice = NULL; - delete _loopbackAudioOutput; + //must be deleted in next eventloop cycle when its called from notify() + _loopbackAudioOutput->deleteLater(); _loopbackAudioOutput = NULL; delete[] _outputMixBuffer; From 4290eb21eaf3459f615c6149a7e35cb86e04f371 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Thu, 11 May 2017 15:41:07 +0200 Subject: [PATCH 19/27] Fixed possible crashes/freezes on input audio switch --- libraries/audio-client/src/AudioClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index e8f50e3281..1282dbb2dc 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1403,7 +1403,7 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceIn _audioInput->stop(); _inputDevice = NULL; - delete _audioInput; + _audioInput->deleteLater(); _audioInput = NULL; _numInputCallbackBytes = 0; From bd6ac7a39e3332cc5878db42fa4aac1b730edf4d Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Thu, 11 May 2017 20:38:09 +0200 Subject: [PATCH 20/27] Code style fixes --- interface/resources/qml/hifi/Audio.qml | 2 +- .../scripting/AudioDeviceScriptingInterface.cpp | 17 +++++++++-------- .../scripting/AudioDeviceScriptingInterface.h | 14 +++++++------- .../script-engine/src/AudioScriptingInterface.h | 2 +- scripts/system/selectAudioDevice.js | 4 ++-- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/interface/resources/qml/hifi/Audio.qml b/interface/resources/qml/hifi/Audio.qml index 09075e6fb5..66760ff290 100644 --- a/interface/resources/qml/hifi/Audio.qml +++ b/interface/resources/qml/hifi/Audio.qml @@ -204,7 +204,7 @@ Rectangle { delegate: Item { width: parent.width visible: devicemode === 1 - height: visible ? 36 : 0 + height: visible ? 36 : 0 AudioCheckbox { id: cbout width: parent.width diff --git a/interface/src/scripting/AudioDeviceScriptingInterface.cpp b/interface/src/scripting/AudioDeviceScriptingInterface.cpp index d76a37dbe0..05168b0d4c 100644 --- a/interface/src/scripting/AudioDeviceScriptingInterface.cpp +++ b/interface/src/scripting/AudioDeviceScriptingInterface.cpp @@ -43,7 +43,7 @@ AudioDeviceScriptingInterface::AudioDeviceScriptingInterface(): QAbstractListMod //fill up model onDeviceChanged(); //set up previously saved device - SettingsScriptingInterface *settings = SettingsScriptingInterface::getInstance(); + SettingsScriptingInterface* settings = SettingsScriptingInterface::getInstance(); const QString inDevice = settings->getValue("audio_input_device").toString(); if (inDevice != _currentInputDevice) { setInputDeviceAsync(inDevice); @@ -72,7 +72,7 @@ bool AudioDeviceScriptingInterface::setOutputDevice(const QString& deviceName) { return result; } -bool AudioDeviceScriptingInterface::setDeviceFromMenu(const QString &deviceMenuName) { +bool AudioDeviceScriptingInterface::setDeviceFromMenu(const QString& deviceMenuName) { QAudio::Mode mode; if (deviceMenuName.indexOf("for Output") != -1) { @@ -229,33 +229,34 @@ void AudioDeviceScriptingInterface::onDeviceChanged() emit deviceChanged(); } -void AudioDeviceScriptingInterface::onCurrentInputDeviceChanged(const QString &name) +void AudioDeviceScriptingInterface::onCurrentInputDeviceChanged(const QString& name) { currentDeviceUpdate(name, QAudio::AudioInput); //we got a signal that device changed. Save it now - SettingsScriptingInterface *settings = SettingsScriptingInterface::getInstance(); + SettingsScriptingInterface* settings = SettingsScriptingInterface::getInstance(); settings->setValue("audio_input_device", name); emit currentInputDeviceChanged(name); } -void AudioDeviceScriptingInterface::onCurrentOutputDeviceChanged(const QString &name) +void AudioDeviceScriptingInterface::onCurrentOutputDeviceChanged(const QString& name) { currentDeviceUpdate(name, QAudio::AudioOutput); //we got a signal that device changed. Save it now - SettingsScriptingInterface *settings = SettingsScriptingInterface::getInstance(); + SettingsScriptingInterface* settings = SettingsScriptingInterface::getInstance(); settings->setValue("audio_output_device", name); emit currentOutputDeviceChanged(name); } -void AudioDeviceScriptingInterface::currentDeviceUpdate(const QString &name, QAudio::Mode mode) +void AudioDeviceScriptingInterface::currentDeviceUpdate(const QString& name, QAudio::Mode mode) { QVector role; role.append(SelectedRole); for (int i = 0; i < _devices.size(); i++) { ScriptingAudioDeviceInfo di = _devices.at(i); - if (di.mode != mode) + if (di.mode != mode) { continue; + } if (di.selected && di.name != name ) { di.selected = false; _devices[i] = di; diff --git a/interface/src/scripting/AudioDeviceScriptingInterface.h b/interface/src/scripting/AudioDeviceScriptingInterface.h index 133069d6f3..f912c35288 100644 --- a/interface/src/scripting/AudioDeviceScriptingInterface.h +++ b/interface/src/scripting/AudioDeviceScriptingInterface.h @@ -52,9 +52,9 @@ public: private slots: void onDeviceChanged(); - void onCurrentInputDeviceChanged(const QString &name); - void onCurrentOutputDeviceChanged(const QString &name); - void currentDeviceUpdate(const QString &name, QAudio::Mode mode); + void onCurrentInputDeviceChanged(const QString& name); + void onCurrentOutputDeviceChanged(const QString& name); + void currentDeviceUpdate(const QString& name, QAudio::Mode mode); public slots: bool setInputDevice(const QString& deviceName); @@ -80,16 +80,16 @@ public slots: void setMuted(bool muted); - void setInputDeviceAsync(const QString &deviceName); - void setOutputDeviceAsync(const QString &deviceName); + void setInputDeviceAsync(const QString& deviceName); + void setOutputDeviceAsync(const QString& deviceName); private: AudioDeviceScriptingInterface(); signals: void muteToggled(); void deviceChanged(); - void currentInputDeviceChanged(const QString &name); - void currentOutputDeviceChanged(const QString &name); + void currentInputDeviceChanged(const QString& name); + void currentOutputDeviceChanged(const QString& name); void mutedChanged(bool muted); void inputAudioDevicesChanged(QStringList inputAudioDevices); void outputAudioDevicesChanged(QStringList outputAudioDevices); diff --git a/libraries/script-engine/src/AudioScriptingInterface.h b/libraries/script-engine/src/AudioScriptingInterface.h index cfc149f59e..5ec8ce4b12 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.h +++ b/libraries/script-engine/src/AudioScriptingInterface.h @@ -24,7 +24,7 @@ class AudioScriptingInterface : public QObject, public Dependency { SINGLETON_DEPENDENCY public: - virtual ~AudioScriptingInterface() {} + virtual ~AudioScriptingInterface() {} void setLocalAudioInterface(AbstractAudioInterface* audioInterface) { _localAudioInterface = audioInterface; } protected: diff --git a/scripts/system/selectAudioDevice.js b/scripts/system/selectAudioDevice.js index 1ecd5d23ed..2d40795692 100644 --- a/scripts/system/selectAudioDevice.js +++ b/scripts/system/selectAudioDevice.js @@ -17,7 +17,7 @@ const INPUT = "Input"; const OUTPUT = "Output"; - +const SELECT_AUDIO_SCRIPT_STARTUP_TIMEOUT = 300; // // VAR DEFINITIONS // @@ -195,7 +195,7 @@ Script.setTimeout(function () { setupAudioMenus(); debug("Checking HMD audio status...") checkHMDAudio(); -}, 300); +}, SELECT_AUDIO_SCRIPT_STARTUP_TIMEOUT); debug("Connecting scriptEnding()"); Script.scriptEnding.connect(function () { From 15574f509edab5081afea71f415d8959b105a3ee Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 11 May 2017 11:45:07 -0700 Subject: [PATCH 21/27] Clarifying comments --- libraries/avatars/src/AvatarData.cpp | 3 +++ libraries/avatars/src/AvatarHashMap.cpp | 1 + 2 files changed, 4 insertions(+) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index ec36a81a43..392d3752e8 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1497,6 +1497,9 @@ QUrl AvatarData::cannonicalSkeletonModelURL(const QUrl& emptyURL) const { void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged, const qint64 clockSkew) { + // Consider the case where this packet is being processed on Client A, and Client A is connected to Sandbox B. + // If Client A's system clock is *ahead of* Sandbox B's system clock, "clockSkew" will be *negative*. + // If Client A's system clock is *behind* Sandbox B's system clock, "clockSkew" will be *positive*. if ((_identityUpdatedAt > identity.updatedAt - clockSkew) && (_identityUpdatedAt != 0)) { qCDebug(avatars) << "Ignoring late identity packet for avatar " << getSessionUUID() << "_identityUpdatedAt (" << _identityUpdatedAt << ") is greater than identity.updatedAt - clockSkew (" << identity.updatedAt << "-" << clockSkew << ")"; diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index f4dc30a10c..155ef9a0a2 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -148,6 +148,7 @@ void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer auto avatar = newOrExistingAvatar(identity.uuid, sendingNode); bool identityChanged = false; bool displayNameChanged = false; + // In this case, the "sendingNode" is the Avatar Mixer. avatar->processAvatarIdentity(identity, identityChanged, displayNameChanged, sendingNode->getClockSkewUsec()); } } From 045e93fb95e8cfdf18d7d6b13f61679bf3041761 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Thu, 11 May 2017 21:49:07 +0200 Subject: [PATCH 22/27] Code style fixes #2 --- libraries/audio-client/src/AudioClient.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index c65cacb129..47808767b3 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -222,8 +222,8 @@ signals: void muteEnvironmentRequested(glm::vec3 position, float radius); - void currentOutputDeviceChanged(const QString &name); - void currentInputDeviceChanged(const QString &name); + void currentOutputDeviceChanged(const QString& name); + void currentInputDeviceChanged(const QString& name); protected: AudioClient(); From 52c288bfed215e817081542302a3b4766a2f0da2 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 11 May 2017 14:20:42 -0700 Subject: [PATCH 23/27] Desktop users of different height can shake hands --- scripts/system/makeUserConnection.js | 36 ++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index a8afad2e1c..37a334bd70 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -198,7 +198,7 @@ } var animationData = {}; - function updateAnimationData() { + function updateAnimationData(verticalOffset) { // all we are doing here is moving the right hand to a spot // that is in front of and a bit above the hips. Basing how // far in front as scaling with the avatar's height (say hips @@ -209,6 +209,9 @@ offset = 0.8 * MyAvatar.getAbsoluteJointTranslationInObjectFrame(headIndex).y; } animationData.rightHandPosition = Vec3.multiply(offset, {x: -0.25, y: 0.8, z: 1.3}); + if (verticalOffset) { + animationData.rightHandPosition.y += verticalOffset; + } animationData.rightHandRotation = Quat.fromPitchYawRollDegrees(90, 0, 90); } function shakeHandsAnimation() { @@ -347,7 +350,32 @@ } return false; } - + function findNearestAvatar() { + // We only look some max distance away (much larger than the handshake distance, but still...) + var minDistance = MAX_AVATAR_DISTANCE * 20; + var closestAvatar; + AvatarList.getAvatarIdentifiers().forEach(function (id) { + var avatar = AvatarList.getAvatar(id); + if (avatar && avatar.sessionUUID != MyAvatar.sessionUUID) { + var currentDistance = Vec3.distance(avatar.position, MyAvatar.position); + if (minDistance > currentDistance) { + minDistance = currentDistance; + closestAvatar = avatar; + } + } + }); + return closestAvatar; + } + function adjustAnimationHeight() { + var avatar = findNearestAvatar(); + if (avatar) { + var myHeadIndex = MyAvatar.getJointIndex("Head"); + var otherHeadIndex = avatar.getJointIndex("Head"); + var diff = (avatar.getJointPosition(otherHeadIndex).y - MyAvatar.getJointPosition(myHeadIndex).y) / 2; + print("head height difference: " + diff); + updateAnimationData(diff); + } + } function findNearestWaitingAvatar() { var handPosition = getHandPosition(MyAvatar, currentHandJointIndex); var minDistance = MAX_AVATAR_DISTANCE; @@ -436,6 +464,10 @@ handStringMessageSend({ key: "waiting", }); + // potentially adjust height of handshake + if (fromKeyboard) { + adjustAnimationHeight(); + } lookForWaitingAvatar(); } } From 539aaf8c598d1ffde91fe402a5b9acfc314b90c5 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 11 May 2017 23:00:41 +0100 Subject: [PATCH 24/27] add debug statment and fixed sorting order --- plugins/openvr/src/ViveControllerManager.cpp | 19 +++++++++++++------ plugins/openvr/src/ViveControllerManager.h | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index e5cd7ffecc..8c357103c9 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -66,7 +66,7 @@ static glm::mat4 computeOffset(glm::mat4 defaultToReferenceMat, glm::mat4 defaul } static bool sortPucksYPosition(std::pair firstPuck, std::pair secondPuck) { - return (firstPuck.second.translation.y < firstPuck.second.translation.y); + return (firstPuck.second.translation.y < secondPuck.second.translation.y); } bool ViveControllerManager::isSupported() const { @@ -245,6 +245,7 @@ void ViveControllerManager::InputDevice::calibrateOrUncalibrate(const controller } void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibrationData& inputCalibration) { + qDebug() << "Puck Calibration: Starting..."; // convert the hmd head from sensor space to avatar space glm::mat4 hmdSensorFlippedMat = inputCalibration.hmdSensorMat * Matrices::Y_180; glm::mat4 sensorToAvatarMat = glm::inverse(inputCalibration.avatarMat) * inputCalibration.sensorToWorldMat; @@ -264,18 +265,24 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr glm::mat4 defaultToReferenceMat = currentHead * glm::inverse(inputCalibration.defaultHeadMat); int puckCount = (int)_validTrackedObjects.size(); + qDebug() << "Puck Calibration: " << puckCount << " pucks found for calibration"; _config = _preferedConfig; if (_config != Config::Auto && puckCount < MIN_PUCK_COUNT) { + qDebug() << "Puck Calibration: Failed: Could not meet the minimal # of pucks"; uncalibrate(); return; } else if (_config == Config::Auto){ if (puckCount == MIN_PUCK_COUNT) { _config = Config::Feet; + qDebug() << "Puck Calibration: Auto Config: " << configToString(_config) << " configuration"; } else if (puckCount == MIN_FEET_AND_HIPS) { _config = Config::FeetAndHips; + qDebug() << "Puck Calibration: Auto Config: " << configToString(_config) << " configuration"; } else if (puckCount >= MIN_FEET_HIPS_CHEST) { _config = Config::FeetHipsAndChest; + qDebug() << "Puck Calibration: Auto Config: " << configToString(_config) << " configuration"; } else { + qDebug() << "Puck Calibration: Auto Config Failed: Could not meet the minimal # of pucks"; uncalibrate(); return; } @@ -283,8 +290,6 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr std::sort(_validTrackedObjects.begin(), _validTrackedObjects.end(), sortPucksYPosition); - - auto& firstFoot = _validTrackedObjects[FIRST_FOOT]; auto& secondFoot = _validTrackedObjects[SECOND_FOOT]; controller::Pose& firstFootPose = firstFoot.second; @@ -314,10 +319,12 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[CHEST].first; _pucksOffset[_validTrackedObjects[CHEST].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultSpine2, _validTrackedObjects[CHEST].second); } else { + qDebug() << "Puck Calibration: " << configToString(_config) << " Config Failed: Could not meet the minimal # of pucks"; uncalibrate(); return; } _calibrated = true; + qDebug() << "PuckCalibration: " << configToString(_config) << " Configuration Successful"; } void ViveControllerManager::InputDevice::uncalibrate() { @@ -575,9 +582,9 @@ void ViveControllerManager::InputDevice::saveSettings() const { settings.endGroup(); } -QString ViveControllerManager::InputDevice::configToString() { +QString ViveControllerManager::InputDevice::configToString(Config config) { QString currentConfig; - switch (_preferedConfig) { + switch (config) { case Config::Auto: currentConfig = "Auto"; break; @@ -615,7 +622,7 @@ void ViveControllerManager::InputDevice::createPreferences() { static const QString VIVE_PUCKS_CONFIG = "Vive Pucks Configuration"; { - auto getter = [this]()->QString { return configToString(); }; + auto getter = [this]()->QString { return configToString(_preferedConfig); }; auto setter = [this](const QString& value) { setConfigFromString(value); saveSettings(); }; auto preference = new ComboBoxPreference(VIVE_PUCKS_CONFIG, "Configuration", getter, setter); QStringList list = (QStringList() << "Auto" << "Feet" << "FeetAndHips" << "FeetHipsAndChest"); diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 9920fb003a..c2ebdc6144 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -126,7 +126,7 @@ private: bool _timeTilCalibrationSet { false }; mutable std::recursive_mutex _lock; - QString configToString(); + QString configToString(Config config); void setConfigFromString(const QString& value); void loadSettings(); void saveSettings() const; From ae5f9e4fb15e274aa9a143dfa101a5e6b1186730 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 11 May 2017 15:10:19 -0700 Subject: [PATCH 25/27] animate scroll of partially visible cards --- interface/resources/qml/hifi/Feed.qml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/Feed.qml b/interface/resources/qml/hifi/Feed.qml index fc108f47e3..3fd28aadb8 100644 --- a/interface/resources/qml/hifi/Feed.qml +++ b/interface/resources/qml/hifi/Feed.qml @@ -238,8 +238,24 @@ Column { stackShadowNarrowing: root.stackShadowNarrowing; shadowHeight: root.stackedCardShadowHeight; - hoverThunk: function () { scroll.currentIndex = index; } - unhoverThunk: function () { scroll.currentIndex = -1; } + hoverThunk: function () { scrollToIndex(index); } + unhoverThunk: function () { scrollToIndex(-1); } } } + NumberAnimation { + id: anim; + target: scroll; + property: "contentX"; + duration: 500; + } + function scrollToIndex(index) { + anim.running = false; + var pos = scroll.contentX; + var destPos; + scroll.positionViewAtIndex(index, ListView.Contain); + destPos = scroll.contentX; + anim.from = pos; + anim.to = destPos; + anim.running = true; + } } From e1c805e76f0a02d499a78c52732764cceddb7354 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 11 May 2017 17:02:00 -0700 Subject: [PATCH 26/27] lock in Overlays::findRayIntersectionInternal --- interface/src/ui/overlays/Overlays.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 61a283b88c..4970112405 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -408,6 +408,7 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickR const QVector& overlaysToInclude, const QVector& overlaysToDiscard, bool visibleOnly, bool collidableOnly) { + QReadLocker lock(&_lock); float bestDistance = std::numeric_limits::max(); bool bestIsFront = false; From a9716313be317edfa72cdf10495e94a556cd9419 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 11 May 2017 17:02:37 -0700 Subject: [PATCH 27/27] cr feedback -- really good feedback in fact --- interface/resources/qml/hifi/Feed.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/Feed.qml b/interface/resources/qml/hifi/Feed.qml index 3fd28aadb8..c1bd35f49d 100644 --- a/interface/resources/qml/hifi/Feed.qml +++ b/interface/resources/qml/hifi/Feed.qml @@ -246,7 +246,7 @@ Column { id: anim; target: scroll; property: "contentX"; - duration: 500; + duration: 250; } function scrollToIndex(index) { anim.running = false; @@ -256,6 +256,7 @@ Column { destPos = scroll.contentX; anim.from = pos; anim.to = destPos; + scroll.currentIndex = index; anim.running = true; } }