diff options
author | Lorn Potter <lorn.potter@gmail.com> | 2023-08-11 14:53:06 +1000 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-08-22 05:18:05 +0000 |
commit | d1841e202ce39413a96e4cb0fc5bb8b8066a6f36 (patch) | |
tree | e60a34c85f2f28747c2dc85a29eeb16ec4572eef | |
parent | ff75ad9bc02676b7eb2d8e8cd4fd9d5c52d04251 (diff) |
wasm: use asyncify to await for device enumeration
Fixes: QTBUG-115059
Change-Id: I86a780209d7caf1f2ac4c1709da83fcdb3db1272
Reviewed-by: MikoĊaj Boc <Mikolaj.Boc@qt.io>
(cherry picked from commit af0e8d0ce152e3a414e502280e271971fef74ed3)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/multimedia/wasm/qwasmmediadevices.cpp | 298 | ||||
-rw-r--r-- | src/multimedia/wasm/qwasmmediadevices_p.h | 2 |
2 files changed, 166 insertions, 134 deletions
diff --git a/src/multimedia/wasm/qwasmmediadevices.cpp b/src/multimedia/wasm/qwasmmediadevices.cpp index eafa1babf..2f4ff687f 100644 --- a/src/multimedia/wasm/qwasmmediadevices.cpp +++ b/src/multimedia/wasm/qwasmmediadevices.cpp @@ -71,6 +71,130 @@ QPlatformAudioSink *QWasmMediaDevices::createAudioSink(const QAudioDevice &devic return new QWasmAudioSink(deviceInfo.id(), parent); } +void QWasmMediaDevices::parseDevices(emscripten::val devices) +{ + if (devices.isNull() || devices.isUndefined()) { + qWarning() << "Something went wrong enumerating devices"; + return; + } + + QList<std::string> cameraDevicesToRemove = m_cameraDevices.keys(); + QList<std::string> audioOutputsToRemove; + QList<std::string> audioInputsToRemove; + + if (m_firstInit) { + m_firstInit = false; + qWarning() << "m_audioInputs count" << m_audioInputs.count(); + + } else { + audioOutputsToRemove = m_audioOutputs.keys(); + audioInputsToRemove = m_audioInputs.keys(); + m_audioInputsAdded = false; + m_audioOutputsAdded = false; + } + m_videoInputsAdded = false; + + bool m_videoInputsRemoved = false; + bool m_audioInputsRemoved = false; + bool m_audioOutputsRemoved = false; + + for (int i = 0; i < devices["length"].as<int>(); i++) { + + emscripten::val mediaDevice = devices[i]; + + std::string defaultDeviceLabel = ""; + + const std::string deviceKind = mediaDevice["kind"].as<std::string>(); + const std::string label = mediaDevice["label"].as<std::string>(); + const std::string deviceId = mediaDevice["deviceId"].as<std::string>(); + + qCDebug(qWasmMediaDevices) << QString::fromStdString(deviceKind) + << QString::fromStdString(deviceId) + << QString::fromStdString(label); + + if (deviceKind.empty()) + continue; + + if (deviceId == std::string("default")) { + // chrome specifies the default device with this as deviceId + // and then prepends "Default - " with the name of the device + // in the label + if (label.empty()) + continue; + + defaultDeviceLabel = label; + continue; + } + + const bool isDefault = false; // FIXME + // (defaultDeviceLabel.find(label) != std::string::npos); + + if (deviceKind == std::string("videoinput")) { + if (!m_cameraDevices.contains(deviceId)) { + QCameraDevicePrivate *camera = new QCameraDevicePrivate; // QSharedData + camera->id = QString::fromStdString(deviceId).toUtf8(); + camera->description = QString::fromUtf8(label.c_str()); + camera->isDefault = isDefault; + + m_cameraDevices.insert(deviceId, camera->create()); + m_videoInputsAdded = true; + } + cameraDevicesToRemove.removeOne(deviceId); + } else if (deviceKind == std::string("audioinput")) { + if (!m_audioInputs.contains(deviceId)) { + m_audioInputs.insert(deviceId, + (new QWasmAudioDevice(deviceId.c_str(), label.c_str(), + isDefault, QAudioDevice::Input)) + ->create()); + + m_audioInputsAdded = true; + } + audioInputsToRemove.removeOne(deviceId); + } else if (deviceKind == std::string("audiooutput")) { + if (!m_audioOutputs.contains(deviceId)) { + m_audioOutputs.insert(deviceId, + (new QWasmAudioDevice(deviceId.c_str(), label.c_str(), + isDefault, QAudioDevice::Input)) + ->create()); + + m_audioOutputsAdded = true; + } + audioOutputsToRemove.removeOne(deviceId); + } + // if permissions are given label will hold the actual + // camera name, such as "Live! Cam Sync 1080p (041e:409d)" + } + if (!m_firstInit) + getOpenALAudioDevices(); + + // any left here were removed + int j = 0; + for (; j < cameraDevicesToRemove.count(); j++) { + m_cameraDevices.remove(cameraDevicesToRemove.at(j)); + } + m_videoInputsRemoved = !cameraDevicesToRemove.isEmpty(); + + for (j = 0; j < audioInputsToRemove.count(); j++) { + m_audioInputs.remove(audioInputsToRemove.at(j)); + } + m_audioInputsRemoved = !audioInputsToRemove.isEmpty(); + + for (j = 0; j < audioOutputsToRemove.count(); j++) { + m_audioOutputs.remove(audioOutputsToRemove.at(j)); + } + m_audioOutputsRemoved = !audioOutputsToRemove.isEmpty(); + + if (m_videoInputsAdded || m_videoInputsRemoved) + emit videoInputsChanged(); + if (m_audioInputsAdded || m_audioInputsRemoved) + emit audioInputsChanged(); + if (m_audioOutputsAdded || m_audioOutputsRemoved) + emit audioOutputsChanged(); + + m_firstInit = false; + +} + void QWasmMediaDevices::getMediaDevices() { emscripten::val navigator = emscripten::val::global("navigator"); @@ -81,140 +205,44 @@ void QWasmMediaDevices::getMediaDevices() return; } - qstdweb::PromiseCallbacks enumerateDevicesCallback{ - .thenFunc = - [&](emscripten::val devices) { - if (devices.isNull() || devices.isUndefined()) { - qWarning() << "Something went wrong enumerating devices"; - return; - } - - QList<std::string> cameraDevicesToRemove = m_cameraDevices.keys(); - QList<std::string> audioInputsToRemove = m_audioInputs.keys(); - QList<std::string> audioOutputsToRemove = m_audioOutputs.keys(); - - m_videoInputsAdded = false; - m_audioInputsAdded = false; - m_audioOutputsAdded = false; - - bool m_videoInputsRemoved = false; - bool m_audioInputsRemoved = false; - bool m_audioOutputsRemoved = false; - - for (int i = 0; i < devices["length"].as<int>(); i++) { - - emscripten::val mediaDevice = devices[i]; - - std::string defaultDeviceLabel = ""; - - const std::string deviceKind = mediaDevice["kind"].as<std::string>(); - const std::string label = mediaDevice["label"].as<std::string>(); - const std::string deviceId = mediaDevice["deviceId"].as<std::string>(); - - qCDebug(qWasmMediaDevices) << QString::fromStdString(deviceKind) - << QString::fromStdString(deviceId) - << QString::fromStdString(label); - - if (deviceKind.empty()) - continue; - - if (deviceId == std::string("default")) { - // chrome specifies the default device with this as deviceId - // and then prepends "Default - " with the name of the device - // in the label - if (label.empty()) - continue; - - defaultDeviceLabel = label; - continue; - } - - const bool isDefault = - (defaultDeviceLabel.find(label) != std::string::npos); - - if (deviceKind == std::string("videoinput")) { - if (!m_cameraDevices.contains(deviceId)) { - QCameraDevicePrivate *camera = new QCameraDevicePrivate; // QSharedData - camera->id = QString::fromStdString(deviceId).toUtf8(); - camera->description = QString::fromUtf8(label.c_str()); - camera->isDefault = isDefault; - - m_cameraDevices.insert(deviceId, camera->create()); - m_videoInputsAdded = true; - } - cameraDevicesToRemove.removeOne(deviceId); - - } else if (deviceKind == std::string("audioinput")) { - if (!m_audioInputs.contains(deviceId)) { - m_audioInputs.insert(deviceId, - (new QWasmAudioDevice(deviceId.c_str(), label.c_str(), - isDefault, QAudioDevice::Input)) - ->create()); - - m_audioInputsAdded = true; - } - audioInputsToRemove.removeOne(deviceId); - } else if (deviceKind == std::string("audiooutput")) { - if (!m_audioOutputs.contains(deviceId)) { - m_audioOutputs.insert(deviceId, - (new QWasmAudioDevice(deviceId.c_str(), label.c_str(), - isDefault, QAudioDevice::Input)) - ->create()); - - m_audioOutputsAdded = true; - } - audioOutputsToRemove.removeOne(deviceId); - } - // if permissions are given label will hold the actual - // camera name, such as "Live! Cam Sync 1080p (041e:409d)" - } - - // any left here were removed - int j = 0; - for (; j < cameraDevicesToRemove.count(); j++) { - m_cameraDevices.remove(cameraDevicesToRemove.at(j)); - } - m_videoInputsRemoved = !cameraDevicesToRemove.isEmpty(); - - for (j = 0; j < audioInputsToRemove.count(); j++) { - m_audioInputs.remove(audioInputsToRemove.at(j)); - } - m_audioInputsRemoved = !audioInputsToRemove.isEmpty(); - - for (j = 0; j < audioOutputsToRemove.count(); j++) { - m_audioOutputs.remove(audioOutputsToRemove.at(j)); - } - m_audioOutputsRemoved = !audioOutputsToRemove.isEmpty(); - - if (m_videoInputsAdded || m_videoInputsRemoved) - emit videoInputsChanged(); - if (m_audioInputsAdded || m_audioInputsRemoved) - emit audioInputsChanged(); - if (m_audioOutputsAdded || m_audioOutputsRemoved) - emit audioOutputsChanged(); - - }, - .catchFunc = - [this](emscripten::val error) { - qWarning() << "mediadevices enumerateDevices fail" - << QString::fromStdString(error["name"].as<std::string>()) - << QString::fromStdString(error["message"].as<std::string>()); - m_initDone = false; - } - }; - - qstdweb::Promise::make(m_jsMediaDevicesInterface, - QStringLiteral("enumerateDevices"), - std::move(enumerateDevicesCallback)); - - // setup devicechange monitor - m_deviceChangedCallback = std::make_unique<qstdweb::EventCallback>( - m_jsMediaDevicesInterface, "devicechange", - [this, enumerateDevicesCallback](emscripten::val) { - qstdweb::Promise::make(m_jsMediaDevicesInterface, - QStringLiteral("enumerateDevices"), - std::move(enumerateDevicesCallback)); - }); + if (qstdweb::haveAsyncify()) { +#ifdef QT_HAVE_EMSCRIPTEN_ASYNCIFY + emscripten::val devicesList = m_jsMediaDevicesInterface.call<emscripten::val>("enumerateDevices").await(); + if (devicesList.isNull() || devicesList.isUndefined()) { + qWarning() << "devices list error"; + return; + } + + parseDevices(devicesList); +#endif + } else { + qstdweb::PromiseCallbacks enumerateDevicesCallback{ + .thenFunc = + [&](emscripten::val devices) { + parseDevices(devices); + }, + .catchFunc = + [this](emscripten::val error) { + qWarning() << "mediadevices enumerateDevices fail" + << QString::fromStdString(error["name"].as<std::string>()) + << QString::fromStdString(error["message"].as<std::string>()); + m_initDone = false; + } + }; + + qstdweb::Promise::make(m_jsMediaDevicesInterface, + QStringLiteral("enumerateDevices"), + std::move(enumerateDevicesCallback)); + + // setup devicechange monitor + m_deviceChangedCallback = std::make_unique<qstdweb::EventCallback>( + m_jsMediaDevicesInterface, "devicechange", + [this, enumerateDevicesCallback](emscripten::val) { + qstdweb::Promise::make(m_jsMediaDevicesInterface, + QStringLiteral("enumerateDevices"), + std::move(enumerateDevicesCallback)); + }); + } } void QWasmMediaDevices::getOpenALAudioDevices() @@ -228,6 +256,7 @@ void QWasmMediaDevices::getOpenALAudioDevices() (new QWasmAudioDevice(capture, "WebAssembly audio capture device", true, QAudioDevice::Input)) ->create()); + m_audioInputsAdded = true; emit audioInputsChanged(); } @@ -240,6 +269,7 @@ void QWasmMediaDevices::getOpenALAudioDevices() ->create()); emit audioOutputsChanged(); } + m_firstInit = true; } QT_END_NAMESPACE diff --git a/src/multimedia/wasm/qwasmmediadevices_p.h b/src/multimedia/wasm/qwasmmediadevices_p.h index 77d6ab257..b97036f97 100644 --- a/src/multimedia/wasm/qwasmmediadevices_p.h +++ b/src/multimedia/wasm/qwasmmediadevices_p.h @@ -67,6 +67,7 @@ private: void updateCameraDevices(); void getMediaDevices(); void getOpenALAudioDevices(); + void parseDevices(emscripten::val devices); QMap <std::string, QAudioDevice> m_audioOutputs; QMap <std::string, QAudioDevice> m_audioInputs; @@ -80,6 +81,7 @@ private: bool m_audioOutputsAdded = false; emscripten::val m_jsMediaDevicesInterface = emscripten::val::undefined(); bool m_initDone = false; + bool m_firstInit = false; }; QT_END_NAMESPACE |