Qt: Support switching webcams
@@ -15,7 +15,7 @@ #include <QApplication>
#include <QTimer> #include <QWidget> #ifdef BUILD_QT_MULTIMEDIA -#include <QCamera> +#include <QCameraInfo> #include <QVideoSurfaceFormat> #endif@@ -98,6 +98,10 @@ image->image.load(":/res/no-cam.png");
} #ifdef BUILD_QT_MULTIMEDIA if (image->p->m_config->getQtOption("cameraDriver").toInt() == static_cast<int>(CameraDriver::QT_MULTIMEDIA)) { + QByteArray camera = image->p->m_config->getQtOption("camera").toByteArray(); + if (!camera.isNull()) { + QMetaObject::invokeMethod(image->p, "setCamera", Q_ARG(QByteArray, camera)); + } QMetaObject::invokeMethod(image->p, "setupCam"); } #endif@@ -691,6 +695,17 @@ m_image.resizedImage = QImage();
m_image.outOfDate = true; } +QList<QPair<QByteArray, QString>> InputController::listCameras() const { + QList<QPair<QByteArray, QString>> out; +#ifdef BUILD_QT_MULTIMEDIA + QList<QCameraInfo> cams = QCameraInfo::availableCameras(); + for (const auto& cam : cams) { + out.append(qMakePair(cam.deviceName().toLatin1(), cam.description())); + } +#endif + return out; +} + void InputController::increaseLuminanceLevel() { setLuminanceLevel(m_luxLevel + 1); }@@ -725,7 +740,7 @@ void InputController::setupCam() {
#ifdef BUILD_QT_MULTIMEDIA if (!m_camera) { m_camera = std::make_unique<QCamera>(); - connect(m_camera.get(), &QCamera::statusChanged, this, &InputController::prepareCamSettings); + connect(m_camera.get(), &QCamera::statusChanged, this, &InputController::prepareCamSettings, Qt::QueuedConnection); } m_camera->setCaptureMode(QCamera::CaptureVideo); m_camera->setViewfinder(&m_videoDumper);@@ -783,3 +798,17 @@ m_camera->stop();
} #endif } + +void InputController::setCamera(const QByteArray& name) { +#ifdef BUILD_QT_MULTIMEDIA + bool needsRestart = false; + if (m_camera) { + needsRestart = m_camera->state() == QCamera::ActiveState; + } + m_camera = std::make_unique<QCamera>(name); + connect(m_camera.get(), &QCamera::statusChanged, this, &InputController::prepareCamSettings, Qt::QueuedConnection); + if (needsRestart) { + setupCam(); + } +#endif +}
@@ -96,6 +96,8 @@
void stealFocus(QWidget* focus); void releaseFocus(QWidget* focus); + QList<QPair<QByteArray, QString>> listCameras() const; + mRumble* rumble(); mRotationSource* rotationSource(); mImageSource* imageSource() { return &m_image; }@@ -121,6 +123,8 @@ void setLuminanceValue(uint8_t value);
void loadCamImage(const QString& path); void setCamImage(const QImage& image); + + void setCamera(const QByteArray& id); private slots: #ifdef BUILD_QT_MULTIMEDIA
@@ -178,12 +178,22 @@ QVariant cameraDriver = m_controller->getQtOption("cameraDriver");
m_ui.cameraDriver->addItem(tr("None (Still Image)"), static_cast<int>(InputController::CameraDriver::NONE)); if (cameraDriver.isNull() || cameraDriver.toInt() == static_cast<int>(InputController::CameraDriver::NONE)) { m_ui.cameraDriver->setCurrentIndex(m_ui.cameraDriver->count() - 1); + m_ui.camera->setEnabled(false); } #ifdef BUILD_QT_MULTIMEDIA m_ui.cameraDriver->addItem(tr("Qt Multimedia"), static_cast<int>(InputController::CameraDriver::QT_MULTIMEDIA)); if (!cameraDriver.isNull() && cameraDriver.toInt() == static_cast<int>(InputController::CameraDriver::QT_MULTIMEDIA)) { m_ui.cameraDriver->setCurrentIndex(m_ui.cameraDriver->count() - 1); + m_ui.camera->setEnabled(true); + } + QList<QPair<QByteArray, QString>> cameras = inputController->listCameras(); + QByteArray currentCamera = m_controller->getQtOption("camera").toByteArray(); + for (const auto& camera : cameras) { + m_ui.camera->addItem(camera.second, camera.first); + if (camera.first == currentCamera) { + m_ui.camera->setCurrentIndex(m_ui.camera->count() - 1); + } } #endif@@ -422,6 +432,12 @@ QVariant cameraDriver = m_ui.cameraDriver->itemData(m_ui.cameraDriver->currentIndex());
if (cameraDriver != m_controller->getQtOption("cameraDriver")) { m_controller->setQtOption("cameraDriver", cameraDriver); emit cameraDriverChanged(); + } + + QVariant camera = m_ui.camera->itemData(m_ui.camera->currentIndex()); + if (camera != m_controller->getQtOption("camera")) { + m_controller->setQtOption("camera", camera); + emit cameraChanged(camera.toByteArray()); } QLocale language = m_ui.languages->itemData(m_ui.languages->currentIndex()).toLocale();
@@ -38,6 +38,7 @@ void biosLoaded(int platform, const QString&);
void audioDriverChanged(); void displayDriverChanged(); void cameraDriverChanged(); + void cameraChanged(const QByteArray&); void pathsChanged(); void languageChanged(); void libraryCleared();
@@ -1210,7 +1210,7 @@ <layout class="QFormLayout" name="formLayout_1">
<item row="0" column="0"> <widget class="QLabel" name="label_29"> <property name="text"> - <string>Game Boy model</string> + <string>Game Boy model:</string> </property> </widget> </item>@@ -1246,7 +1246,7 @@ </item>
<item row="1" column="0"> <widget class="QLabel" name="label_32"> <property name="text"> - <string>Super Game Boy model</string> + <string>Super Game Boy model:</string> </property> </widget> </item>@@ -1282,7 +1282,7 @@ </item>
<item row="2" column="0"> <widget class="QLabel" name="label_33"> <property name="text"> - <string>Game Boy Color model</string> + <string>Game Boy Color model:</string> </property> </widget> </item>@@ -1611,6 +1611,26 @@ <item row="6" column="0">
<widget class="QLabel" name="label_70"> <property name="text"> <string>Default sprite colors 2:</string> + </property> + </widget> + </item> + <item row="10" column="0"> + <widget class="QLabel" name="label_35"> + <property name="text"> + <string>Camera:</string> + </property> + </widget> + </item> + <item row="10" column="1"> + <widget class="QComboBox" name="camera"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> </widget> </item>
@@ -441,6 +441,7 @@ #endif
connect(settingsWindow, &SettingsView::displayDriverChanged, this, &Window::reloadDisplayDriver); connect(settingsWindow, &SettingsView::audioDriverChanged, this, &Window::reloadAudioDriver); connect(settingsWindow, &SettingsView::cameraDriverChanged, this, &Window::mustRestart); + connect(settingsWindow, &SettingsView::cameraChanged, &m_inputController, &InputController::setCamera); connect(settingsWindow, &SettingsView::languageChanged, this, &Window::mustRestart); connect(settingsWindow, &SettingsView::pathsChanged, this, &Window::reloadConfig); #ifdef USE_SQLITE3