Qt: Support switching webcams

This commit is contained in:
Vicki Pfau 2019-03-05 17:37:21 -08:00
parent 03aed12d28
commit 1fd8b1b299
7 changed files with 76 additions and 4 deletions

View File

@ -25,6 +25,7 @@ Misc:
- Qt: Add missing HEVC NVENC option (fixes mgba.io/i/1323) - Qt: Add missing HEVC NVENC option (fixes mgba.io/i/1323)
- LR35902: Support PC-relative opcode decoding - LR35902: Support PC-relative opcode decoding
- Qt: Improve camera initialization - Qt: Improve camera initialization
- Qt: Support switching webcams
0.7.1: (2019-02-24) 0.7.1: (2019-02-24)
Bugfixes: Bugfixes:

View File

@ -15,7 +15,7 @@
#include <QTimer> #include <QTimer>
#include <QWidget> #include <QWidget>
#ifdef BUILD_QT_MULTIMEDIA #ifdef BUILD_QT_MULTIMEDIA
#include <QCamera> #include <QCameraInfo>
#include <QVideoSurfaceFormat> #include <QVideoSurfaceFormat>
#endif #endif
@ -98,6 +98,10 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren
} }
#ifdef BUILD_QT_MULTIMEDIA #ifdef BUILD_QT_MULTIMEDIA
if (image->p->m_config->getQtOption("cameraDriver").toInt() == static_cast<int>(CameraDriver::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"); QMetaObject::invokeMethod(image->p, "setupCam");
} }
#endif #endif
@ -691,6 +695,17 @@ void InputController::setCamImage(const QImage& image) {
m_image.outOfDate = true; 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() { void InputController::increaseLuminanceLevel() {
setLuminanceLevel(m_luxLevel + 1); setLuminanceLevel(m_luxLevel + 1);
} }
@ -783,3 +798,17 @@ void InputController::teardownCam() {
} }
#endif #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);
if (needsRestart) {
setupCam();
}
#endif
}

View File

@ -96,6 +96,8 @@ public:
void stealFocus(QWidget* focus); void stealFocus(QWidget* focus);
void releaseFocus(QWidget* focus); void releaseFocus(QWidget* focus);
QList<QPair<QByteArray, QString>> listCameras() const;
mRumble* rumble(); mRumble* rumble();
mRotationSource* rotationSource(); mRotationSource* rotationSource();
mImageSource* imageSource() { return &m_image; } mImageSource* imageSource() { return &m_image; }
@ -122,6 +124,8 @@ public slots:
void loadCamImage(const QString& path); void loadCamImage(const QString& path);
void setCamImage(const QImage& image); void setCamImage(const QImage& image);
void setCamera(const QByteArray& id);
private slots: private slots:
#ifdef BUILD_QT_MULTIMEDIA #ifdef BUILD_QT_MULTIMEDIA
void prepareCamSettings(QCamera::Status); void prepareCamSettings(QCamera::Status);

View File

@ -180,12 +180,22 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
m_ui.cameraDriver->addItem(tr("None (Still Image)"), static_cast<int>(InputController::CameraDriver::NONE)); 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)) { if (cameraDriver.isNull() || cameraDriver.toInt() == static_cast<int>(InputController::CameraDriver::NONE)) {
m_ui.cameraDriver->setCurrentIndex(m_ui.cameraDriver->count() - 1); m_ui.cameraDriver->setCurrentIndex(m_ui.cameraDriver->count() - 1);
m_ui.camera->setEnabled(false);
} }
#ifdef BUILD_QT_MULTIMEDIA #ifdef BUILD_QT_MULTIMEDIA
m_ui.cameraDriver->addItem(tr("Qt Multimedia"), static_cast<int>(InputController::CameraDriver::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)) { if (!cameraDriver.isNull() && cameraDriver.toInt() == static_cast<int>(InputController::CameraDriver::QT_MULTIMEDIA)) {
m_ui.cameraDriver->setCurrentIndex(m_ui.cameraDriver->count() - 1); 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 #endif
@ -442,6 +452,12 @@ void SettingsView::updateConfig() {
emit cameraDriverChanged(); 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(); 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())) { if (language != m_controller->getQtOption("language").toLocale() && !(language.bcp47Name() == QLocale::system().bcp47Name() && m_controller->getQtOption("language").isNull())) {
m_controller->setQtOption("language", language.bcp47Name()); m_controller->setQtOption("language", language.bcp47Name());

View File

@ -39,6 +39,7 @@ signals:
void audioDriverChanged(); void audioDriverChanged();
void displayDriverChanged(); void displayDriverChanged();
void cameraDriverChanged(); void cameraDriverChanged();
void cameraChanged(const QByteArray&);
void pathsChanged(); void pathsChanged();
void languageChanged(); void languageChanged();
void libraryCleared(); void libraryCleared();

View File

@ -1261,7 +1261,7 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_29"> <widget class="QLabel" name="label_29">
<property name="text"> <property name="text">
<string>Game Boy model</string> <string>Game Boy model:</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -1297,7 +1297,7 @@
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_32"> <widget class="QLabel" name="label_32">
<property name="text"> <property name="text">
<string>Super Game Boy model</string> <string>Super Game Boy model:</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -1333,7 +1333,7 @@
<item row="2" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label_33"> <widget class="QLabel" name="label_33">
<property name="text"> <property name="text">
<string>Game Boy Color model</string> <string>Game Boy Color model:</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -1672,6 +1672,26 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="0">
<widget class="QLabel" name="label_35">
<property name="text">
<string>Camera:</string>
</property>
</widget>
</item>
<item row="11" 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>
</layout> </layout>
</widget> </widget>
</widget> </widget>

View File

@ -443,6 +443,7 @@ void Window::openSettingsWindow() {
connect(settingsWindow, &SettingsView::displayDriverChanged, this, &Window::reloadDisplayDriver); connect(settingsWindow, &SettingsView::displayDriverChanged, this, &Window::reloadDisplayDriver);
connect(settingsWindow, &SettingsView::audioDriverChanged, this, &Window::reloadAudioDriver); connect(settingsWindow, &SettingsView::audioDriverChanged, this, &Window::reloadAudioDriver);
connect(settingsWindow, &SettingsView::cameraDriverChanged, this, &Window::mustRestart); 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::languageChanged, this, &Window::mustRestart);
connect(settingsWindow, &SettingsView::pathsChanged, this, &Window::reloadConfig); connect(settingsWindow, &SettingsView::pathsChanged, this, &Window::reloadConfig);
#ifdef USE_SQLITE3 #ifdef USE_SQLITE3