5#include "private/qcameradevice_p.h"
6#include "private/qplatformmediaintegration_p.h"
20Q_GLOBAL_STATIC(QWasmMediaDevices, s_wasmMediaDevicesInstance);
23 : QPlatformVideoDevices(integration)
34 Q_ASSERT(QThread::isMainThread());
41 const QAudioFormat &fmt,
48 const QAudioFormat &fmt,
51 return new QWasmAudioSink(deviceInfo, fmt, parent);
66 Q_ASSERT(QThread::isMainThread());
77 return s_wasmMediaDevicesInstance();
86 getOpenALAudioDevices();
92 return m_cameraDevices.values();
97 return m_audioInputs.values();
102 return m_audioOutputs.values();
107 if (devices.isNull() || devices.isUndefined()) {
108 qWarning() <<
"Something went wrong enumerating devices";
112 QList<std::string> cameraDevicesToRemove = m_cameraDevices.keys();
113 QList<std::string> audioOutputsToRemove;
114 QList<std::string> audioInputsToRemove;
118 qWarning() <<
"m_audioInputs count" << m_audioInputs.count();
121 audioOutputsToRemove = m_audioOutputs.keys();
122 audioInputsToRemove = m_audioInputs.keys();
123 m_audioInputsAdded =
false;
124 m_audioOutputsAdded =
false;
126 m_videoInputsAdded =
false;
128 bool m_videoInputsRemoved =
false;
129 bool m_audioInputsRemoved =
false;
130 bool m_audioOutputsRemoved =
false;
132 for (
int i = 0; i < devices[
"length"].as<
int>(); i++) {
134 emscripten::val mediaDevice = devices[i];
136 const std::string deviceKind = mediaDevice[
"kind"].as<
std::string>();
137 std::string label = mediaDevice[
"label"].as<
std::string>();
138 std::string deviceId = mediaDevice[
"deviceId"].as<
std::string>();
140 qCDebug(qWasmMediaDevices) << QString::fromStdString(deviceKind)
141 << QString::fromStdString(deviceId)
142 << QString::fromStdString(label);
144 if (deviceId.empty()) {
145 label =
"System " + deviceKind;
148 if (deviceKind.empty())
150 bool isDefault =
false;
152 if (deviceKind == std::string(
"videoinput")) {
153 if (!m_cameraDevices.contains(deviceId)) {
155 camera->id = QString::fromStdString(deviceId).toUtf8();
156 camera->description = QString::fromUtf8(label.c_str());
158 camera->isDefault = !m_videoInputsAdded;
159 m_cameraDevices.insert(deviceId, camera->create());
160 m_videoInputsAdded =
true;
162 cameraDevicesToRemove.removeOne(deviceId);
163 }
else if (deviceKind == std::string(
"audioinput")) {
164 if (!m_audioInputs.contains(deviceId)) {
165 isDefault = !m_audioInputsAdded;
166 m_audioInputs.insert(
168 QAudioDevicePrivate::createQAudioDevice(std::make_unique<QWasmAudioDevice>(
169 deviceId.c_str(), label.c_str(), isDefault, QAudioDevice::Input)));
171 m_audioInputsAdded =
true;
173 audioInputsToRemove.removeOne(deviceId);
174 }
else if (deviceKind == std::string(
"audiooutput")) {
175 if (!m_audioOutputs.contains(deviceId)) {
176 isDefault = !m_audioOutputsAdded;
177 m_audioOutputs.insert(
179 QAudioDevicePrivate::createQAudioDevice(std::make_unique<QWasmAudioDevice>(
180 deviceId.c_str(), label.c_str(), isDefault, QAudioDevice::Output)));
183 m_audioOutputsAdded =
true;
185 audioOutputsToRemove.removeOne(deviceId);
191 getOpenALAudioDevices();
195 for (; j < cameraDevicesToRemove.count(); j++) {
196 m_cameraDevices.remove(cameraDevicesToRemove.at(j));
198 m_videoInputsRemoved = !cameraDevicesToRemove.isEmpty();
200 for (j = 0; j < audioInputsToRemove.count(); j++) {
201 m_audioInputs.remove(audioInputsToRemove.at(j));
203 m_audioInputsRemoved = !audioInputsToRemove.isEmpty();
205 for (j = 0; j < audioOutputsToRemove.count(); j++) {
206 m_audioOutputs.remove(audioOutputsToRemove.at(j));
208 m_audioOutputsRemoved = !audioOutputsToRemove.isEmpty();
210 if (m_videoInputsAdded || m_videoInputsRemoved) {
211 auto videoDevices =
static_cast<QWasmCameraDevices*>(QPlatformMediaIntegration::instance()->videoDevices());
212 videoDevices->onVideoInputsChanged();
214 if (m_audioInputsAdded || m_audioInputsRemoved) {
215 auto audioDevices =
static_cast<QWasmAudioDevices*>(QPlatformMediaIntegration::instance()->audioDevices());
216 audioDevices->onAudioInputsChanged();
218 if (m_audioOutputsAdded || m_audioOutputsRemoved) {
219 auto audioDevices =
static_cast<QWasmAudioDevices*>(QPlatformMediaIntegration::instance()->audioDevices());
220 audioDevices->onAudioOutputsChanged();
229 emscripten::val navigator = emscripten::val::global(
"navigator");
230 m_jsMediaDevicesInterface = navigator[
"mediaDevices"];
232 if (m_jsMediaDevicesInterface.isNull() || m_jsMediaDevicesInterface.isUndefined()) {
233 qWarning() <<
"No media devices found";
237 if (qstdweb::haveAsyncify()) {
238#ifdef QT_HAVE_EMSCRIPTEN_ASYNCIFY
239 emscripten::val devicesList = m_jsMediaDevicesInterface.call<emscripten::val>(
"enumerateDevices").await();
240 if (devicesList.isNull() || devicesList.isUndefined()) {
241 qWarning() <<
"devices list error";
245 parseDevices(devicesList);
248 qstdweb::PromiseCallbacks enumerateDevicesCallback{
250 [&](emscripten::val devices) {
251 parseDevices(devices);
254 [
this](emscripten::val error) {
255 qWarning() <<
"mediadevices enumerateDevices fail"
256 << QString::fromStdString(error[
"name"].as<std::string>())
257 << QString::fromStdString(error[
"message"].as<std::string>());
262 qstdweb::Promise::make(m_jsMediaDevicesInterface,
263 QStringLiteral(
"enumerateDevices"),
264 std::move(enumerateDevicesCallback));
267 m_deviceChangedCallback = std::make_unique<qstdweb::EventCallback>(
268 m_jsMediaDevicesInterface,
"devicechange",
269 [
this, enumerateDevicesCallback](emscripten::val) {
270 qstdweb::Promise::make(m_jsMediaDevicesInterface,
271 QStringLiteral(
"enumerateDevices"),
272 std::move(enumerateDevicesCallback));
282 auto capture = alcGetString(
nullptr, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
284 if (capture && !m_audioOutputs.contains(capture)) {
285 m_audioInputs.insert(
287 QAudioDevicePrivate::createQAudioDevice(std::make_unique<QWasmAudioDevice>(
288 capture,
"WebAssembly audio capture device",
true, QAudioDevice::Input)));
289 m_audioInputsAdded =
true;
290 auto audioDevices =
static_cast<QWasmAudioDevices*>(QPlatformMediaIntegration::instance()->audioDevices());
291 audioDevices->onAudioInputsChanged();
294 auto playback = alcGetString(
nullptr, ALC_DEFAULT_DEVICE_SPECIFIER);
296 if (playback && !m_audioOutputs.contains(capture)) {
297 m_audioOutputs.insert(
299 QAudioDevicePrivate::createQAudioDevice(std::make_unique<QWasmAudioDevice>(
300 playback,
"WebAssembly audio playback device",
true,
301 QAudioDevice::Output)));
302 auto audioDevices =
static_cast<QWasmAudioDevices*>(QPlatformMediaIntegration::instance()->audioDevices());
303 audioDevices->onAudioOutputsChanged();
The QAudioDevice class provides an information about audio devices and their functionality.
The QCameraDevice class provides general information about camera devices.
QPlatformAudioSink * createAudioSink(const QAudioDevice &, const QAudioFormat &, QObject *parent) override
QList< QAudioDevice > findAudioOutputs() const override
QList< QAudioDevice > findAudioInputs() const override
QPlatformAudioSource * createAudioSource(const QAudioDevice &, const QAudioFormat &, QObject *parent) override
void connectNotify(const QMetaMethod &signal) override
void connectNotify(const QMetaMethod &signal) override
QList< QCameraDevice > findVideoInputs() const override
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")