From f6bbdec90277bb06c0b48182d4b1d51b60810fb7 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Fri, 23 Mar 2018 20:20:40 +0300 Subject: [PATCH 1/8] remove 'isHMD' from input parameters of AudioDeviceList::onDevicesChanged note: having 'isHMD' as a parameter doesn't make sense because function rebuilds model which is used by both HMD and Desktop --- interface/src/scripting/AudioDevices.cpp | 42 +++++++++++++----------- interface/src/scripting/AudioDevices.h | 2 +- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index a130b46877..1b6b71a947 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -200,28 +200,34 @@ void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device, bool isHMD emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0)); } -void AudioDeviceList::onDevicesChanged(const QList& devices, bool isHMD) { - QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice; - - const QString& savedDeviceName = isHMD ? _hmdSavedDeviceName : _desktopSavedDeviceName; +void AudioDeviceList::onDevicesChanged(const QList& devices) { beginResetModel(); _devices.clear(); foreach(const QAudioDeviceInfo& deviceInfo, devices) { AudioDevice device; - bool &isSelected = isHMD ? device.selectedHMD : device.selectedDesktop; device.info = deviceInfo; device.display = device.info.deviceName() .replace("High Definition", "HD") .remove("Device") .replace(" )", ")"); - if (!selectedDevice.isNull()) { - isSelected = (device.info == selectedDevice); - } else { - //no selected device for context. fallback to saved - isSelected = (device.info.deviceName() == savedDeviceName); + + for (bool isHMD : {false, true}) + { + QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice; + bool &isSelected = isHMD ? device.selectedHMD : device.selectedDesktop; + + if (!selectedDevice.isNull()) { + isSelected = (device.info == selectedDevice); + } + else { + //no selected device for context. fallback to saved + const QString& savedDeviceName = isHMD ? _hmdSavedDeviceName : _desktopSavedDeviceName; + isSelected = (device.info.deviceName() == savedDeviceName); + } } + qDebug() << "adding audio device:" << device.display << device.selectedDesktop << device.selectedHMD << _mode; _devices.push_back(newDevice(device)); } @@ -271,12 +277,10 @@ AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) { // connections are made after client is initialized, so we must also fetch the devices const QList& devicesInput = client->getAudioDevices(QAudio::AudioInput); const QList& devicesOutput = client->getAudioDevices(QAudio::AudioOutput); - //setup HMD devices - _inputs.onDevicesChanged(devicesInput, true); - _outputs.onDevicesChanged(devicesOutput, true); - //setup Desktop devices - _inputs.onDevicesChanged(devicesInput, false); - _outputs.onDevicesChanged(devicesOutput, false); + + //setup devices + _inputs.onDevicesChanged(devicesInput); + _outputs.onDevicesChanged(devicesOutput); } AudioDevices::~AudioDevices() {} @@ -375,11 +379,9 @@ void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList& devices, bool isHMD); + void onDevicesChanged(const QList& devices); protected: friend class AudioDevices; From 3c45f17d709a1ffd04a958e2d55992cb1cb84645 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Sun, 25 Mar 2018 12:52:55 +0300 Subject: [PATCH 2/8] remove unused code --- interface/src/scripting/AudioDevices.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index 1b6b71a947..dbdbe778b2 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -182,7 +182,6 @@ void AudioDeviceList::resetDevice(bool contextIsHMD) { } void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device, bool isHMD) { - auto oldDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice; QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice; selectedDevice = device; From 8e551f4dc0fd9d93765fe54742273cce973b55f6 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Sun, 25 Mar 2018 13:49:59 +0300 Subject: [PATCH 3/8] re-select re-plugged device --- interface/src/scripting/AudioDevices.cpp | 31 +++++++++++++++++++++--- interface/src/scripting/AudioDevices.h | 7 +++--- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index dbdbe778b2..327f9dab9f 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -202,8 +202,7 @@ void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device, bool isHMD void AudioDeviceList::onDevicesChanged(const QList& devices) { beginResetModel(); - _devices.clear(); - + QList> newDevices; foreach(const QAudioDeviceInfo& deviceInfo, devices) { AudioDevice device; device.info = deviceInfo; @@ -225,12 +224,28 @@ void AudioDeviceList::onDevicesChanged(const QList& devices) { const QString& savedDeviceName = isHMD ? _hmdSavedDeviceName : _desktopSavedDeviceName; isSelected = (device.info.deviceName() == savedDeviceName); } + + if (isSelected) { + // check if this device *is not* in old devices list - it means it was just re-plugged so needs to be selected explicitly + bool isNewDevice = true; + for (auto& oldDevice : _devices) { + if (oldDevice->info.deviceName() == device.info.deviceName()) { + isNewDevice = false; + break; + } + } + + if (isNewDevice) { + emit selectedDevicePlugged(device.info, isHMD); + } + } } qDebug() << "adding audio device:" << device.display << device.selectedDesktop << device.selectedHMD << _mode; - _devices.push_back(newDevice(device)); + newDevices.push_back(newDevice(device)); } + _devices.swap(newDevices); endResetModel(); } @@ -379,8 +394,18 @@ void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList Date: Mon, 26 Mar 2018 01:05:05 +0300 Subject: [PATCH 4/8] temporarily select 'similar-by-title' device if previously selected one was unlplugged; re-select originally selected device if it was re-plugged --- interface/src/scripting/AudioDevices.cpp | 89 +++++++++++++++++++++++- interface/src/scripting/AudioDevices.h | 2 + 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index 327f9dab9f..34a3630b78 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -10,6 +10,7 @@ // #include +#include #include #include @@ -199,10 +200,74 @@ void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device, bool isHMD emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0)); } +// Function returns 'strings similarity' as a number. The lesser number - the more similar strings are. Absolutely equal strings should return 0. +// Optimized version kindly provided by Ken +int levenshteinDistance(const QString& s1, const QString& s2) { + const int m = s1.size(); + const int n = s2.size(); + + if (m == 0) { + return n; + } + if (n == 0) { + return m; + } + + auto cost = (int*)alloca((n + 1) * sizeof(int)); + + for (int j = 0; j <= n; j++) { + cost[j] = j; + } + + for (int i = 0; i < m; i++) { + + int prev = i; + cost[0] = i + 1; + + for (int j = 0; j < n; j++) { + + int temp = cost[j + 1]; + cost[j + 1] = (s1[i] == s2[j]) ? prev : std::min(cost[j], std::min(temp, prev)) + 1; + prev = temp; + } + } + return cost[n]; +} + +std::shared_ptr getSimilarDevice(const QString& deviceName, const QList>& devices) { + + int minDistance = INT_MAX; + int minDistanceIndex = 0; + + for (auto i = 0; i < devices.length(); ++i) { + auto distance = levenshteinDistance(deviceName, devices[i]->info.deviceName()); + if (distance < minDistance) { + minDistance = distance; + minDistanceIndex = i; + } + } + + return devices[minDistanceIndex]; +} + void AudioDeviceList::onDevicesChanged(const QList& devices) { beginResetModel(); QList> newDevices; + bool hmdIsSelected = false; + bool desktopIsSelected = false; + + foreach(const QAudioDeviceInfo& deviceInfo, devices) { + for (bool isHMD : {false, true}) { + auto &backupSelectedDeviceName = isHMD ? _backupSelectedHMDDeviceName : _backupSelectedDesktopDeviceName; + if (deviceInfo.deviceName() == backupSelectedDeviceName) { + QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice; + selectedDevice = deviceInfo; + backupSelectedDeviceName.clear(); + } + } + } + foreach(const QAudioDeviceInfo& deviceInfo, devices) { AudioDevice device; device.info = deviceInfo; @@ -211,8 +276,7 @@ void AudioDeviceList::onDevicesChanged(const QList& devices) { .remove("Device") .replace(" )", ")"); - for (bool isHMD : {false, true}) - { + for (bool isHMD : {false, true}) { QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice; bool &isSelected = isHMD ? device.selectedHMD : device.selectedDesktop; @@ -226,6 +290,12 @@ void AudioDeviceList::onDevicesChanged(const QList& devices) { } if (isSelected) { + if (isHMD) { + hmdIsSelected = isSelected; + } else { + desktopIsSelected = isSelected; + } + // check if this device *is not* in old devices list - it means it was just re-plugged so needs to be selected explicitly bool isNewDevice = true; for (auto& oldDevice : _devices) { @@ -245,6 +315,21 @@ void AudioDeviceList::onDevicesChanged(const QList& devices) { newDevices.push_back(newDevice(device)); } + if (!newDevices.isEmpty()) { + if (!hmdIsSelected) { + _backupSelectedHMDDeviceName = !_selectedHMDDevice.isNull() ? _selectedHMDDevice.deviceName() : _hmdSavedDeviceName; + auto device = getSimilarDevice(_backupSelectedHMDDeviceName, newDevices); + device->selectedHMD = true; + emit selectedDevicePlugged(device->info, true); + } + if (!desktopIsSelected) { + _backupSelectedDesktopDeviceName = !_selectedDesktopDevice.isNull() ? _selectedDesktopDevice.deviceName() : _desktopSavedDeviceName; + auto device = getSimilarDevice(_backupSelectedDesktopDeviceName, newDevices); + device->selectedDesktop = true; + emit selectedDevicePlugged(device->info, false); + } + } + _devices.swap(newDevices); endResetModel(); } diff --git a/interface/src/scripting/AudioDevices.h b/interface/src/scripting/AudioDevices.h index 72d5fccedb..3d12f93113 100644 --- a/interface/src/scripting/AudioDevices.h +++ b/interface/src/scripting/AudioDevices.h @@ -65,6 +65,8 @@ protected: const QAudio::Mode _mode; QAudioDeviceInfo _selectedDesktopDevice; QAudioDeviceInfo _selectedHMDDevice; + QString _backupSelectedDesktopDeviceName; + QString _backupSelectedHMDDeviceName; QList> _devices; QString _hmdSavedDeviceName; QString _desktopSavedDeviceName; From d1d58eceab9c8f97fa43cd0e7ee2ffe3e01846d7 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 27 Mar 2018 13:04:50 +1300 Subject: [PATCH 5/8] Add Window.raise() as replacement for Window.raiseMainWindow() --- interface/src/scripting/WindowScriptingInterface.cpp | 6 +++++- interface/src/scripting/WindowScriptingInterface.h | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 78f55f0d6e..58ec744f4e 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -78,13 +78,17 @@ void WindowScriptingInterface::setFocus() { }); } -void WindowScriptingInterface::raiseMainWindow() { +void WindowScriptingInterface::raise() { // It's forbidden to call raise() from another thread. qApp->postLambdaEvent([] { qApp->raise(); }); } +void WindowScriptingInterface::raiseMainWindow() { + raise(); +} + /// Display an alert box /// \param const QString& message message to display /// \return QScriptValue::UndefinedValue diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 997e425e53..e3b092d011 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -68,9 +68,16 @@ public slots: */ void setFocus(); + /**jsdoc + * Raise the Interface window if it is minimized. If raised, the window gains focus. + * @function Window.raise + */ + void raise(); + /**jsdoc * Raise the Interface window if it is minimized. If raised, the window gains focus. * @function Window.raiseMainWindow + * @deprecated Use {@link Window.raise|raise} instead. */ void raiseMainWindow(); From 3d7f7f0e620270b6dc5b14bac5ac176c02139ad7 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 27 Mar 2018 14:05:43 -0700 Subject: [PATCH 6/8] fix parent tree grabbing --- .../system/controllers/controllerModules/farActionGrabEntity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index 09cea58cea..07450e54ba 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -475,7 +475,7 @@ Script.include("/~/system/libraries/Xform.js"); entityID = targetEntity.id; targetProps = targetEntity.props; - if (entityIsGrabbable(targetProps)) { + if (entityIsGrabbable(targetProps) || entityIsGrabbable(this.targetObject.entityProps)) { if (!entityIsDistanceGrabbable(targetProps)) { this.targetObject.makeDynamic(); } From 420672a7690d1ccaf4fb070812bc9abbc7c11f6f Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 29 Mar 2018 09:26:05 -0700 Subject: [PATCH 7/8] fix-qml-confict --- interface/resources/qml/{AudioScope.qml => AudioScopeUI.qml} | 1 + scripts/developer/utilities/audio/audioScope.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) rename interface/resources/qml/{AudioScope.qml => AudioScopeUI.qml} (99%) diff --git a/interface/resources/qml/AudioScope.qml b/interface/resources/qml/AudioScopeUI.qml similarity index 99% rename from interface/resources/qml/AudioScope.qml rename to interface/resources/qml/AudioScopeUI.qml index aa181dbf8d..b009c249bc 100644 --- a/interface/resources/qml/AudioScope.qml +++ b/interface/resources/qml/AudioScopeUI.qml @@ -12,6 +12,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import "styles-uit" import "controls-uit" as HifiControlsUit +import "." as HifiRoot Item { id: root diff --git a/scripts/developer/utilities/audio/audioScope.js b/scripts/developer/utilities/audio/audioScope.js index 00c9e4b725..63cbf0a6e2 100644 --- a/scripts/developer/utilities/audio/audioScope.js +++ b/scripts/developer/utilities/audio/audioScope.js @@ -1,4 +1,4 @@ -var qml = Script.resourcesPath() + '/qml/AudioScope.qml'; +var qml = Script.resourcesPath() + '/qml/AudioScopeUI.qml'; var window = new OverlayWindow({ title: 'Audio Scope', source: qml, @@ -14,4 +14,4 @@ window.closed.connect(function () { AudioScope.setServerEcho(false); AudioScope.selectAudioScopeFiveFrames(); Script.stop(); -}); \ No newline at end of file +}); From f7a081c9ecf6180c848697041bf519a033da08cb Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 29 Mar 2018 09:29:01 -0700 Subject: [PATCH 8/8] minimize diff --- interface/resources/qml/AudioScopeUI.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/resources/qml/AudioScopeUI.qml b/interface/resources/qml/AudioScopeUI.qml index b009c249bc..aa181dbf8d 100644 --- a/interface/resources/qml/AudioScopeUI.qml +++ b/interface/resources/qml/AudioScopeUI.qml @@ -12,7 +12,6 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import "styles-uit" import "controls-uit" as HifiControlsUit -import "." as HifiRoot Item { id: root