From 5ebd4668690c9e51ae80342d5e43bccac2339c1d Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Sun, 20 May 2018 09:07:37 +0800 Subject: [PATCH 1/7] camera: Add camera flip config --- src/citra/config.cpp | 6 + src/citra/default_ini.h | 6 + src/citra_qt/camera/qt_camera_factory.cpp | 6 +- src/citra_qt/camera/qt_camera_factory.h | 4 +- src/citra_qt/camera/qt_multimedia_camera.cpp | 14 +- src/citra_qt/camera/qt_multimedia_camera.h | 6 +- src/citra_qt/camera/still_image_camera.cpp | 16 +- src/citra_qt/camera/still_image_camera.h | 6 +- src/citra_qt/configuration/config.cpp | 8 + .../configuration/configure_camera.cpp | 23 +- src/citra_qt/configuration/configure_camera.h | 1 + .../configuration/configure_camera.ui | 572 ++++++++++-------- src/core/frontend/camera/factory.cpp | 9 +- src/core/frontend/camera/factory.h | 15 +- src/core/hle/service/cam/cam.cpp | 5 +- src/core/settings.h | 1 + 16 files changed, 416 insertions(+), 282 deletions(-) diff --git a/src/citra/config.cpp b/src/citra/config.cpp index b4e3a2ce9..ce51b687b 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -155,14 +155,20 @@ void Config::ReadValues() { sdl2_config->Get("Camera", "camera_outer_right_name", "blank"); Settings::values.camera_config[OuterRightCamera] = sdl2_config->Get("Camera", "camera_outer_right_config", ""); + Settings::values.camera_flip[OuterRightCamera] = + sdl2_config->GetInteger("Camera", "camera_outer_right_flip", 0); Settings::values.camera_name[InnerCamera] = sdl2_config->Get("Camera", "camera_inner_name", "blank"); Settings::values.camera_config[InnerCamera] = sdl2_config->Get("Camera", "camera_inner_config", ""); + Settings::values.camera_flip[InnerCamera] = + sdl2_config->GetInteger("Camera", "camera_inner_flip", 0); Settings::values.camera_name[OuterLeftCamera] = sdl2_config->Get("Camera", "camera_outer_left_name", "blank"); Settings::values.camera_config[OuterLeftCamera] = sdl2_config->Get("Camera", "camera_outer_left_config", ""); + Settings::values.camera_flip[OuterLeftCamera] = + sdl2_config->GetInteger("Camera", "camera_outer_left_flip", 0); // Miscellaneous Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Info"); diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index 7179d6f94..4a17eb6ca 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -178,13 +178,19 @@ camera_outer_right_name = # A config string for the right outer camera. Its meaning is defined by the camera engine camera_outer_right_config = +# The image flip to apply +# 0: None (default), 1: Horizontal, 2: Vertical, 3: Reverse +camera_outer_right_flip = + # ... for the left outer camera camera_outer_left_name = camera_outer_left_config = +camera_outer_left_flip = # ... for the inner camera camera_inner_name = camera_inner_config = +camera_inner_flip = [Miscellaneous] # A filter which removes logs below a certain logging level. diff --git a/src/citra_qt/camera/qt_camera_factory.cpp b/src/citra_qt/camera/qt_camera_factory.cpp index fa78591ba..063a600df 100644 --- a/src/citra_qt/camera/qt_camera_factory.cpp +++ b/src/citra_qt/camera/qt_camera_factory.cpp @@ -7,9 +7,9 @@ namespace Camera { -std::unique_ptr QtCameraFactory::CreatePreview(const std::string& config, - int width, int height) const { - std::unique_ptr camera = Create(config); +std::unique_ptr QtCameraFactory::CreatePreview( + const std::string& config, int width, int height, const Service::CAM::Flip& flip) const { + std::unique_ptr camera = Create(config, flip); if (camera->IsPreviewAvailable()) { return camera; diff --git a/src/citra_qt/camera/qt_camera_factory.h b/src/citra_qt/camera/qt_camera_factory.h index 7efc21b58..9e590ca66 100644 --- a/src/citra_qt/camera/qt_camera_factory.h +++ b/src/citra_qt/camera/qt_camera_factory.h @@ -11,8 +11,8 @@ namespace Camera { // Base class for camera factories of citra_qt class QtCameraFactory : public CameraFactory { - std::unique_ptr CreatePreview(const std::string& config, int width, - int height) const override; + std::unique_ptr CreatePreview(const std::string& config, int width, int height, + const Service::CAM::Flip& flip) const override; }; } // namespace Camera diff --git a/src/citra_qt/camera/qt_multimedia_camera.cpp b/src/citra_qt/camera/qt_multimedia_camera.cpp index 6c2668df6..5f2137835 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.cpp +++ b/src/citra_qt/camera/qt_multimedia_camera.cpp @@ -46,7 +46,8 @@ bool QtCameraSurface::present(const QVideoFrame& frame) { return true; } -QtMultimediaCamera::QtMultimediaCamera(const std::string& camera_name) +QtMultimediaCamera::QtMultimediaCamera(const std::string& camera_name, + const Service::CAM::Flip& flip) : handler(QtMultimediaCameraHandler::GetHandler()) { if (handler->thread() == QThread::currentThread()) { handler->CreateCamera(camera_name); @@ -54,6 +55,9 @@ QtMultimediaCamera::QtMultimediaCamera(const std::string& camera_name) QMetaObject::invokeMethod(handler.get(), "CreateCamera", Qt::BlockingQueuedConnection, Q_ARG(const std::string&, camera_name)); } + using namespace Service::CAM; + flip_horizontal = basic_flip_horizontal = (flip == Flip::Horizontal) || (flip == Flip::Reverse); + flip_vertical = basic_flip_vertical = (flip == Flip::Vertical) || (flip == Flip::Reverse); } QtMultimediaCamera::~QtMultimediaCamera() { @@ -107,8 +111,8 @@ void QtMultimediaCamera::SetResolution(const Service::CAM::Resolution& resolutio void QtMultimediaCamera::SetFlip(Service::CAM::Flip flip) { using namespace Service::CAM; - flip_horizontal = (flip == Flip::Horizontal) || (flip == Flip::Reverse); - flip_vertical = (flip == Flip::Vertical) || (flip == Flip::Reverse); + flip_horizontal = basic_flip_horizontal ^ (flip == Flip::Horizontal || flip == Flip::Reverse); + flip_vertical = basic_flip_vertical ^ (flip == Flip::Vertical || flip == Flip::Reverse); } void QtMultimediaCamera::SetEffect(Service::CAM::Effect effect) { @@ -128,8 +132,8 @@ bool QtMultimediaCamera::IsPreviewAvailable() { } std::unique_ptr QtMultimediaCameraFactory::Create( - const std::string& config) const { - return std::make_unique(config); + const std::string& config, const Service::CAM::Flip& flip) const { + return std::make_unique(config, flip); } std::array, 3> QtMultimediaCameraHandler::handlers; diff --git a/src/citra_qt/camera/qt_multimedia_camera.h b/src/citra_qt/camera/qt_multimedia_camera.h index 103aff8a0..580834275 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.h +++ b/src/citra_qt/camera/qt_multimedia_camera.h @@ -38,7 +38,7 @@ class QtMultimediaCameraHandler; /// This class is only an interface. It just calls QtMultimediaCameraHandler. class QtMultimediaCamera final : public CameraInterface { public: - QtMultimediaCamera(const std::string& camera_name); + QtMultimediaCamera(const std::string& camera_name, const Service::CAM::Flip& flip); ~QtMultimediaCamera(); void StartCapture() override; void StopCapture() override; @@ -55,11 +55,13 @@ private: int width, height; bool output_rgb; bool flip_horizontal, flip_vertical; + bool basic_flip_horizontal, basic_flip_vertical; }; class QtMultimediaCameraFactory final : public QtCameraFactory { public: - std::unique_ptr Create(const std::string& config) const override; + std::unique_ptr Create(const std::string& config, + const Service::CAM::Flip& flip) const override; }; class QtMultimediaCameraHandler final : public QObject { diff --git a/src/citra_qt/camera/still_image_camera.cpp b/src/citra_qt/camera/still_image_camera.cpp index ab0d18308..7e54fad3e 100644 --- a/src/citra_qt/camera/still_image_camera.cpp +++ b/src/citra_qt/camera/still_image_camera.cpp @@ -9,7 +9,12 @@ namespace Camera { -StillImageCamera::StillImageCamera(QImage image_) : image(std::move(image_)) {} +StillImageCamera::StillImageCamera(QImage image_, const Service::CAM::Flip& flip) + : image(std::move(image_)) { + using namespace Service::CAM; + flip_horizontal = basic_flip_horizontal = (flip == Flip::Horizontal) || (flip == Flip::Reverse); + flip_vertical = basic_flip_vertical = (flip == Flip::Vertical) || (flip == Flip::Reverse); +} void StillImageCamera::StartCapture() {} @@ -26,8 +31,8 @@ void StillImageCamera::SetResolution(const Service::CAM::Resolution& resolution) void StillImageCamera::SetFlip(Service::CAM::Flip flip) { using namespace Service::CAM; - flip_horizontal = (flip == Flip::Horizontal) || (flip == Flip::Reverse); - flip_vertical = (flip == Flip::Vertical) || (flip == Flip::Reverse); + flip_horizontal = basic_flip_horizontal ^ (flip == Flip::Horizontal || flip == Flip::Reverse); + flip_vertical = basic_flip_vertical ^ (flip == Flip::Vertical || flip == Flip::Reverse); } void StillImageCamera::SetEffect(Service::CAM::Effect effect) { @@ -58,7 +63,8 @@ const std::string StillImageCameraFactory::getFilePath() { .toStdString(); } -std::unique_ptr StillImageCameraFactory::Create(const std::string& config) const { +std::unique_ptr StillImageCameraFactory::Create( + const std::string& config, const Service::CAM::Flip& flip) const { std::string real_config = config; if (config.empty()) { real_config = getFilePath(); @@ -67,7 +73,7 @@ std::unique_ptr StillImageCameraFactory::Create(const std::stri if (image.isNull()) { NGLOG_ERROR(Service_CAM, "Couldn't load image \"{}\"", real_config.c_str()); } - return std::make_unique(image); + return std::make_unique(image, flip); } } // namespace Camera diff --git a/src/citra_qt/camera/still_image_camera.h b/src/citra_qt/camera/still_image_camera.h index c54d367e8..e9016981b 100644 --- a/src/citra_qt/camera/still_image_camera.h +++ b/src/citra_qt/camera/still_image_camera.h @@ -14,7 +14,7 @@ namespace Camera { class StillImageCamera final : public CameraInterface { public: - StillImageCamera(QImage image); + StillImageCamera(QImage image, const Service::CAM::Flip& flip); void StartCapture() override; void StopCapture() override; void SetResolution(const Service::CAM::Resolution&) override; @@ -30,11 +30,13 @@ private: int width, height; bool output_rgb; bool flip_horizontal, flip_vertical; + bool basic_flip_horizontal, basic_flip_vertical; }; class StillImageCameraFactory final : public QtCameraFactory { public: - std::unique_ptr Create(const std::string& config) const override; + std::unique_ptr Create(const std::string& config, + const Service::CAM::Flip& flip) const override; private: static const std::string getFilePath(); diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index bdb296659..e5d252c81 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -128,14 +128,19 @@ void Config::ReadValues() { qt_config->value("camera_outer_right_name", "blank").toString().toStdString(); Settings::values.camera_config[OuterRightCamera] = qt_config->value("camera_outer_right_config", "").toString().toStdString(); + Settings::values.camera_flip[OuterRightCamera] = + qt_config->value("camera_outer_right_flip", "0").toInt(); Settings::values.camera_name[InnerCamera] = qt_config->value("camera_inner_name", "blank").toString().toStdString(); Settings::values.camera_config[InnerCamera] = qt_config->value("camera_inner_config", "").toString().toStdString(); + Settings::values.camera_flip[InnerCamera] = qt_config->value("camera_inner_flip", "").toInt(); Settings::values.camera_name[OuterLeftCamera] = qt_config->value("camera_outer_left_name", "blank").toString().toStdString(); Settings::values.camera_config[OuterLeftCamera] = qt_config->value("camera_outer_left_config", "").toString().toStdString(); + Settings::values.camera_flip[OuterLeftCamera] = + qt_config->value("camera_outer_left_flip", "").toInt(); qt_config->endGroup(); qt_config->beginGroup("Data Storage"); @@ -317,14 +322,17 @@ void Config::SaveValues() { QString::fromStdString(Settings::values.camera_name[OuterRightCamera])); qt_config->setValue("camera_outer_right_config", QString::fromStdString(Settings::values.camera_config[OuterRightCamera])); + qt_config->setValue("camera_outer_right_flip", Settings::values.camera_flip[OuterRightCamera]); qt_config->setValue("camera_inner_name", QString::fromStdString(Settings::values.camera_name[InnerCamera])); qt_config->setValue("camera_inner_config", QString::fromStdString(Settings::values.camera_config[InnerCamera])); + qt_config->setValue("camera_inner_flip", Settings::values.camera_flip[InnerCamera]); qt_config->setValue("camera_outer_left_name", QString::fromStdString(Settings::values.camera_name[OuterLeftCamera])); qt_config->setValue("camera_outer_left_config", QString::fromStdString(Settings::values.camera_config[OuterLeftCamera])); + qt_config->setValue("camera_outer_left_flip", Settings::values.camera_flip[OuterLeftCamera]); qt_config->endGroup(); qt_config->beginGroup("Data Storage"); diff --git a/src/citra_qt/configuration/configure_camera.cpp b/src/citra_qt/configuration/configure_camera.cpp index ca6db4623..e9d964b3a 100644 --- a/src/citra_qt/configuration/configure_camera.cpp +++ b/src/citra_qt/configuration/configure_camera.cpp @@ -27,14 +27,7 @@ ConfigureCamera::ConfigureCamera(QWidget* parent) // Load settings camera_name = Settings::values.camera_name; camera_config = Settings::values.camera_config; - for (auto&& item : camera_name) { - if (item == "opencv") { - QMessageBox::critical(this, tr("Error"), - tr("Sorry, Citra has removed support for OpenCV cameras.\n\nYour " - "existing OpenCV cameras have been replaced with Blank.")); - item = "blank"; - } - } + camera_flip = Settings::values.camera_flip; QList cameras = QCameraInfo::availableCameras(); for (const QCameraInfo& cameraInfo : cameras) { ui->system_camera->addItem(cameraInfo.deviceName()); @@ -98,6 +91,8 @@ void ConfigureCamera::connectEvents() { connect(ui->system_camera, static_cast(&QComboBox::currentIndexChanged), this, [=] { stopPreviewing(); }); + connect(ui->camera_flip, static_cast(&QComboBox::currentIndexChanged), + this, [=] { stopPreviewing(); }); } void ConfigureCamera::updateCameraMode() { @@ -148,6 +143,8 @@ void ConfigureCamera::updateImageSourceUI() { } ui->system_camera_label->setHidden(image_source != 2); ui->system_camera->setHidden(image_source != 2); + ui->camera_flip_label->setHidden(image_source == 0); + ui->camera_flip->setHidden(image_source == 0); } void ConfigureCamera::recordConfig() { @@ -166,10 +163,12 @@ void ConfigureCamera::recordConfig() { if (current_selected == CameraPosition::RearBoth) { camera_name[0] = camera_name[2] = implementation; camera_config[0] = camera_config[2] = config; + camera_flip[0] = camera_flip[2] = ui->camera_flip->currentIndex(); } else if (current_selected != CameraPosition::Null) { int index = static_cast(current_selected); camera_name[index] = implementation; camera_config[index] = config; + camera_flip[index] = ui->camera_flip->currentIndex(); } current_selected = getCameraSelection(); } @@ -187,9 +186,9 @@ void ConfigureCamera::startPreviewing() { ui->preview_box->setToolTip(tr("Resolution: ") + QString::number(preview_width) + "*" + QString::number(preview_height)); // Load previewing camera - previewing_camera = - Camera::CreateCameraPreview(camera_name[camera_selection], camera_config[camera_selection], - preview_width, preview_height); + previewing_camera = Camera::CreateCameraPreview( + camera_name[camera_selection], camera_config[camera_selection], preview_width, + preview_height, static_cast(camera_flip[camera_selection])); if (!previewing_camera) { stopPreviewing(); return; @@ -262,6 +261,7 @@ void ConfigureCamera::setConfiguration() { } else { ui->camera_file->setText(QString::fromStdString(camera_config[index])); } + ui->camera_flip->setCurrentIndex(camera_flip[index]); updateImageSourceUI(); } @@ -288,6 +288,7 @@ void ConfigureCamera::applyConfiguration() { stopPreviewing(); Settings::values.camera_name = camera_name; Settings::values.camera_config = camera_config; + Settings::values.camera_flip = camera_flip; Settings::Apply(); } diff --git a/src/citra_qt/configuration/configure_camera.h b/src/citra_qt/configuration/configure_camera.h index 5621de7ef..0aa55996e 100644 --- a/src/citra_qt/configuration/configure_camera.h +++ b/src/citra_qt/configuration/configure_camera.h @@ -47,6 +47,7 @@ private: std::unique_ptr ui; std::array camera_name; std::array camera_config; + std::array camera_flip; int timer_id = 0; int preview_width = 0; int preview_height = 0; diff --git a/src/citra_qt/configuration/configure_camera.ui b/src/citra_qt/configuration/configure_camera.ui index cd4d2e108..46c56b266 100644 --- a/src/citra_qt/configuration/configure_camera.ui +++ b/src/citra_qt/configuration/configure_camera.ui @@ -1,257 +1,347 @@ - - ConfigureCamera - - + ConfigureCamera + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + Camera + + - - - Camera + + + + + Select the camera to configure - - - - - - - Select the camera to configure - - - Camera to configure: - - - - - - - Select the camera to configure - - - - Front - - - - - Rear - - - - - - - - - - - - Select the camera mode (single or double) - - - Camera mode: - - - - - - - Select the camera mode (single or double) - - - - Single (2D) - - - - - Double (3D) - - - - - - - - - - - - Select the position of camera to configure - - - Camera position: - - - - - - - Select the position of camera to configure - - - - Left - - - - - Right - - - - - - - - + + Camera to configure: + + + + + + + Select the camera to configure + + + + Front + + + + + Rear + + + + + - - - Configuration + + + + + Select the camera mode (single or double) - - - - - - - Select where the image of the emulated camera comes from. It may be an image or a real camera. - - - Camera Image Source: - - - - - - - Select where the image of the emulated camera come from. It may be an image or a real camera. - - - - Blank (blank) - - - - - Still Image (image) - - - - - System Camera (qt) - - - - - - - - - - - - QFrame::NoFrame - - - File: - - - - - - - - - - ... - - - - - - - - - - - QFrame::NoFrame - - - Camera: - - - - - - - - <Default> - - - - - - - - - - Prompt before load - - - - - + + Camera mode: + + + + + + + Select the camera mode (single or double) + + + + Single (2D) + + + + + Double (3D) + + + + + - - - Preview + + + + + Select the position of camera to configure - - - - - - 512 - 384 - - - - Resolution: 512*384 - - - - - - - - - - Click to preview - - - - - + + Camera position: + + + + + + + Select the position of camera to configure + + + + Left + + + + + Right + + + + + + + + + + + + + Configuration + + + + + + + + Select where the image of the emulated camera comes from. It may be an image or a real camera. + + + Camera Image Source: + + + + + + + Select where the image of the emulated camera comes from. It may be an image or a real camera. + + + + Blank (blank) + + + + + Still Image (image) + + + + + System Camera (qt) + + + + + - - - Qt::Vertical + + + + + QFrame::NoFrame - - - 20 - 40 - + + File: - + + + + + + + + + ... + + + + - - - - + + + + + + QFrame::NoFrame + + + Select the system camera to use + + + Camera: + + + + + + + + 0 + 0 + + + + + 250 + 16777215 + + + + Select the system camera to use + + + + <Default> + + + + + + + + + + + + QFrame::NoFrame + + + Select the image flip to apply + + + Flip: + + + + + + + true + + + + 0 + 0 + + + + + 800 + 16777215 + + + + Select the image flip to apply + + + + None + + + + + Horizontal + + + + + Vertical + + + + + Reverse + + + + + + + + + + Select an image file every time before the camera is loaded + + + Prompt before load + + + + + + + + + + Preview + + + + + + + 512 + 384 + + + + Resolution: 512*384 + + + + + + + + + + Click to preview + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + diff --git a/src/core/frontend/camera/factory.cpp b/src/core/frontend/camera/factory.cpp index f0434cdad..2a871196c 100644 --- a/src/core/frontend/camera/factory.cpp +++ b/src/core/frontend/camera/factory.cpp @@ -17,10 +17,11 @@ void RegisterFactory(const std::string& name, std::unique_ptr fac factories[name] = std::move(factory); } -std::unique_ptr CreateCamera(const std::string& name, const std::string& config) { +std::unique_ptr CreateCamera(const std::string& name, const std::string& config, + const Service::CAM::Flip& flip) { auto pair = factories.find(name); if (pair != factories.end()) { - return pair->second->Create(config); + return pair->second->Create(config, flip); } if (name != "blank") { @@ -31,10 +32,10 @@ std::unique_ptr CreateCamera(const std::string& name, const std std::unique_ptr CreateCameraPreview(const std::string& name, const std::string& config, int width, - int height) { + int height, const Service::CAM::Flip& flip) { auto pair = factories.find(name); if (pair != factories.end()) { - return pair->second->CreatePreview(config, width, height); + return pair->second->CreatePreview(config, width, height, flip); } if (name != "blank") { diff --git a/src/core/frontend/camera/factory.h b/src/core/frontend/camera/factory.h index 840be7022..2c4ab1479 100644 --- a/src/core/frontend/camera/factory.h +++ b/src/core/frontend/camera/factory.h @@ -18,22 +18,26 @@ public: * Creates a camera object based on the configuration string. * @param config Configuration string to create the camera. The implementation can decide the * meaning of this string. + * @param flip The image flip to apply * @returns a unique_ptr to the created camera object. */ - virtual std::unique_ptr Create(const std::string& config) const = 0; + virtual std::unique_ptr Create(const std::string& config, + const Service::CAM::Flip& flip) const = 0; /** * Creates a camera object for preview based on the configuration string. * @param config Configuration string to create the camera. The implementation can decide the * meaning of this string. + * @param flip The image flip to apply * @returns a unique_ptr to the created camera object. * Note: The default implementation for this is to call Create(). Derived classes may have other * Implementations. For example, A dialog may be used instead of LOG_ERROR when error * occurs. */ virtual std::unique_ptr CreatePreview(const std::string& config, int width, - int height) const { - return Create(config); + int height, + const Service::CAM::Flip& flip) const { + return Create(config, flip); } }; @@ -50,7 +54,8 @@ void RegisterFactory(const std::string& name, std::unique_ptr fac * @param config Configuration string to create the camera. The meaning of this string is * defined by the factory. */ -std::unique_ptr CreateCamera(const std::string& name, const std::string& config); +std::unique_ptr CreateCamera(const std::string& name, const std::string& config, + const Service::CAM::Flip& flip); /** * Creates a camera from the factory for previewing. @@ -60,6 +65,6 @@ std::unique_ptr CreateCamera(const std::string& name, const std */ std::unique_ptr CreateCameraPreview(const std::string& name, const std::string& config, int width, - int height); + int height, const Service::CAM::Flip& flip); } // namespace Camera diff --git a/src/core/hle/service/cam/cam.cpp b/src/core/hle/service/cam/cam.cpp index 3328dcf8e..78cdb23e8 100644 --- a/src/core/hle/service/cam/cam.cpp +++ b/src/core/hle/service/cam/cam.cpp @@ -1041,8 +1041,9 @@ void Module::ReloadCameraDevices() { } void Module::LoadCameraImplementation(CameraConfig& camera, int camera_id) { - camera.impl = Camera::CreateCamera(Settings::values.camera_name[camera_id], - Settings::values.camera_config[camera_id]); + camera.impl = Camera::CreateCamera( + Settings::values.camera_name[camera_id], Settings::values.camera_config[camera_id], + static_cast(Settings::values.camera_flip[camera_id])); camera.impl->SetFlip(camera.contexts[0].flip); camera.impl->SetEffect(camera.contexts[0].effect); camera.impl->SetFormat(camera.contexts[0].format); diff --git a/src/core/settings.h b/src/core/settings.h index b57a1cbed..5ce4811af 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -140,6 +140,7 @@ struct Values { // Camera std::array camera_name; std::array camera_config; + std::array camera_flip; // Debugging bool use_gdbstub; From 6e410dcef55d55a40305baa574ace61d5f7fe86b Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Sat, 26 May 2018 11:26:58 +0800 Subject: [PATCH 2/7] camera: refactor (add qt_camera_base) --- src/citra_qt/CMakeLists.txt | 4 +- src/citra_qt/camera/qt_camera_base.cpp | 57 ++++++++++++++++++++ src/citra_qt/camera/qt_camera_base.h | 36 +++++++++++++ src/citra_qt/camera/qt_camera_factory.cpp | 24 --------- src/citra_qt/camera/qt_camera_factory.h | 18 ------- src/citra_qt/camera/qt_multimedia_camera.cpp | 31 ++--------- src/citra_qt/camera/qt_multimedia_camera.h | 14 ++--- src/citra_qt/camera/still_image_camera.cpp | 32 ++--------- src/citra_qt/camera/still_image_camera.h | 14 ++--- 9 files changed, 107 insertions(+), 123 deletions(-) create mode 100644 src/citra_qt/camera/qt_camera_base.cpp create mode 100644 src/citra_qt/camera/qt_camera_base.h delete mode 100644 src/citra_qt/camera/qt_camera_factory.cpp delete mode 100644 src/citra_qt/camera/qt_camera_factory.h diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index 4e0fcdbeb..7b0d0eaac 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -13,8 +13,8 @@ add_executable(citra-qt camera/camera_util.h camera/still_image_camera.cpp camera/still_image_camera.h - camera/qt_camera_factory.cpp - camera/qt_camera_factory.h + camera/qt_camera_base.cpp + camera/qt_camera_base.h camera/qt_multimedia_camera.cpp camera/qt_multimedia_camera.h citra-qt.rc diff --git a/src/citra_qt/camera/qt_camera_base.cpp b/src/citra_qt/camera/qt_camera_base.cpp new file mode 100644 index 000000000..65bf2361c --- /dev/null +++ b/src/citra_qt/camera/qt_camera_base.cpp @@ -0,0 +1,57 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include "citra_qt/camera/camera_util.h" +#include "citra_qt/camera/qt_camera_base.h" + +namespace Camera { + +QtCameraInterface::QtCameraInterface(const Service::CAM::Flip& flip) { + using namespace Service::CAM; + flip_horizontal = basic_flip_horizontal = (flip == Flip::Horizontal) || (flip == Flip::Reverse); + flip_vertical = basic_flip_vertical = (flip == Flip::Vertical) || (flip == Flip::Reverse); +} + +void QtCameraInterface::SetFormat(Service::CAM::OutputFormat output_format) { + output_rgb = output_format == Service::CAM::OutputFormat::RGB565; +} + +void QtCameraInterface::SetResolution(const Service::CAM::Resolution& resolution) { + width = resolution.width; + height = resolution.height; +} + +void QtCameraInterface::SetFlip(Service::CAM::Flip flip) { + using namespace Service::CAM; + flip_horizontal = basic_flip_horizontal ^ (flip == Flip::Horizontal || flip == Flip::Reverse); + flip_vertical = basic_flip_vertical ^ (flip == Flip::Vertical || flip == Flip::Reverse); +} + +void QtCameraInterface::SetEffect(Service::CAM::Effect effect) { + if (effect != Service::CAM::Effect::None) { + NGLOG_ERROR(Service_CAM, "Unimplemented effect {}", static_cast(effect)); + } +} + +std::vector QtCameraInterface::ReceiveFrame() { + return CameraUtil::ProcessImage(QtReceiveFrame(), width, height, output_rgb, flip_horizontal, + flip_vertical); +} + +std::unique_ptr QtCameraFactory::CreatePreview( + const std::string& config, int width, int height, const Service::CAM::Flip& flip) const { + std::unique_ptr camera = Create(config, flip); + + if (camera->IsPreviewAvailable()) { + return camera; + } + QMessageBox::critical( + nullptr, QObject::tr("Error"), + (config.empty() ? QObject::tr("Couldn't load the camera") + : QObject::tr("Couldn't load %1").arg(QString::fromStdString(config)))); + return nullptr; +} + +} // namespace Camera diff --git a/src/citra_qt/camera/qt_camera_base.h b/src/citra_qt/camera/qt_camera_base.h new file mode 100644 index 000000000..e66c3bb46 --- /dev/null +++ b/src/citra_qt/camera/qt_camera_base.h @@ -0,0 +1,36 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "core/frontend/camera/factory.h" + +namespace Camera { + +// Base class for camera interfaces of citra_qt +class QtCameraInterface : public CameraInterface { +public: + QtCameraInterface(const Service::CAM::Flip& flip); + void SetResolution(const Service::CAM::Resolution&) override; + void SetFlip(Service::CAM::Flip) override; + void SetEffect(Service::CAM::Effect) override; + void SetFormat(Service::CAM::OutputFormat) override; + std::vector ReceiveFrame() override; + virtual QImage QtReceiveFrame() = 0; + +private: + int width, height; + bool output_rgb; + bool flip_horizontal, flip_vertical; + bool basic_flip_horizontal, basic_flip_vertical; +}; + +// Base class for camera factories of citra_qt +class QtCameraFactory : public CameraFactory { + std::unique_ptr CreatePreview(const std::string& config, int width, int height, + const Service::CAM::Flip& flip) const override; +}; + +} // namespace Camera diff --git a/src/citra_qt/camera/qt_camera_factory.cpp b/src/citra_qt/camera/qt_camera_factory.cpp deleted file mode 100644 index 063a600df..000000000 --- a/src/citra_qt/camera/qt_camera_factory.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2018 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include "citra_qt/camera/qt_camera_factory.h" - -namespace Camera { - -std::unique_ptr QtCameraFactory::CreatePreview( - const std::string& config, int width, int height, const Service::CAM::Flip& flip) const { - std::unique_ptr camera = Create(config, flip); - - if (camera->IsPreviewAvailable()) { - return camera; - } - QMessageBox::critical( - nullptr, QObject::tr("Error"), - (config.empty() ? QObject::tr("Couldn't load the camera") - : QObject::tr("Couldn't load %1").arg(QString::fromStdString(config)))); - return nullptr; -} - -} // namespace Camera diff --git a/src/citra_qt/camera/qt_camera_factory.h b/src/citra_qt/camera/qt_camera_factory.h deleted file mode 100644 index 9e590ca66..000000000 --- a/src/citra_qt/camera/qt_camera_factory.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2018 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include "core/frontend/camera/factory.h" - -namespace Camera { - -// Base class for camera factories of citra_qt -class QtCameraFactory : public CameraFactory { - std::unique_ptr CreatePreview(const std::string& config, int width, int height, - const Service::CAM::Flip& flip) const override; -}; - -} // namespace Camera diff --git a/src/citra_qt/camera/qt_multimedia_camera.cpp b/src/citra_qt/camera/qt_multimedia_camera.cpp index 5f2137835..abf2ff25e 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.cpp +++ b/src/citra_qt/camera/qt_multimedia_camera.cpp @@ -48,16 +48,13 @@ bool QtCameraSurface::present(const QVideoFrame& frame) { QtMultimediaCamera::QtMultimediaCamera(const std::string& camera_name, const Service::CAM::Flip& flip) - : handler(QtMultimediaCameraHandler::GetHandler()) { + : QtCameraInterface(flip), handler(QtMultimediaCameraHandler::GetHandler()) { if (handler->thread() == QThread::currentThread()) { handler->CreateCamera(camera_name); } else { QMetaObject::invokeMethod(handler.get(), "CreateCamera", Qt::BlockingQueuedConnection, Q_ARG(const std::string&, camera_name)); } - using namespace Service::CAM; - flip_horizontal = basic_flip_horizontal = (flip == Flip::Horizontal) || (flip == Flip::Reverse); - flip_vertical = basic_flip_vertical = (flip == Flip::Vertical) || (flip == Flip::Reverse); } QtMultimediaCamera::~QtMultimediaCamera() { @@ -77,10 +74,6 @@ void QtMultimediaCamera::StopCapture() { handler->StopCamera(); } -void QtMultimediaCamera::SetFormat(Service::CAM::OutputFormat output_format) { - output_rgb = output_format == Service::CAM::OutputFormat::RGB565; -} - void QtMultimediaCamera::SetFrameRate(Service::CAM::FrameRate frame_rate) { const std::array FrameRateList = { /* Rate_15 */ QCamera::FrameRateRange(15, 15), @@ -104,27 +97,9 @@ void QtMultimediaCamera::SetFrameRate(Service::CAM::FrameRate frame_rate) { handler->settings.setMinimumFrameRate(framerate.maximumFrameRate); } -void QtMultimediaCamera::SetResolution(const Service::CAM::Resolution& resolution) { - width = resolution.width; - height = resolution.height; -} - -void QtMultimediaCamera::SetFlip(Service::CAM::Flip flip) { - using namespace Service::CAM; - flip_horizontal = basic_flip_horizontal ^ (flip == Flip::Horizontal || flip == Flip::Reverse); - flip_vertical = basic_flip_vertical ^ (flip == Flip::Vertical || flip == Flip::Reverse); -} - -void QtMultimediaCamera::SetEffect(Service::CAM::Effect effect) { - if (effect != Service::CAM::Effect::None) { - NGLOG_ERROR(Service_CAM, "Unimplemented effect {}", static_cast(effect)); - } -} - -std::vector QtMultimediaCamera::ReceiveFrame() { +QImage QtMultimediaCamera::QtReceiveFrame() { QMutexLocker locker(&handler->camera_surface.mutex); - return CameraUtil::ProcessImage(handler->camera_surface.current_frame, width, height, - output_rgb, flip_horizontal, flip_vertical); + return handler->camera_surface.current_frame; } bool QtMultimediaCamera::IsPreviewAvailable() { diff --git a/src/citra_qt/camera/qt_multimedia_camera.h b/src/citra_qt/camera/qt_multimedia_camera.h index 580834275..41024214c 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.h +++ b/src/citra_qt/camera/qt_multimedia_camera.h @@ -13,7 +13,7 @@ #include #include #include "citra_qt/camera/camera_util.h" -#include "citra_qt/camera/qt_camera_factory.h" +#include "citra_qt/camera/qt_camera_base.h" #include "core/frontend/camera/interface.h" class GMainWindow; @@ -36,26 +36,18 @@ private: class QtMultimediaCameraHandler; /// This class is only an interface. It just calls QtMultimediaCameraHandler. -class QtMultimediaCamera final : public CameraInterface { +class QtMultimediaCamera final : public QtCameraInterface { public: QtMultimediaCamera(const std::string& camera_name, const Service::CAM::Flip& flip); ~QtMultimediaCamera(); void StartCapture() override; void StopCapture() override; - void SetResolution(const Service::CAM::Resolution&) override; - void SetFlip(Service::CAM::Flip) override; - void SetEffect(Service::CAM::Effect) override; - void SetFormat(Service::CAM::OutputFormat) override; void SetFrameRate(Service::CAM::FrameRate frame_rate) override; - std::vector ReceiveFrame() override; + QImage QtReceiveFrame() override; bool IsPreviewAvailable() override; private: std::shared_ptr handler; - int width, height; - bool output_rgb; - bool flip_horizontal, flip_vertical; - bool basic_flip_horizontal, basic_flip_vertical; }; class QtMultimediaCameraFactory final : public QtCameraFactory { diff --git a/src/citra_qt/camera/still_image_camera.cpp b/src/citra_qt/camera/still_image_camera.cpp index 7e54fad3e..2b9f4e54b 100644 --- a/src/citra_qt/camera/still_image_camera.cpp +++ b/src/citra_qt/camera/still_image_camera.cpp @@ -10,40 +10,14 @@ namespace Camera { StillImageCamera::StillImageCamera(QImage image_, const Service::CAM::Flip& flip) - : image(std::move(image_)) { - using namespace Service::CAM; - flip_horizontal = basic_flip_horizontal = (flip == Flip::Horizontal) || (flip == Flip::Reverse); - flip_vertical = basic_flip_vertical = (flip == Flip::Vertical) || (flip == Flip::Reverse); -} + : QtCameraInterface(flip), image(std::move(image_)) {} void StillImageCamera::StartCapture() {} void StillImageCamera::StopCapture() {} -void StillImageCamera::SetFormat(Service::CAM::OutputFormat output_format) { - output_rgb = output_format == Service::CAM::OutputFormat::RGB565; -} - -void StillImageCamera::SetResolution(const Service::CAM::Resolution& resolution) { - width = resolution.width; - height = resolution.height; -} - -void StillImageCamera::SetFlip(Service::CAM::Flip flip) { - using namespace Service::CAM; - flip_horizontal = basic_flip_horizontal ^ (flip == Flip::Horizontal || flip == Flip::Reverse); - flip_vertical = basic_flip_vertical ^ (flip == Flip::Vertical || flip == Flip::Reverse); -} - -void StillImageCamera::SetEffect(Service::CAM::Effect effect) { - if (effect != Service::CAM::Effect::None) { - NGLOG_ERROR(Service_CAM, "Unimplemented effect {}", static_cast(effect)); - } -} - -std::vector StillImageCamera::ReceiveFrame() { - return CameraUtil::ProcessImage(image, width, height, output_rgb, flip_horizontal, - flip_vertical); +QImage StillImageCamera::QtReceiveFrame() { + return image; } bool StillImageCamera::IsPreviewAvailable() { diff --git a/src/citra_qt/camera/still_image_camera.h b/src/citra_qt/camera/still_image_camera.h index e9016981b..11011622f 100644 --- a/src/citra_qt/camera/still_image_camera.h +++ b/src/citra_qt/camera/still_image_camera.h @@ -7,30 +7,22 @@ #include #include #include "citra_qt/camera/camera_util.h" -#include "citra_qt/camera/qt_camera_factory.h" +#include "citra_qt/camera/qt_camera_base.h" #include "core/frontend/camera/interface.h" namespace Camera { -class StillImageCamera final : public CameraInterface { +class StillImageCamera final : public QtCameraInterface { public: StillImageCamera(QImage image, const Service::CAM::Flip& flip); void StartCapture() override; void StopCapture() override; - void SetResolution(const Service::CAM::Resolution&) override; - void SetFlip(Service::CAM::Flip) override; - void SetEffect(Service::CAM::Effect) override; - void SetFormat(Service::CAM::OutputFormat) override; void SetFrameRate(Service::CAM::FrameRate frame_rate) override {} - std::vector ReceiveFrame() override; + QImage QtReceiveFrame() override; bool IsPreviewAvailable() override; private: QImage image; - int width, height; - bool output_rgb; - bool flip_horizontal, flip_vertical; - bool basic_flip_horizontal, basic_flip_vertical; }; class StillImageCameraFactory final : public QtCameraFactory { From 3cb91338e966730cbda7940577246b50b35f8259 Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Sat, 26 May 2018 11:32:18 +0800 Subject: [PATCH 3/7] camera: migrate logging macros --- src/core/frontend/camera/factory.cpp | 4 ++-- src/core/frontend/camera/factory.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/frontend/camera/factory.cpp b/src/core/frontend/camera/factory.cpp index 2a871196c..619fa3974 100644 --- a/src/core/frontend/camera/factory.cpp +++ b/src/core/frontend/camera/factory.cpp @@ -25,7 +25,7 @@ std::unique_ptr CreateCamera(const std::string& name, const std } if (name != "blank") { - LOG_ERROR(Service_CAM, "Unknown camera \"%s\"", name.c_str()); + NGLOG_ERROR(Service_CAM, "Unknown camera {}", name); } return std::make_unique(); } @@ -39,7 +39,7 @@ std::unique_ptr CreateCameraPreview(const std::string& name, } if (name != "blank") { - LOG_ERROR(Service_CAM, "Unknown camera \"%s\"", name.c_str()); + NGLOG_ERROR(Service_CAM, "Unknown camera {}", name); } return std::make_unique(); } diff --git a/src/core/frontend/camera/factory.h b/src/core/frontend/camera/factory.h index 2c4ab1479..dc795f0ce 100644 --- a/src/core/frontend/camera/factory.h +++ b/src/core/frontend/camera/factory.h @@ -31,7 +31,7 @@ public: * @param flip The image flip to apply * @returns a unique_ptr to the created camera object. * Note: The default implementation for this is to call Create(). Derived classes may have other - * Implementations. For example, A dialog may be used instead of LOG_ERROR when error + * Implementations. For example, A dialog may be used instead of NGLOG_ERROR when error * occurs. */ virtual std::unique_ptr CreatePreview(const std::string& config, int width, From 341c07156ac02f213e14c18ca2e28d119df7719f Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Sat, 2 Jun 2018 22:13:54 +0800 Subject: [PATCH 4/7] camera: Single/Double (QtMultimediaCamera) --- src/citra_qt/camera/qt_multimedia_camera.cpp | 20 +++++++++++++++++--- src/citra_qt/camera/qt_multimedia_camera.h | 4 +++- src/citra_qt/camera/still_image_camera.cpp | 5 ++--- src/citra_qt/camera/still_image_camera.h | 2 +- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/citra_qt/camera/qt_multimedia_camera.cpp b/src/citra_qt/camera/qt_multimedia_camera.cpp index abf2ff25e..05bcbd4f8 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.cpp +++ b/src/citra_qt/camera/qt_multimedia_camera.cpp @@ -48,7 +48,7 @@ bool QtCameraSurface::present(const QVideoFrame& frame) { QtMultimediaCamera::QtMultimediaCamera(const std::string& camera_name, const Service::CAM::Flip& flip) - : QtCameraInterface(flip), handler(QtMultimediaCameraHandler::GetHandler()) { + : QtCameraInterface(flip), handler(QtMultimediaCameraHandler::GetHandler(camera_name)) { if (handler->thread() == QThread::currentThread()) { handler->CreateCamera(camera_name); } else { @@ -94,7 +94,7 @@ void QtMultimediaCamera::SetFrameRate(Service::CAM::FrameRate frame_rate) { auto framerate = FrameRateList[static_cast(frame_rate)]; handler->settings.setMinimumFrameRate(framerate.minimumFrameRate); - handler->settings.setMinimumFrameRate(framerate.maximumFrameRate); + handler->settings.setMaximumFrameRate(framerate.maximumFrameRate); } QImage QtMultimediaCamera::QtReceiveFrame() { @@ -115,17 +115,25 @@ std::array, 3> QtMultimediaCameraHand std::array QtMultimediaCameraHandler::status; +std::unordered_map> + QtMultimediaCameraHandler::loaded; + void QtMultimediaCameraHandler::Init() { for (auto& handler : handlers) { handler = std::make_shared(); } } -std::shared_ptr QtMultimediaCameraHandler::GetHandler() { +std::shared_ptr QtMultimediaCameraHandler::GetHandler( + const std::string& camera_name) { + if (loaded.count(camera_name)) { + return loaded.at(camera_name); + } for (int i = 0; i < handlers.size(); i++) { if (!status[i]) { NGLOG_INFO(Service_CAM, "Successfully got handler {}", i); status[i] = true; + loaded.emplace(camera_name, handlers[i]); return handlers[i]; } } @@ -140,6 +148,12 @@ void QtMultimediaCameraHandler::ReleaseHandler( NGLOG_INFO(Service_CAM, "Successfully released handler {}", i); status[i] = false; handlers[i]->started = false; + for (auto it = loaded.begin(); it != loaded.end(); it++) { + if (it->second == handlers[i]) { + loaded.erase(it); + break; + } + } break; } } diff --git a/src/citra_qt/camera/qt_multimedia_camera.h b/src/citra_qt/camera/qt_multimedia_camera.h index 41024214c..e6d7b6b6d 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.h +++ b/src/citra_qt/camera/qt_multimedia_camera.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -62,7 +63,7 @@ class QtMultimediaCameraHandler final : public QObject { public: /// Creates the global handler. Must be called in UI thread. static void Init(); - static std::shared_ptr GetHandler(); + static std::shared_ptr GetHandler(const std::string& camera_name); static void ReleaseHandler(const std::shared_ptr& handler); /** @@ -92,6 +93,7 @@ private: static std::array, 3> handlers; static std::array status; + static std::unordered_map> loaded; friend class QtMultimediaCamera; // For access to camera_surface (and camera) }; diff --git a/src/citra_qt/camera/still_image_camera.cpp b/src/citra_qt/camera/still_image_camera.cpp index 2b9f4e54b..a166e3336 100644 --- a/src/citra_qt/camera/still_image_camera.cpp +++ b/src/citra_qt/camera/still_image_camera.cpp @@ -24,7 +24,7 @@ bool StillImageCamera::IsPreviewAvailable() { return !image.isNull(); } -const std::string StillImageCameraFactory::getFilePath() { +const std::string StillImageCameraFactory::GetFilePath() { QList types = QImageReader::supportedImageFormats(); QList temp_filters; for (QByteArray type : types) { @@ -32,7 +32,6 @@ const std::string StillImageCameraFactory::getFilePath() { } QString filter = QObject::tr("Supported image files (%1)").arg(temp_filters.join(" ")); - return QFileDialog::getOpenFileName(nullptr, QObject::tr("Open File"), ".", filter) .toStdString(); } @@ -41,7 +40,7 @@ std::unique_ptr StillImageCameraFactory::Create( const std::string& config, const Service::CAM::Flip& flip) const { std::string real_config = config; if (config.empty()) { - real_config = getFilePath(); + real_config = GetFilePath(); } QImage image(QString::fromStdString(real_config)); if (image.isNull()) { diff --git a/src/citra_qt/camera/still_image_camera.h b/src/citra_qt/camera/still_image_camera.h index 11011622f..80e43ba17 100644 --- a/src/citra_qt/camera/still_image_camera.h +++ b/src/citra_qt/camera/still_image_camera.h @@ -31,7 +31,7 @@ public: const Service::CAM::Flip& flip) const override; private: - static const std::string getFilePath(); + static const std::string GetFilePath(); }; } // namespace Camera From 7c48160beb8a4b0937dbe39ac2e84bcd422be08e Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Sun, 3 Jun 2018 11:29:46 +0800 Subject: [PATCH 5/7] StillImageCamera: move GetFilePath to UI thread --- src/citra_qt/camera/qt_camera_base.cpp | 5 +++-- src/citra_qt/camera/qt_camera_base.h | 2 +- src/citra_qt/camera/qt_multimedia_camera.cpp | 4 ++-- src/citra_qt/camera/qt_multimedia_camera.h | 2 +- src/citra_qt/camera/still_image_camera.cpp | 16 ++++++++++++---- src/citra_qt/camera/still_image_camera.h | 9 +++++---- src/core/frontend/camera/factory.h | 4 ++-- 7 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/citra_qt/camera/qt_camera_base.cpp b/src/citra_qt/camera/qt_camera_base.cpp index 65bf2361c..69593ab51 100644 --- a/src/citra_qt/camera/qt_camera_base.cpp +++ b/src/citra_qt/camera/qt_camera_base.cpp @@ -40,8 +40,9 @@ std::vector QtCameraInterface::ReceiveFrame() { flip_vertical); } -std::unique_ptr QtCameraFactory::CreatePreview( - const std::string& config, int width, int height, const Service::CAM::Flip& flip) const { +std::unique_ptr QtCameraFactory::CreatePreview(const std::string& config, + int width, int height, + const Service::CAM::Flip& flip) { std::unique_ptr camera = Create(config, flip); if (camera->IsPreviewAvailable()) { diff --git a/src/citra_qt/camera/qt_camera_base.h b/src/citra_qt/camera/qt_camera_base.h index e66c3bb46..6c6095a28 100644 --- a/src/citra_qt/camera/qt_camera_base.h +++ b/src/citra_qt/camera/qt_camera_base.h @@ -30,7 +30,7 @@ private: // Base class for camera factories of citra_qt class QtCameraFactory : public CameraFactory { std::unique_ptr CreatePreview(const std::string& config, int width, int height, - const Service::CAM::Flip& flip) const override; + const Service::CAM::Flip& flip) override; }; } // namespace Camera diff --git a/src/citra_qt/camera/qt_multimedia_camera.cpp b/src/citra_qt/camera/qt_multimedia_camera.cpp index 05bcbd4f8..ad6bad876 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.cpp +++ b/src/citra_qt/camera/qt_multimedia_camera.cpp @@ -106,8 +106,8 @@ bool QtMultimediaCamera::IsPreviewAvailable() { return handler->CameraAvailable(); } -std::unique_ptr QtMultimediaCameraFactory::Create( - const std::string& config, const Service::CAM::Flip& flip) const { +std::unique_ptr QtMultimediaCameraFactory::Create(const std::string& config, + const Service::CAM::Flip& flip) { return std::make_unique(config, flip); } diff --git a/src/citra_qt/camera/qt_multimedia_camera.h b/src/citra_qt/camera/qt_multimedia_camera.h index e6d7b6b6d..14242c554 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.h +++ b/src/citra_qt/camera/qt_multimedia_camera.h @@ -54,7 +54,7 @@ private: class QtMultimediaCameraFactory final : public QtCameraFactory { public: std::unique_ptr Create(const std::string& config, - const Service::CAM::Flip& flip) const override; + const Service::CAM::Flip& flip) override; }; class QtMultimediaCameraHandler final : public QObject { diff --git a/src/citra_qt/camera/still_image_camera.cpp b/src/citra_qt/camera/still_image_camera.cpp index a166e3336..b466d17df 100644 --- a/src/citra_qt/camera/still_image_camera.cpp +++ b/src/citra_qt/camera/still_image_camera.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "citra_qt/camera/still_image_camera.h" namespace Camera { @@ -24,7 +25,7 @@ bool StillImageCamera::IsPreviewAvailable() { return !image.isNull(); } -const std::string StillImageCameraFactory::GetFilePath() { +const std::string StillImageCameraFactory::GetFilePath() const { QList types = QImageReader::supportedImageFormats(); QList temp_filters; for (QByteArray type : types) { @@ -36,11 +37,18 @@ const std::string StillImageCameraFactory::GetFilePath() { .toStdString(); } -std::unique_ptr StillImageCameraFactory::Create( - const std::string& config, const Service::CAM::Flip& flip) const { +std::unique_ptr StillImageCameraFactory::Create(const std::string& config, + const Service::CAM::Flip& flip) { std::string real_config = config; if (config.empty()) { - real_config = GetFilePath(); + // call GetFilePath() in UI thread (note: StillImageCameraFactory itself is initialized in + // UI thread, so we can just pass in "this" here) + if (thread() == QThread::currentThread()) { + real_config = GetFilePath(); + } else { + QMetaObject::invokeMethod(this, "GetFilePath", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(std::string, real_config)); + } } QImage image(QString::fromStdString(real_config)); if (image.isNull()) { diff --git a/src/citra_qt/camera/still_image_camera.h b/src/citra_qt/camera/still_image_camera.h index 80e43ba17..ccfc13211 100644 --- a/src/citra_qt/camera/still_image_camera.h +++ b/src/citra_qt/camera/still_image_camera.h @@ -25,13 +25,14 @@ private: QImage image; }; -class StillImageCameraFactory final : public QtCameraFactory { +class StillImageCameraFactory final : public QObject, public QtCameraFactory { + Q_OBJECT + public: std::unique_ptr Create(const std::string& config, - const Service::CAM::Flip& flip) const override; + const Service::CAM::Flip& flip) override; -private: - static const std::string GetFilePath(); + Q_INVOKABLE const std::string GetFilePath() const; }; } // namespace Camera diff --git a/src/core/frontend/camera/factory.h b/src/core/frontend/camera/factory.h index dc795f0ce..0fe9f314f 100644 --- a/src/core/frontend/camera/factory.h +++ b/src/core/frontend/camera/factory.h @@ -22,7 +22,7 @@ public: * @returns a unique_ptr to the created camera object. */ virtual std::unique_ptr Create(const std::string& config, - const Service::CAM::Flip& flip) const = 0; + const Service::CAM::Flip& flip) = 0; /** * Creates a camera object for preview based on the configuration string. @@ -36,7 +36,7 @@ public: */ virtual std::unique_ptr CreatePreview(const std::string& config, int width, int height, - const Service::CAM::Flip& flip) const { + const Service::CAM::Flip& flip) { return Create(config, flip); } }; From a15e4e80c695e8a5976418c333a99b610f3b6d9d Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Thu, 7 Jun 2018 12:59:18 +0800 Subject: [PATCH 6/7] QtMultimediaCamera: fix invalid settings --- src/citra_qt/camera/qt_multimedia_camera.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/citra_qt/camera/qt_multimedia_camera.cpp b/src/citra_qt/camera/qt_multimedia_camera.cpp index ad6bad876..76a21453d 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.cpp +++ b/src/citra_qt/camera/qt_multimedia_camera.cpp @@ -93,8 +93,10 @@ void QtMultimediaCamera::SetFrameRate(Service::CAM::FrameRate frame_rate) { auto framerate = FrameRateList[static_cast(frame_rate)]; - handler->settings.setMinimumFrameRate(framerate.minimumFrameRate); - handler->settings.setMaximumFrameRate(framerate.maximumFrameRate); + if (handler->camera->supportedViewfinderFrameRateRanges().contains(framerate)) { + handler->settings.setMinimumFrameRate(framerate.minimumFrameRate); + handler->settings.setMaximumFrameRate(framerate.maximumFrameRate); + } } QImage QtMultimediaCamera::QtReceiveFrame() { @@ -171,6 +173,7 @@ void QtMultimediaCameraHandler::CreateCamera(const std::string& camera_name) { settings.setMinimumFrameRate(30); settings.setMaximumFrameRate(30); camera->setViewfinder(&camera_surface); + camera->load(); } void QtMultimediaCameraHandler::StopCamera() { From 3c554153c78ece768e05b126ff2bc51338f0c08d Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Thu, 7 Jun 2018 14:48:52 +0800 Subject: [PATCH 7/7] StillImageCamera: fix multiple prompt --- src/citra_qt/camera/still_image_camera.cpp | 14 ++++++++++++-- src/citra_qt/camera/still_image_camera.h | 7 +++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/citra_qt/camera/still_image_camera.cpp b/src/citra_qt/camera/still_image_camera.cpp index b466d17df..e02d0d0d3 100644 --- a/src/citra_qt/camera/still_image_camera.cpp +++ b/src/citra_qt/camera/still_image_camera.cpp @@ -13,6 +13,10 @@ namespace Camera { StillImageCamera::StillImageCamera(QImage image_, const Service::CAM::Flip& flip) : QtCameraInterface(flip), image(std::move(image_)) {} +StillImageCamera::~StillImageCamera() { + StillImageCameraFactory::last_path.clear(); +} + void StillImageCamera::StartCapture() {} void StillImageCamera::StopCapture() {} @@ -25,7 +29,12 @@ bool StillImageCamera::IsPreviewAvailable() { return !image.isNull(); } +std::string StillImageCameraFactory::last_path; + const std::string StillImageCameraFactory::GetFilePath() const { + if (!last_path.empty()) { + return last_path; + } QList types = QImageReader::supportedImageFormats(); QList temp_filters; for (QByteArray type : types) { @@ -33,8 +42,9 @@ const std::string StillImageCameraFactory::GetFilePath() const { } QString filter = QObject::tr("Supported image files (%1)").arg(temp_filters.join(" ")); - return QFileDialog::getOpenFileName(nullptr, QObject::tr("Open File"), ".", filter) - .toStdString(); + last_path = + QFileDialog::getOpenFileName(nullptr, QObject::tr("Open File"), ".", filter).toStdString(); + return last_path; } std::unique_ptr StillImageCameraFactory::Create(const std::string& config, diff --git a/src/citra_qt/camera/still_image_camera.h b/src/citra_qt/camera/still_image_camera.h index ccfc13211..19ca044f0 100644 --- a/src/citra_qt/camera/still_image_camera.h +++ b/src/citra_qt/camera/still_image_camera.h @@ -15,6 +15,7 @@ namespace Camera { class StillImageCamera final : public QtCameraInterface { public: StillImageCamera(QImage image, const Service::CAM::Flip& flip); + ~StillImageCamera(); void StartCapture() override; void StopCapture() override; void SetFrameRate(Service::CAM::FrameRate frame_rate) override {} @@ -33,6 +34,12 @@ public: const Service::CAM::Flip& flip) override; Q_INVOKABLE const std::string GetFilePath() const; + +private: + /// Record the path chosen to avoid multiple prompt problem + static std::string last_path; + + friend class StillImageCamera; }; } // namespace Camera