diff --git a/interface/resources/html/createGlobalEventBridge.js b/interface/resources/html/createGlobalEventBridge.js
index bccbdfaf7c..b85aa33e33 100644
--- a/interface/resources/html/createGlobalEventBridge.js
+++ b/interface/resources/html/createGlobalEventBridge.js
@@ -65,21 +65,23 @@ var EventBridge;
// we need to listen to events that might precede the addition of this elements.
// A more robust hack will be to add a setInterval that look for DOM changes every 100-300 ms (low performance?)
- window.onload = function(){
+ window.addEventListener("load",function(event) {
setTimeout(function() {
EventBridge.forceHtmlAudioOutputDeviceUpdate();
}, 1200);
- };
- document.onclick = function(){
+ }, false);
+
+ document.addEventListener("click",function(){
setTimeout(function() {
EventBridge.forceHtmlAudioOutputDeviceUpdate();
}, 1200);
- };
- document.onchange = function(){
+ }, false);
+
+ document.addEventListener("change",function(){
setTimeout(function() {
EventBridge.forceHtmlAudioOutputDeviceUpdate();
}, 1200);
- };
+ }, false);
tempEventBridge._callbacks.forEach(function (callback) {
EventBridge.scriptEventReceived.connect(callback);
diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
index 7bc88d73f6..9a591018f5 100644
--- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp
+++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
@@ -121,63 +121,58 @@ uint64_t uvec2ToUint64(const uvec2& v) {
class AudioHandler : public QObject, QRunnable {
Q_OBJECT
public:
- AudioHandler(QObject* container, const QString& deviceName, int runDelayMs = 0, QObject* parent = nullptr) : QObject(parent) {
- _container = container;
+ AudioHandler(QSharedPointer surface, const QString& deviceName, QObject* parent = nullptr) : QObject(parent) {
_newTargetDevice = deviceName;
- _runDelayMs = runDelayMs;
+ _surface = surface;
setAutoDelete(true);
- QThreadPool::globalInstance()->start(this);
+ if (deviceName.size() > 0) {
+ QThreadPool::globalInstance()->start(this);
+ }
}
virtual ~AudioHandler() {
qDebug() << "Audio Handler Destroyed";
}
void run() override {
- if (_newTargetDevice.isEmpty()) {
- return;
- }
- if (_runDelayMs > 0) {
- QThread::msleep(_runDelayMs);
- }
- auto audioIO = DependencyManager::get();
- QString deviceName = audioIO->getActiveAudioDevice(QAudio::AudioOutput).deviceName();
- for (auto player : _container->findChildren()) {
- auto mediaState = player->state();
- QMediaService *svc = player->service();
- if (nullptr == svc) {
- return;
- }
- QAudioOutputSelectorControl *out = qobject_cast
- (svc->requestControl(QAudioOutputSelectorControl_iid));
- if (nullptr == out) {
- return;
- }
- QString deviceOuput;
- auto outputs = out->availableOutputs();
- for (int i = 0; i < outputs.size(); i++) {
- QString output = outputs[i];
- QString description = out->outputDescription(output);
- if (description == deviceName) {
- deviceOuput = output;
- break;
+ if (!_surface.isNull() && _surface->getRootItem() && !_surface->getCleaned()) {
+ for (auto player : _surface->getRootItem()->findChildren()) {
+ auto mediaState = player->state();
+ QMediaService *svc = player->service();
+ if (nullptr == svc) {
+ return;
+ }
+ QAudioOutputSelectorControl *out = qobject_cast
+ (svc->requestControl(QAudioOutputSelectorControl_iid));
+ if (nullptr == out) {
+ return;
+ }
+ QString deviceOuput;
+ auto outputs = out->availableOutputs();
+ for (int i = 0; i < outputs.size(); i++) {
+ QString output = outputs[i];
+ QString description = out->outputDescription(output);
+ if (description == _newTargetDevice) {
+ deviceOuput = output;
+ break;
+ }
+ }
+ out->setActiveOutput(deviceOuput);
+ svc->releaseControl(out);
+ // if multimedia was paused, it will start playing automatically after changing audio device
+ // this will reset it back to a paused state
+ if (mediaState == QMediaPlayer::State::PausedState) {
+ player->pause();
+ }
+ else if (mediaState == QMediaPlayer::State::StoppedState) {
+ player->stop();
}
}
- out->setActiveOutput(deviceOuput);
- svc->releaseControl(out);
- // if multimedia was paused, it will start playing automatically after changing audio device
- // this will reset it back to a paused state
- if (mediaState == QMediaPlayer::State::PausedState) {
- player->pause();
- } else if (mediaState == QMediaPlayer::State::StoppedState) {
- player->stop();
- }
}
- qDebug() << "QML Audio changed to " << deviceName;
+ qDebug() << "QML Audio changed to " << _newTargetDevice;
}
private:
QString _newTargetDevice;
- QObject* _container;
- int _runDelayMs;
+ QSharedPointer _surface;
};
class OffscreenTextures {
@@ -502,6 +497,7 @@ QOpenGLContext* OffscreenQmlSurface::getSharedContext() {
}
void OffscreenQmlSurface::cleanup() {
+ _isCleaned = true;
_canvas->makeCurrent();
_renderControl->invalidate();
@@ -600,6 +596,7 @@ OffscreenQmlSurface::OffscreenQmlSurface() {
OffscreenQmlSurface::~OffscreenQmlSurface() {
QObject::disconnect(&_updateTimer);
+ disconnectAudioOutputTimer();
QObject::disconnect(qApp);
cleanup();
@@ -613,6 +610,15 @@ OffscreenQmlSurface::~OffscreenQmlSurface() {
void OffscreenQmlSurface::onAboutToQuit() {
_paused = true;
QObject::disconnect(&_updateTimer);
+ disconnectAudioOutputTimer();
+
+}
+
+void OffscreenQmlSurface::disconnectAudioOutputTimer() {
+ if (_audioOutputUpdateTimer.isActive()) {
+ _audioOutputUpdateTimer.stop();
+ }
+ QObject::disconnect(&_audioOutputUpdateTimer);
}
void OffscreenQmlSurface::create() {
@@ -671,6 +677,14 @@ void OffscreenQmlSurface::create() {
}
});
+ // Setup the update of the QML media components with the current audio output device
+ QObject::connect(&_audioOutputUpdateTimer, &QTimer::timeout, this, [this]() {
+ new AudioHandler(sharedFromThis(), _currentAudioOutputDevice);
+ });
+ int waitForAudioQmlMs = 200;
+ _audioOutputUpdateTimer.setInterval(waitForAudioQmlMs);
+ _audioOutputUpdateTimer.setSingleShot(true);
+
// When Quick says there is a need to render, we will not render immediately. Instead,
// a timer with a small interval is used to get better performance.
QObject::connect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick);
@@ -699,10 +713,11 @@ void OffscreenQmlSurface::forceQmlAudioOutputDeviceUpdate() {
QMetaObject::invokeMethod(this, "forceQmlAudioOutputDeviceUpdate", Qt::QueuedConnection);
} else {
auto audioIO = DependencyManager::get();
- QString deviceName = audioIO->getActiveAudioDevice(QAudio::AudioOutput).deviceName();
- int waitForAudioQmlMs = 500;
- // The audio device need to be change using oth
- new AudioHandler(_rootItem, deviceName, waitForAudioQmlMs);
+ _currentAudioOutputDevice = audioIO->getActiveAudioDevice(QAudio::AudioOutput).deviceName();
+ if (_audioOutputUpdateTimer.isActive()) {
+ _audioOutputUpdateTimer.stop();
+ }
+ _audioOutputUpdateTimer.start();
}
}
diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.h b/libraries/ui/src/ui/OffscreenQmlSurface.h
index 44c6c3c77b..4c23c62c12 100644
--- a/libraries/ui/src/ui/OffscreenQmlSurface.h
+++ b/libraries/ui/src/ui/OffscreenQmlSurface.h
@@ -40,7 +40,7 @@ class QQuickItem;
using QmlContextCallback = std::function;
-class OffscreenQmlSurface : public QObject {
+class OffscreenQmlSurface : public QObject, public QEnableSharedFromThis {
Q_OBJECT
Q_PROPERTY(bool focusText READ isFocusText NOTIFY focusTextChanged)
public:
@@ -75,6 +75,7 @@ public:
void pause();
void resume();
bool isPaused() const;
+ bool getCleaned() { return _isCleaned; }
void setBaseUrl(const QUrl& baseUrl);
QQuickItem* getRootItem();
@@ -116,6 +117,7 @@ public slots:
void changeAudioOutputDevice(const QString& deviceName, bool isHtmlUpdate = false);
void forceHtmlAudioOutputDeviceUpdate();
void forceQmlAudioOutputDeviceUpdate();
+
signals:
void audioOutputDeviceChanged(const QString& deviceName);
@@ -147,6 +149,7 @@ private:
void render();
void cleanup();
QJsonObject getGLContextData();
+ void disconnectAudioOutputTimer();
private slots:
void updateQuick();
@@ -170,6 +173,9 @@ private:
uint64_t _lastRenderTime { 0 };
uvec2 _size;
+ QTimer _audioOutputUpdateTimer;
+ QString _currentAudioOutputDevice;
+
// Texture management
TextureAndFence _latestTextureAndFence { 0, 0 };
@@ -177,6 +183,7 @@ private:
bool _polish { true };
bool _paused { true };
bool _focusText { false };
+ bool _isCleaned{ false };
uint8_t _maxFps { 60 };
MouseTranslator _mouseTranslator { [](const QPointF& p) { return p.toPoint(); } };
QWindow* _proxyWindow { nullptr };
diff --git a/scripts/system/controllers/controllerModules/hudOverlayPointer.js b/scripts/system/controllers/controllerModules/hudOverlayPointer.js
index 38ee29ae3b..a1faacbdd6 100644
--- a/scripts/system/controllers/controllerModules/hudOverlayPointer.js
+++ b/scripts/system/controllers/controllerModules/hudOverlayPointer.js
@@ -62,7 +62,7 @@
this.pointingAtTablet = function(controllerData) {
var rayPick = controllerData.rayPicks[this.hand];
- return (rayPick.objectID === HMD.tabletScreenID || rayPick.objectID === HMD.homeButtonID);
+ return (HMD.tabletScreenID && HMD.homeButtonID && (rayPick.objectID === HMD.tabletScreenID || rayPick.objectID === HMD.homeButtonID));
};
this.getOtherModule = function() {
diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js
index 26bebc9247..01c8424e0c 100644
--- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js
+++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js
@@ -81,7 +81,8 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
};
this.otherHandIsParent = function(props) {
- return this.getOtherModule().thisHandIsParent(props);
+ var otherModule = this.getOtherModule();
+ return (otherModule.thisHandIsParent(props) && otherModule.grabbing);
};
this.startNearParentingGrabEntity = function (controllerData, targetProps) {