mirror of https://git.suyu.dev/suyu/suyu
yuzu: Hook qt camera to camera driver
parent
f19e7be6e8
commit
cc83e0a600
@ -0,0 +1,126 @@
|
||||
// Text : Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <memory>
|
||||
#include <QCameraImageCapture>
|
||||
#include <QCameraInfo>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTimer>
|
||||
|
||||
#include "input_common/drivers/camera.h"
|
||||
#include "input_common/main.h"
|
||||
#include "ui_configure_camera.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configure_camera.h"
|
||||
|
||||
ConfigureCamera::ConfigureCamera(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_)
|
||||
: QDialog(parent), input_subsystem{input_subsystem_},
|
||||
ui(std::make_unique<Ui::ConfigureCamera>()) {
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->restore_defaults_button, &QPushButton::clicked, this,
|
||||
&ConfigureCamera::RestoreDefaults);
|
||||
connect(ui->preview_button, &QPushButton::clicked, this, &ConfigureCamera::PreviewCamera);
|
||||
|
||||
auto blank_image = QImage(320, 240, QImage::Format::Format_RGB32);
|
||||
blank_image.fill(Qt::black);
|
||||
DisplayCapturedFrame(0, blank_image);
|
||||
|
||||
LoadConfiguration();
|
||||
resize(0, 0);
|
||||
}
|
||||
|
||||
ConfigureCamera::~ConfigureCamera() = default;
|
||||
|
||||
void ConfigureCamera::PreviewCamera() {
|
||||
const auto index = ui->ir_sensor_combo_box->currentIndex();
|
||||
bool camera_found = false;
|
||||
const QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
|
||||
for (const QCameraInfo& cameraInfo : cameras) {
|
||||
if (input_devices[index] == cameraInfo.deviceName().toStdString() ||
|
||||
input_devices[index] == "Auto") {
|
||||
LOG_ERROR(Frontend, "Selected Camera {} {}", cameraInfo.description().toStdString(),
|
||||
cameraInfo.deviceName().toStdString());
|
||||
camera = std::make_unique<QCamera>(cameraInfo);
|
||||
camera_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear previous frame
|
||||
auto blank_image = QImage(320, 240, QImage::Format::Format_RGB32);
|
||||
blank_image.fill(Qt::black);
|
||||
DisplayCapturedFrame(0, blank_image);
|
||||
|
||||
if (!camera_found) {
|
||||
return;
|
||||
}
|
||||
|
||||
camera_capture = std::make_unique<QCameraImageCapture>(camera.get());
|
||||
connect(camera_capture.get(), &QCameraImageCapture::imageCaptured, this,
|
||||
&ConfigureCamera::DisplayCapturedFrame);
|
||||
camera->unload();
|
||||
camera->setCaptureMode(QCamera::CaptureViewfinder);
|
||||
camera->load();
|
||||
|
||||
camera_timer = std::make_unique<QTimer>();
|
||||
connect(camera_timer.get(), &QTimer::timeout, [this] {
|
||||
camera->stop();
|
||||
camera->start();
|
||||
|
||||
camera_capture->capture();
|
||||
});
|
||||
|
||||
camera_timer->start(250);
|
||||
}
|
||||
|
||||
void ConfigureCamera::DisplayCapturedFrame(int requestId, const QImage& img) {
|
||||
LOG_ERROR(Frontend, "ImageCaptured {} {}", img.width(), img.height());
|
||||
const auto converted = img.scaled(320, 240, Qt::AspectRatioMode::IgnoreAspectRatio,
|
||||
Qt::TransformationMode::SmoothTransformation);
|
||||
ui->preview_box->setPixmap(QPixmap::fromImage(converted));
|
||||
}
|
||||
|
||||
void ConfigureCamera::changeEvent(QEvent* event) {
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
RetranslateUI();
|
||||
}
|
||||
|
||||
QDialog::changeEvent(event);
|
||||
}
|
||||
|
||||
void ConfigureCamera::RetranslateUI() {
|
||||
ui->retranslateUi(this);
|
||||
}
|
||||
|
||||
void ConfigureCamera::ApplyConfiguration() {
|
||||
const auto index = ui->ir_sensor_combo_box->currentIndex();
|
||||
Settings::values.ir_sensor_device.SetValue(input_devices[index]);
|
||||
}
|
||||
|
||||
void ConfigureCamera::LoadConfiguration() {
|
||||
input_devices.clear();
|
||||
ui->ir_sensor_combo_box->clear();
|
||||
input_devices.push_back("Auto");
|
||||
ui->ir_sensor_combo_box->addItem(tr("Auto"));
|
||||
const auto cameras = QCameraInfo::availableCameras();
|
||||
for (const QCameraInfo& cameraInfo : cameras) {
|
||||
input_devices.push_back(cameraInfo.deviceName().toStdString());
|
||||
ui->ir_sensor_combo_box->addItem(cameraInfo.description());
|
||||
}
|
||||
|
||||
const auto current_device = Settings::values.ir_sensor_device.GetValue();
|
||||
|
||||
const auto devices_it = std::find_if(
|
||||
input_devices.begin(), input_devices.end(),
|
||||
[current_device](const std::string& device) { return device == current_device; });
|
||||
const int device_index =
|
||||
devices_it != input_devices.end()
|
||||
? static_cast<int>(std::distance(input_devices.begin(), devices_it))
|
||||
: 0;
|
||||
ui->ir_sensor_combo_box->setCurrentIndex(device_index);
|
||||
}
|
||||
|
||||
void ConfigureCamera::RestoreDefaults() {
|
||||
ui->ir_sensor_combo_box->setCurrentIndex(0);
|
||||
}
|
@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ConfigureCamera</class>
|
||||
<widget class="QDialog" name="ConfigureCamera">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>298</width>
|
||||
<height>339</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Configure Infrared Camera</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>280</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select where the image of the emulated camera comes from. It may be a virtual camera or a real camera.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gridGroupBox">
|
||||
<property name="title">
|
||||
<string>Camera Image Source:</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Input device:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QComboBox" name="ir_sensor_combo_box"/>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item><item>
|
||||
<widget class="QGroupBox" name="previewBox">
|
||||
<property name="title">
|
||||
<string>Preview</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="preview_box">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>320</width>
|
||||
<height>240</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Resolution: 320*240</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="preview_button">
|
||||
<property name="text">
|
||||
<string>Click to preview</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="restore_defaults_button">
|
||||
<property name="text">
|
||||
<string>Restore Defaults</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ConfigureCamera</receiver>
|
||||
<slot>accept()</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ConfigureCamera</receiver>
|
||||
<slot>reject()</slot>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Loading…
Reference in New Issue