mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
Clean update bug 8027
This commit is contained in:
parent
f21a284324
commit
f32282afdd
8 changed files with 153 additions and 6 deletions
|
@ -33,6 +33,54 @@ var EventBridge;
|
|||
// replace the TempEventBridge with the real one.
|
||||
var tempEventBridge = EventBridge;
|
||||
EventBridge = channel.objects.eventBridge;
|
||||
EventBridge.audioOutputDeviceChanged.connect(function(deviceName) {
|
||||
navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then(function(mediaStream) {
|
||||
navigator.mediaDevices.enumerateDevices().then(function(devices) {
|
||||
devices.forEach(function(device) {
|
||||
if (device.kind == "audiooutput") {
|
||||
if (device.label == deviceName){
|
||||
console.log("Changing HTML audio output to device " + device.label);
|
||||
var deviceId = device.deviceId;
|
||||
var videos = document.getElementsByTagName("video");
|
||||
for (var i = 0; i < videos.length; i++){
|
||||
videos[i].setSinkId(deviceId);
|
||||
}
|
||||
var audios = document.getElementsByTagName("audio");
|
||||
for (var i = 0; i < audios.length; i++){
|
||||
audios[i].setSinkId(deviceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}).catch(function(err) {
|
||||
console.log("Error getting media devices"+ err.name + ": " + err.message);
|
||||
});
|
||||
}).catch(function(err) {
|
||||
console.log("Error getting user media"+ err.name + ": " + err.message);
|
||||
});
|
||||
});
|
||||
|
||||
// To be able to update the state of the output device selection for every element added to the DOM
|
||||
// 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(){
|
||||
setTimeout(function() {
|
||||
EventBridge.forceHtmlAudioOutputDeviceUpdate();
|
||||
}, 1200);
|
||||
};
|
||||
document.onclick = function(){
|
||||
setTimeout(function() {
|
||||
EventBridge.forceHtmlAudioOutputDeviceUpdate();
|
||||
}, 1200);
|
||||
};
|
||||
document.onchange = function(){
|
||||
setTimeout(function() {
|
||||
EventBridge.forceHtmlAudioOutputDeviceUpdate();
|
||||
}, 1200);
|
||||
};
|
||||
|
||||
tempEventBridge._callbacks.forEach(function (callback) {
|
||||
EventBridge.scriptEventReceived.connect(callback);
|
||||
});
|
||||
|
|
|
@ -212,7 +212,7 @@ ScrollingWindow {
|
|||
WebEngineScript {
|
||||
id: createGlobalEventBridge
|
||||
sourceCode: eventBridgeJavaScriptToInject
|
||||
injectionPoint: WebEngineScript.DocumentCreation
|
||||
injectionPoint: WebEngineScript.Deferred
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
|
@ -233,9 +233,13 @@ ScrollingWindow {
|
|||
anchors.right: parent.right
|
||||
|
||||
onFeaturePermissionRequested: {
|
||||
permissionsBar.securityOrigin = securityOrigin;
|
||||
permissionsBar.feature = feature;
|
||||
root.showPermissionsBar();
|
||||
if (feature == 2) { // QWebEnginePage::MediaAudioCapture
|
||||
grantFeaturePermission(securityOrigin, feature, true);
|
||||
} else {
|
||||
permissionsBar.securityOrigin = securityOrigin;
|
||||
permissionsBar.feature = feature;
|
||||
root.showPermissionsBar();
|
||||
}
|
||||
}
|
||||
|
||||
onLoadingChanged: {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
set(TARGET_NAME ui)
|
||||
setup_hifi_library(OpenGL Network Qml Quick Script WebChannel WebEngine WebSockets XmlPatterns)
|
||||
link_hifi_libraries(shared networking gl audio)
|
||||
setup_hifi_library(OpenGL Multimedia Network Qml Quick Script WebChannel WebEngine WebSockets XmlPatterns)
|
||||
link_hifi_libraries(shared networking gl audio audio-client plugins)
|
||||
|
||||
# Required for some low level GL interaction in the OffscreenQMLSurface
|
||||
target_opengl()
|
||||
|
|
|
@ -24,7 +24,11 @@
|
|||
#include <QtCore/QThread>
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QWaitCondition>
|
||||
#include <QtMultimedia/qmediaservice.h>
|
||||
#include <QtMultimedia/qaudiooutputselectorcontrol.h>
|
||||
#include <QtMultimedia/qmediaplayer.h>
|
||||
|
||||
#include <AudioClient.h>
|
||||
#include <shared/NsightHelpers.h>
|
||||
#include <shared/GlobalAppProperties.h>
|
||||
#include <shared/QtHelpers.h>
|
||||
|
@ -595,6 +599,14 @@ void OffscreenQmlSurface::create() {
|
|||
// Find a way to flag older scripts using this mechanism and wanr that this is deprecated
|
||||
_qmlContext->setContextProperty("eventBridgeWrapper", new EventBridgeWrapper(this, _qmlContext));
|
||||
_renderControl->initialize(_canvas->getContext());
|
||||
|
||||
// Connect with the audio client and listen for audio device changes
|
||||
auto audioIO = DependencyManager::get<AudioClient>();
|
||||
connect(audioIO.data(), &AudioClient::deviceChanged, this, [&](QAudio::Mode mode, const QAudioDeviceInfo& device) {
|
||||
if (mode == QAudio::Mode::AudioOutput) {
|
||||
QMetaObject::invokeMethod(this, "changeAudioOutputDevice", Qt::DirectConnection, Q_ARG(QString, device.deviceName()));
|
||||
}
|
||||
});
|
||||
|
||||
// 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.
|
||||
|
@ -605,6 +617,68 @@ void OffscreenQmlSurface::create() {
|
|||
_updateTimer.start();
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::changeAudioOutputDevice(const QString& deviceName, bool isHtmlUpdate) {
|
||||
if (_rootItem != nullptr && !isHtmlUpdate) {
|
||||
QMetaObject::invokeMethod(this, "forceQmlAudioOutputDeviceUpdate", Qt::DirectConnection);
|
||||
}
|
||||
emit audioOutputDeviceChanged(deviceName);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::forceHtmlAudioOutputDeviceUpdate() {
|
||||
auto audioIO = DependencyManager::get<AudioClient>();
|
||||
QString deviceName = audioIO->getActiveAudioDevice(QAudio::AudioOutput).deviceName();
|
||||
QMetaObject::invokeMethod(this, "changeAudioOutputDevice", Qt::DirectConnection,
|
||||
Q_ARG(QString, deviceName), Q_ARG(bool, true));
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::forceQmlAudioOutputDeviceUpdate() {
|
||||
if (QThread::currentThread() != qApp->thread()) {
|
||||
QMetaObject::invokeMethod(this, "forceQmlAudioOutputDeviceUpdate", Qt::QueuedConnection);
|
||||
}
|
||||
else {
|
||||
int waitForAudioQmlMs = 500;
|
||||
QTimer::singleShot(waitForAudioQmlMs, this, SLOT(updateQmlAudio()));
|
||||
}
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::updateQmlAudio() {
|
||||
auto audioIO = DependencyManager::get<AudioClient>();
|
||||
QString deviceName = audioIO->getActiveAudioDevice(QAudio::AudioOutput).deviceName();
|
||||
for (auto player : _rootItem->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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
static uvec2 clampSize(const uvec2& size, uint32_t maxDimension) {
|
||||
return glm::clamp(size, glm::uvec2(1), glm::uvec2(maxDimension));
|
||||
}
|
||||
|
@ -798,6 +872,7 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext
|
|||
if (newItem) {
|
||||
newItem->setParentItem(_rootItem);
|
||||
}
|
||||
QMetaObject::invokeMethod(this, "forceQmlAudioOutputDeviceUpdate", Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -817,6 +892,7 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext
|
|||
for (const auto& callback : callbacks) {
|
||||
callback(qmlContext, newObject);
|
||||
}
|
||||
QMetaObject::invokeMethod(this, "forceQmlAudioOutputDeviceUpdate", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::updateQuick() {
|
||||
|
|
|
@ -103,6 +103,15 @@ public slots:
|
|||
void onAboutToQuit();
|
||||
void focusDestroyed(QObject *obj);
|
||||
|
||||
// audio output device
|
||||
public slots:
|
||||
void changeAudioOutputDevice(const QString& deviceName, bool isHtmlUpdate = false);
|
||||
void forceHtmlAudioOutputDeviceUpdate();
|
||||
void forceQmlAudioOutputDeviceUpdate();
|
||||
void updateQmlAudio();
|
||||
signals:
|
||||
void audioOutputDeviceChanged(const QString& deviceName);
|
||||
|
||||
// event bridge
|
||||
public slots:
|
||||
void emitScriptEvent(const QVariant& scriptMessage);
|
||||
|
|
|
@ -15,4 +15,7 @@ if (NOT ANDROID)
|
|||
setup_hifi_plugin(Script Qml Widgets)
|
||||
link_hifi_libraries(shared controllers ui plugins ui-plugins input-plugins)
|
||||
target_sixense()
|
||||
if (WIN32)
|
||||
target_link_libraries(${TARGET_NAME} Winmm.lib)
|
||||
endif()
|
||||
endif ()
|
||||
|
|
|
@ -17,5 +17,8 @@ if (WIN32)
|
|||
target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES})
|
||||
endif()
|
||||
if (WIN32)
|
||||
target_link_libraries(${TARGET_NAME} Winmm.lib)
|
||||
endif()
|
||||
|
||||
package_libraries_for_deployment()
|
||||
|
|
|
@ -14,6 +14,10 @@ set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
|
|||
# link in the shared libraries
|
||||
link_hifi_libraries(shared networking model fbx ktx image octree gl gpu gpu-gl render model-networking networking render-utils entities entities-renderer animation audio avatars script-engine physics procedural midi ui)
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(${TARGET_NAME} Winmm.lib)
|
||||
endif()
|
||||
|
||||
package_libraries_for_deployment()
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue