diff --git a/CHANGES b/CHANGES index d90561c6a..6117bcaaa 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ Bugfixes: Misc: - Qt: Add missing HEVC NVENC option (fixes mgba.io/i/1323) - Qt: Improve camera initialization + - Qt: Support switching webcams 0.7.1: (2019-02-24) Bugfixes: diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp index 8869dac82..9935626bc 100644 --- a/src/platform/qt/InputController.cpp +++ b/src/platform/qt/InputController.cpp @@ -15,7 +15,7 @@ #include #include #ifdef BUILD_QT_MULTIMEDIA -#include +#include #include #endif @@ -98,6 +98,10 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren } #ifdef BUILD_QT_MULTIMEDIA if (image->p->m_config->getQtOption("cameraDriver").toInt() == static_cast(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 @@ void InputController::setCamImage(const QImage& image) { m_image.outOfDate = true; } +QList> InputController::listCameras() const { + QList> out; +#ifdef BUILD_QT_MULTIMEDIA + QList 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(); - 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 @@ void InputController::teardownCam() { } #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(name); + connect(m_camera.get(), &QCamera::statusChanged, this, &InputController::prepareCamSettings, Qt::QueuedConnection); + if (needsRestart) { + setupCam(); + } +#endif +} diff --git a/src/platform/qt/InputController.h b/src/platform/qt/InputController.h index d15bd0e22..6418343c1 100644 --- a/src/platform/qt/InputController.h +++ b/src/platform/qt/InputController.h @@ -96,6 +96,8 @@ public: void stealFocus(QWidget* focus); void releaseFocus(QWidget* focus); + QList> listCameras() const; + mRumble* rumble(); mRotationSource* rotationSource(); mImageSource* imageSource() { return &m_image; } @@ -122,6 +124,8 @@ public slots: void loadCamImage(const QString& path); void setCamImage(const QImage& image); + void setCamera(const QByteArray& id); + private slots: #ifdef BUILD_QT_MULTIMEDIA void prepareCamSettings(QCamera::Status); diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index 07f38edf9..025f56a9f 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -178,12 +178,22 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC m_ui.cameraDriver->addItem(tr("None (Still Image)"), static_cast(InputController::CameraDriver::NONE)); if (cameraDriver.isNull() || cameraDriver.toInt() == static_cast(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(InputController::CameraDriver::QT_MULTIMEDIA)); if (!cameraDriver.isNull() && cameraDriver.toInt() == static_cast(InputController::CameraDriver::QT_MULTIMEDIA)) { m_ui.cameraDriver->setCurrentIndex(m_ui.cameraDriver->count() - 1); + m_ui.camera->setEnabled(true); + } + QList> 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 @@ -424,6 +434,12 @@ void SettingsView::updateConfig() { 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(); if (language != m_controller->getQtOption("language").toLocale() && !(language.bcp47Name() == QLocale::system().bcp47Name() && m_controller->getQtOption("language").isNull())) { m_controller->setQtOption("language", language.bcp47Name()); diff --git a/src/platform/qt/SettingsView.h b/src/platform/qt/SettingsView.h index 2be49d32d..9a97106e6 100644 --- a/src/platform/qt/SettingsView.h +++ b/src/platform/qt/SettingsView.h @@ -38,6 +38,7 @@ signals: void audioDriverChanged(); void displayDriverChanged(); void cameraDriverChanged(); + void cameraChanged(const QByteArray&); void pathsChanged(); void languageChanged(); void libraryCleared(); diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 43725c118..2d5437405 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -1210,7 +1210,7 @@ - Game Boy model + Game Boy model: @@ -1246,7 +1246,7 @@ - Super Game Boy model + Super Game Boy model: @@ -1282,7 +1282,7 @@ - Game Boy Color model + Game Boy Color model: @@ -1614,6 +1614,26 @@ + + + + Camera: + + + + + + + false + + + + 0 + 0 + + + + diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 336b78c89..a28935668 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -441,6 +441,7 @@ void Window::openSettingsWindow() { 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