Merge pull request #11931 from highfidelity/stable

stable -> master
This commit is contained in:
Clément Brisset 2017-12-05 11:58:23 -08:00 committed by GitHub
commit a5e671e0fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 81 additions and 56 deletions

View file

@ -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);

View file

@ -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<OffscreenQmlSurface> 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<AudioClient>();
QString deviceName = audioIO->getActiveAudioDevice(QAudio::AudioOutput).deviceName();
for (auto player : _container->findChildren<QMediaPlayer*>()) {
auto mediaState = player->state();
QMediaService *svc = player->service();
if (nullptr == svc) {
return;
}
QAudioOutputSelectorControl *out = qobject_cast<QAudioOutputSelectorControl *>
(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<QMediaPlayer*>()) {
auto mediaState = player->state();
QMediaService *svc = player->service();
if (nullptr == svc) {
return;
}
QAudioOutputSelectorControl *out = qobject_cast<QAudioOutputSelectorControl *>
(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<OffscreenQmlSurface> _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<AudioClient>();
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();
}
}

View file

@ -40,7 +40,7 @@ class QQuickItem;
using QmlContextCallback = std::function<void(QQmlContext*, QObject*)>;
class OffscreenQmlSurface : public QObject {
class OffscreenQmlSurface : public QObject, public QEnableSharedFromThis<OffscreenQmlSurface> {
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 };

View file

@ -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() {

View file

@ -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) {