mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge pull request #3764 from zhaowenlan1779/camera-flip
camera: camera refinement
This commit is contained in:
		
						commit
						6811eda2b9
					
				
					 19 changed files with 563 additions and 400 deletions
				
			
		|  | @ -155,14 +155,20 @@ void Config::ReadValues() { | ||||||
|         sdl2_config->Get("Camera", "camera_outer_right_name", "blank"); |         sdl2_config->Get("Camera", "camera_outer_right_name", "blank"); | ||||||
|     Settings::values.camera_config[OuterRightCamera] = |     Settings::values.camera_config[OuterRightCamera] = | ||||||
|         sdl2_config->Get("Camera", "camera_outer_right_config", ""); |         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] = |     Settings::values.camera_name[InnerCamera] = | ||||||
|         sdl2_config->Get("Camera", "camera_inner_name", "blank"); |         sdl2_config->Get("Camera", "camera_inner_name", "blank"); | ||||||
|     Settings::values.camera_config[InnerCamera] = |     Settings::values.camera_config[InnerCamera] = | ||||||
|         sdl2_config->Get("Camera", "camera_inner_config", ""); |         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] = |     Settings::values.camera_name[OuterLeftCamera] = | ||||||
|         sdl2_config->Get("Camera", "camera_outer_left_name", "blank"); |         sdl2_config->Get("Camera", "camera_outer_left_name", "blank"); | ||||||
|     Settings::values.camera_config[OuterLeftCamera] = |     Settings::values.camera_config[OuterLeftCamera] = | ||||||
|         sdl2_config->Get("Camera", "camera_outer_left_config", ""); |         sdl2_config->Get("Camera", "camera_outer_left_config", ""); | ||||||
|  |     Settings::values.camera_flip[OuterLeftCamera] = | ||||||
|  |         sdl2_config->GetInteger("Camera", "camera_outer_left_flip", 0); | ||||||
| 
 | 
 | ||||||
|     // Miscellaneous
 |     // Miscellaneous
 | ||||||
|     Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Info"); |     Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Info"); | ||||||
|  |  | ||||||
|  | @ -178,13 +178,19 @@ camera_outer_right_name = | ||||||
| # A config string for the right outer camera. Its meaning is defined by the camera engine | # A config string for the right outer camera. Its meaning is defined by the camera engine | ||||||
| camera_outer_right_config = | 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 | # ... for the left outer camera | ||||||
| camera_outer_left_name = | camera_outer_left_name = | ||||||
| camera_outer_left_config = | camera_outer_left_config = | ||||||
|  | camera_outer_left_flip = | ||||||
| 
 | 
 | ||||||
| # ... for the inner camera | # ... for the inner camera | ||||||
| camera_inner_name = | camera_inner_name = | ||||||
| camera_inner_config = | camera_inner_config = | ||||||
|  | camera_inner_flip = | ||||||
| 
 | 
 | ||||||
| [Miscellaneous] | [Miscellaneous] | ||||||
| # A filter which removes logs below a certain logging level. | # A filter which removes logs below a certain logging level. | ||||||
|  |  | ||||||
|  | @ -13,8 +13,8 @@ add_executable(citra-qt | ||||||
|     camera/camera_util.h |     camera/camera_util.h | ||||||
|     camera/still_image_camera.cpp |     camera/still_image_camera.cpp | ||||||
|     camera/still_image_camera.h |     camera/still_image_camera.h | ||||||
|     camera/qt_camera_factory.cpp |     camera/qt_camera_base.cpp | ||||||
|     camera/qt_camera_factory.h |     camera/qt_camera_base.h | ||||||
|     camera/qt_multimedia_camera.cpp |     camera/qt_multimedia_camera.cpp | ||||||
|     camera/qt_multimedia_camera.h |     camera/qt_multimedia_camera.h | ||||||
|     citra-qt.rc |     citra-qt.rc | ||||||
|  |  | ||||||
							
								
								
									
										58
									
								
								src/citra_qt/camera/qt_camera_base.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/citra_qt/camera/qt_camera_base.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | ||||||
|  | // Copyright 2018 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include <QMessageBox> | ||||||
|  | #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<int>(effect)); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::vector<u16> QtCameraInterface::ReceiveFrame() { | ||||||
|  |     return CameraUtil::ProcessImage(QtReceiveFrame(), width, height, output_rgb, flip_horizontal, | ||||||
|  |                                     flip_vertical); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::unique_ptr<CameraInterface> QtCameraFactory::CreatePreview(const std::string& config, | ||||||
|  |                                                                 int width, int height, | ||||||
|  |                                                                 const Service::CAM::Flip& flip) { | ||||||
|  |     std::unique_ptr<CameraInterface> 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
 | ||||||
							
								
								
									
										36
									
								
								src/citra_qt/camera/qt_camera_base.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/citra_qt/camera/qt_camera_base.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 <string> | ||||||
|  | #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<u16> 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<CameraInterface> CreatePreview(const std::string& config, int width, int height, | ||||||
|  |                                                    const Service::CAM::Flip& flip) override; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace Camera
 | ||||||
|  | @ -1,24 +0,0 @@ | ||||||
| // Copyright 2018 Citra Emulator Project
 |  | ||||||
| // Licensed under GPLv2 or any later version
 |  | ||||||
| // Refer to the license.txt file included.
 |  | ||||||
| 
 |  | ||||||
| #include <QMessageBox> |  | ||||||
| #include "citra_qt/camera/qt_camera_factory.h" |  | ||||||
| 
 |  | ||||||
| namespace Camera { |  | ||||||
| 
 |  | ||||||
| std::unique_ptr<CameraInterface> QtCameraFactory::CreatePreview(const std::string& config, |  | ||||||
|                                                                 int width, int height) const { |  | ||||||
|     std::unique_ptr<CameraInterface> camera = Create(config); |  | ||||||
| 
 |  | ||||||
|     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
 |  | ||||||
|  | @ -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 <string> |  | ||||||
| #include "core/frontend/camera/factory.h" |  | ||||||
| 
 |  | ||||||
| namespace Camera { |  | ||||||
| 
 |  | ||||||
| // Base class for camera factories of citra_qt
 |  | ||||||
| class QtCameraFactory : public CameraFactory { |  | ||||||
|     std::unique_ptr<CameraInterface> CreatePreview(const std::string& config, int width, |  | ||||||
|                                                    int height) const override; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| } // namespace Camera
 |  | ||||||
|  | @ -46,8 +46,9 @@ bool QtCameraSurface::present(const QVideoFrame& frame) { | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| QtMultimediaCamera::QtMultimediaCamera(const std::string& camera_name) | QtMultimediaCamera::QtMultimediaCamera(const std::string& camera_name, | ||||||
|     : handler(QtMultimediaCameraHandler::GetHandler()) { |                                        const Service::CAM::Flip& flip) | ||||||
|  |     : QtCameraInterface(flip), handler(QtMultimediaCameraHandler::GetHandler(camera_name)) { | ||||||
|     if (handler->thread() == QThread::currentThread()) { |     if (handler->thread() == QThread::currentThread()) { | ||||||
|         handler->CreateCamera(camera_name); |         handler->CreateCamera(camera_name); | ||||||
|     } else { |     } else { | ||||||
|  | @ -73,10 +74,6 @@ void QtMultimediaCamera::StopCapture() { | ||||||
|     handler->StopCamera(); |     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) { | void QtMultimediaCamera::SetFrameRate(Service::CAM::FrameRate frame_rate) { | ||||||
|     const std::array<QCamera::FrameRateRange, 13> FrameRateList = { |     const std::array<QCamera::FrameRateRange, 13> FrameRateList = { | ||||||
|         /* Rate_15 */ QCamera::FrameRateRange(15, 15), |         /* Rate_15 */ QCamera::FrameRateRange(15, 15), | ||||||
|  | @ -96,57 +93,49 @@ void QtMultimediaCamera::SetFrameRate(Service::CAM::FrameRate frame_rate) { | ||||||
| 
 | 
 | ||||||
|     auto framerate = FrameRateList[static_cast<int>(frame_rate)]; |     auto framerate = FrameRateList[static_cast<int>(frame_rate)]; | ||||||
| 
 | 
 | ||||||
|  |     if (handler->camera->supportedViewfinderFrameRateRanges().contains(framerate)) { | ||||||
|         handler->settings.setMinimumFrameRate(framerate.minimumFrameRate); |         handler->settings.setMinimumFrameRate(framerate.minimumFrameRate); | ||||||
|     handler->settings.setMinimumFrameRate(framerate.maximumFrameRate); |         handler->settings.setMaximumFrameRate(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 = (flip == Flip::Horizontal) || (flip == Flip::Reverse); |  | ||||||
|     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<int>(effect)); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::vector<u16> QtMultimediaCamera::ReceiveFrame() { | QImage QtMultimediaCamera::QtReceiveFrame() { | ||||||
|     QMutexLocker locker(&handler->camera_surface.mutex); |     QMutexLocker locker(&handler->camera_surface.mutex); | ||||||
|     return CameraUtil::ProcessImage(handler->camera_surface.current_frame, width, height, |     return handler->camera_surface.current_frame; | ||||||
|                                     output_rgb, flip_horizontal, flip_vertical); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool QtMultimediaCamera::IsPreviewAvailable() { | bool QtMultimediaCamera::IsPreviewAvailable() { | ||||||
|     return handler->CameraAvailable(); |     return handler->CameraAvailable(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::unique_ptr<CameraInterface> QtMultimediaCameraFactory::Create( | std::unique_ptr<CameraInterface> QtMultimediaCameraFactory::Create(const std::string& config, | ||||||
|     const std::string& config) const { |                                                                    const Service::CAM::Flip& flip) { | ||||||
|     return std::make_unique<QtMultimediaCamera>(config); |     return std::make_unique<QtMultimediaCamera>(config, flip); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::array<std::shared_ptr<QtMultimediaCameraHandler>, 3> QtMultimediaCameraHandler::handlers; | std::array<std::shared_ptr<QtMultimediaCameraHandler>, 3> QtMultimediaCameraHandler::handlers; | ||||||
| 
 | 
 | ||||||
| std::array<bool, 3> QtMultimediaCameraHandler::status; | std::array<bool, 3> QtMultimediaCameraHandler::status; | ||||||
| 
 | 
 | ||||||
|  | std::unordered_map<std::string, std::shared_ptr<QtMultimediaCameraHandler>> | ||||||
|  |     QtMultimediaCameraHandler::loaded; | ||||||
|  | 
 | ||||||
| void QtMultimediaCameraHandler::Init() { | void QtMultimediaCameraHandler::Init() { | ||||||
|     for (auto& handler : handlers) { |     for (auto& handler : handlers) { | ||||||
|         handler = std::make_shared<QtMultimediaCameraHandler>(); |         handler = std::make_shared<QtMultimediaCameraHandler>(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::shared_ptr<QtMultimediaCameraHandler> QtMultimediaCameraHandler::GetHandler() { | std::shared_ptr<QtMultimediaCameraHandler> 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++) { |     for (int i = 0; i < handlers.size(); i++) { | ||||||
|         if (!status[i]) { |         if (!status[i]) { | ||||||
|             NGLOG_INFO(Service_CAM, "Successfully got handler {}", i); |             NGLOG_INFO(Service_CAM, "Successfully got handler {}", i); | ||||||
|             status[i] = true; |             status[i] = true; | ||||||
|  |             loaded.emplace(camera_name, handlers[i]); | ||||||
|             return handlers[i]; |             return handlers[i]; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -161,6 +150,12 @@ void QtMultimediaCameraHandler::ReleaseHandler( | ||||||
|             NGLOG_INFO(Service_CAM, "Successfully released handler {}", i); |             NGLOG_INFO(Service_CAM, "Successfully released handler {}", i); | ||||||
|             status[i] = false; |             status[i] = false; | ||||||
|             handlers[i]->started = false; |             handlers[i]->started = false; | ||||||
|  |             for (auto it = loaded.begin(); it != loaded.end(); it++) { | ||||||
|  |                 if (it->second == handlers[i]) { | ||||||
|  |                     loaded.erase(it); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -178,6 +173,7 @@ void QtMultimediaCameraHandler::CreateCamera(const std::string& camera_name) { | ||||||
|     settings.setMinimumFrameRate(30); |     settings.setMinimumFrameRate(30); | ||||||
|     settings.setMaximumFrameRate(30); |     settings.setMaximumFrameRate(30); | ||||||
|     camera->setViewfinder(&camera_surface); |     camera->setViewfinder(&camera_surface); | ||||||
|  |     camera->load(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void QtMultimediaCameraHandler::StopCamera() { | void QtMultimediaCameraHandler::StopCamera() { | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <array> | #include <array> | ||||||
| #include <string> | #include <string> | ||||||
|  | #include <unordered_map> | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <QAbstractVideoSurface> | #include <QAbstractVideoSurface> | ||||||
| #include <QCamera> | #include <QCamera> | ||||||
|  | @ -13,7 +14,7 @@ | ||||||
| #include <QImage> | #include <QImage> | ||||||
| #include <QMutex> | #include <QMutex> | ||||||
| #include "citra_qt/camera/camera_util.h" | #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" | #include "core/frontend/camera/interface.h" | ||||||
| 
 | 
 | ||||||
| class GMainWindow; | class GMainWindow; | ||||||
|  | @ -36,30 +37,24 @@ private: | ||||||
| class QtMultimediaCameraHandler; | class QtMultimediaCameraHandler; | ||||||
| 
 | 
 | ||||||
| /// This class is only an interface. It just calls QtMultimediaCameraHandler.
 | /// This class is only an interface. It just calls QtMultimediaCameraHandler.
 | ||||||
| class QtMultimediaCamera final : public CameraInterface { | class QtMultimediaCamera final : public QtCameraInterface { | ||||||
| public: | public: | ||||||
|     QtMultimediaCamera(const std::string& camera_name); |     QtMultimediaCamera(const std::string& camera_name, const Service::CAM::Flip& flip); | ||||||
|     ~QtMultimediaCamera(); |     ~QtMultimediaCamera(); | ||||||
|     void StartCapture() override; |     void StartCapture() override; | ||||||
|     void StopCapture() 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; |     void SetFrameRate(Service::CAM::FrameRate frame_rate) override; | ||||||
|     std::vector<u16> ReceiveFrame() override; |     QImage QtReceiveFrame() override; | ||||||
|     bool IsPreviewAvailable() override; |     bool IsPreviewAvailable() override; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     std::shared_ptr<QtMultimediaCameraHandler> handler; |     std::shared_ptr<QtMultimediaCameraHandler> handler; | ||||||
|     int width, height; |  | ||||||
|     bool output_rgb; |  | ||||||
|     bool flip_horizontal, flip_vertical; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class QtMultimediaCameraFactory final : public QtCameraFactory { | class QtMultimediaCameraFactory final : public QtCameraFactory { | ||||||
| public: | public: | ||||||
|     std::unique_ptr<CameraInterface> Create(const std::string& config) const override; |     std::unique_ptr<CameraInterface> Create(const std::string& config, | ||||||
|  |                                             const Service::CAM::Flip& flip) override; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class QtMultimediaCameraHandler final : public QObject { | class QtMultimediaCameraHandler final : public QObject { | ||||||
|  | @ -68,7 +63,7 @@ class QtMultimediaCameraHandler final : public QObject { | ||||||
| public: | public: | ||||||
|     /// Creates the global handler. Must be called in UI thread.
 |     /// Creates the global handler. Must be called in UI thread.
 | ||||||
|     static void Init(); |     static void Init(); | ||||||
|     static std::shared_ptr<QtMultimediaCameraHandler> GetHandler(); |     static std::shared_ptr<QtMultimediaCameraHandler> GetHandler(const std::string& camera_name); | ||||||
|     static void ReleaseHandler(const std::shared_ptr<QtMultimediaCameraHandler>& handler); |     static void ReleaseHandler(const std::shared_ptr<QtMultimediaCameraHandler>& handler); | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|  | @ -98,6 +93,7 @@ private: | ||||||
| 
 | 
 | ||||||
|     static std::array<std::shared_ptr<QtMultimediaCameraHandler>, 3> handlers; |     static std::array<std::shared_ptr<QtMultimediaCameraHandler>, 3> handlers; | ||||||
|     static std::array<bool, 3> status; |     static std::array<bool, 3> status; | ||||||
|  |     static std::unordered_map<std::string, std::shared_ptr<QtMultimediaCameraHandler>> loaded; | ||||||
| 
 | 
 | ||||||
|     friend class QtMultimediaCamera; // For access to camera_surface (and camera)
 |     friend class QtMultimediaCamera; // For access to camera_surface (and camera)
 | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -5,47 +5,36 @@ | ||||||
| #include <QFileDialog> | #include <QFileDialog> | ||||||
| #include <QImageReader> | #include <QImageReader> | ||||||
| #include <QMessageBox> | #include <QMessageBox> | ||||||
|  | #include <QThread> | ||||||
| #include "citra_qt/camera/still_image_camera.h" | #include "citra_qt/camera/still_image_camera.h" | ||||||
| 
 | 
 | ||||||
| namespace Camera { | namespace Camera { | ||||||
| 
 | 
 | ||||||
| StillImageCamera::StillImageCamera(QImage image_) : image(std::move(image_)) {} | 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::StartCapture() {} | ||||||
| 
 | 
 | ||||||
| void StillImageCamera::StopCapture() {} | void StillImageCamera::StopCapture() {} | ||||||
| 
 | 
 | ||||||
| void StillImageCamera::SetFormat(Service::CAM::OutputFormat output_format) { | QImage StillImageCamera::QtReceiveFrame() { | ||||||
|     output_rgb = output_format == Service::CAM::OutputFormat::RGB565; |     return image; | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 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 = (flip == Flip::Horizontal) || (flip == Flip::Reverse); |  | ||||||
|     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<int>(effect)); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| std::vector<u16> StillImageCamera::ReceiveFrame() { |  | ||||||
|     return CameraUtil::ProcessImage(image, width, height, output_rgb, flip_horizontal, |  | ||||||
|                                     flip_vertical); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool StillImageCamera::IsPreviewAvailable() { | bool StillImageCamera::IsPreviewAvailable() { | ||||||
|     return !image.isNull(); |     return !image.isNull(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const std::string StillImageCameraFactory::getFilePath() { | std::string StillImageCameraFactory::last_path; | ||||||
|  | 
 | ||||||
|  | const std::string StillImageCameraFactory::GetFilePath() const { | ||||||
|  |     if (!last_path.empty()) { | ||||||
|  |         return last_path; | ||||||
|  |     } | ||||||
|     QList<QByteArray> types = QImageReader::supportedImageFormats(); |     QList<QByteArray> types = QImageReader::supportedImageFormats(); | ||||||
|     QList<QString> temp_filters; |     QList<QString> temp_filters; | ||||||
|     for (QByteArray type : types) { |     for (QByteArray type : types) { | ||||||
|  | @ -53,21 +42,29 @@ const std::string StillImageCameraFactory::getFilePath() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     QString filter = QObject::tr("Supported image files (%1)").arg(temp_filters.join(" ")); |     QString filter = QObject::tr("Supported image files (%1)").arg(temp_filters.join(" ")); | ||||||
| 
 |     last_path = | ||||||
|     return QFileDialog::getOpenFileName(nullptr, QObject::tr("Open File"), ".", filter) |         QFileDialog::getOpenFileName(nullptr, QObject::tr("Open File"), ".", filter).toStdString(); | ||||||
|         .toStdString(); |     return last_path; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::unique_ptr<CameraInterface> StillImageCameraFactory::Create(const std::string& config) const { | std::unique_ptr<CameraInterface> StillImageCameraFactory::Create(const std::string& config, | ||||||
|  |                                                                  const Service::CAM::Flip& flip) { | ||||||
|     std::string real_config = config; |     std::string real_config = config; | ||||||
|     if (config.empty()) { |     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)); |     QImage image(QString::fromStdString(real_config)); | ||||||
|     if (image.isNull()) { |     if (image.isNull()) { | ||||||
|         NGLOG_ERROR(Service_CAM, "Couldn't load image \"{}\"", real_config.c_str()); |         NGLOG_ERROR(Service_CAM, "Couldn't load image \"{}\"", real_config.c_str()); | ||||||
|     } |     } | ||||||
|     return std::make_unique<StillImageCamera>(image); |     return std::make_unique<StillImageCamera>(image, flip); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace Camera
 | } // namespace Camera
 | ||||||
|  |  | ||||||
|  | @ -7,37 +7,39 @@ | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <QImage> | #include <QImage> | ||||||
| #include "citra_qt/camera/camera_util.h" | #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" | #include "core/frontend/camera/interface.h" | ||||||
| 
 | 
 | ||||||
| namespace Camera { | namespace Camera { | ||||||
| 
 | 
 | ||||||
| class StillImageCamera final : public CameraInterface { | class StillImageCamera final : public QtCameraInterface { | ||||||
| public: | public: | ||||||
|     StillImageCamera(QImage image); |     StillImageCamera(QImage image, const Service::CAM::Flip& flip); | ||||||
|  |     ~StillImageCamera(); | ||||||
|     void StartCapture() override; |     void StartCapture() override; | ||||||
|     void StopCapture() 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 {} |     void SetFrameRate(Service::CAM::FrameRate frame_rate) override {} | ||||||
|     std::vector<u16> ReceiveFrame() override; |     QImage QtReceiveFrame() override; | ||||||
|     bool IsPreviewAvailable() override; |     bool IsPreviewAvailable() override; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     QImage image; |     QImage image; | ||||||
|     int width, height; |  | ||||||
|     bool output_rgb; |  | ||||||
|     bool flip_horizontal, flip_vertical; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class StillImageCameraFactory final : public QtCameraFactory { | class StillImageCameraFactory final : public QObject, public QtCameraFactory { | ||||||
|  |     Q_OBJECT | ||||||
|  | 
 | ||||||
| public: | public: | ||||||
|     std::unique_ptr<CameraInterface> Create(const std::string& config) const override; |     std::unique_ptr<CameraInterface> Create(const std::string& config, | ||||||
|  |                                             const Service::CAM::Flip& flip) override; | ||||||
|  | 
 | ||||||
|  |     Q_INVOKABLE const std::string GetFilePath() const; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     static const std::string getFilePath(); |     /// Record the path chosen to avoid multiple prompt problem
 | ||||||
|  |     static std::string last_path; | ||||||
|  | 
 | ||||||
|  |     friend class StillImageCamera; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace Camera
 | } // namespace Camera
 | ||||||
|  |  | ||||||
|  | @ -128,14 +128,19 @@ void Config::ReadValues() { | ||||||
|         qt_config->value("camera_outer_right_name", "blank").toString().toStdString(); |         qt_config->value("camera_outer_right_name", "blank").toString().toStdString(); | ||||||
|     Settings::values.camera_config[OuterRightCamera] = |     Settings::values.camera_config[OuterRightCamera] = | ||||||
|         qt_config->value("camera_outer_right_config", "").toString().toStdString(); |         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] = |     Settings::values.camera_name[InnerCamera] = | ||||||
|         qt_config->value("camera_inner_name", "blank").toString().toStdString(); |         qt_config->value("camera_inner_name", "blank").toString().toStdString(); | ||||||
|     Settings::values.camera_config[InnerCamera] = |     Settings::values.camera_config[InnerCamera] = | ||||||
|         qt_config->value("camera_inner_config", "").toString().toStdString(); |         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] = |     Settings::values.camera_name[OuterLeftCamera] = | ||||||
|         qt_config->value("camera_outer_left_name", "blank").toString().toStdString(); |         qt_config->value("camera_outer_left_name", "blank").toString().toStdString(); | ||||||
|     Settings::values.camera_config[OuterLeftCamera] = |     Settings::values.camera_config[OuterLeftCamera] = | ||||||
|         qt_config->value("camera_outer_left_config", "").toString().toStdString(); |         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->endGroup(); | ||||||
| 
 | 
 | ||||||
|     qt_config->beginGroup("Data Storage"); |     qt_config->beginGroup("Data Storage"); | ||||||
|  | @ -317,14 +322,17 @@ void Config::SaveValues() { | ||||||
|                         QString::fromStdString(Settings::values.camera_name[OuterRightCamera])); |                         QString::fromStdString(Settings::values.camera_name[OuterRightCamera])); | ||||||
|     qt_config->setValue("camera_outer_right_config", |     qt_config->setValue("camera_outer_right_config", | ||||||
|                         QString::fromStdString(Settings::values.camera_config[OuterRightCamera])); |                         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", |     qt_config->setValue("camera_inner_name", | ||||||
|                         QString::fromStdString(Settings::values.camera_name[InnerCamera])); |                         QString::fromStdString(Settings::values.camera_name[InnerCamera])); | ||||||
|     qt_config->setValue("camera_inner_config", |     qt_config->setValue("camera_inner_config", | ||||||
|                         QString::fromStdString(Settings::values.camera_config[InnerCamera])); |                         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", |     qt_config->setValue("camera_outer_left_name", | ||||||
|                         QString::fromStdString(Settings::values.camera_name[OuterLeftCamera])); |                         QString::fromStdString(Settings::values.camera_name[OuterLeftCamera])); | ||||||
|     qt_config->setValue("camera_outer_left_config", |     qt_config->setValue("camera_outer_left_config", | ||||||
|                         QString::fromStdString(Settings::values.camera_config[OuterLeftCamera])); |                         QString::fromStdString(Settings::values.camera_config[OuterLeftCamera])); | ||||||
|  |     qt_config->setValue("camera_outer_left_flip", Settings::values.camera_flip[OuterLeftCamera]); | ||||||
|     qt_config->endGroup(); |     qt_config->endGroup(); | ||||||
| 
 | 
 | ||||||
|     qt_config->beginGroup("Data Storage"); |     qt_config->beginGroup("Data Storage"); | ||||||
|  |  | ||||||
|  | @ -27,14 +27,7 @@ ConfigureCamera::ConfigureCamera(QWidget* parent) | ||||||
|     // Load settings
 |     // Load settings
 | ||||||
|     camera_name = Settings::values.camera_name; |     camera_name = Settings::values.camera_name; | ||||||
|     camera_config = Settings::values.camera_config; |     camera_config = Settings::values.camera_config; | ||||||
|     for (auto&& item : camera_name) { |     camera_flip = Settings::values.camera_flip; | ||||||
|         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"; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     QList<QCameraInfo> cameras = QCameraInfo::availableCameras(); |     QList<QCameraInfo> cameras = QCameraInfo::availableCameras(); | ||||||
|     for (const QCameraInfo& cameraInfo : cameras) { |     for (const QCameraInfo& cameraInfo : cameras) { | ||||||
|         ui->system_camera->addItem(cameraInfo.deviceName()); |         ui->system_camera->addItem(cameraInfo.deviceName()); | ||||||
|  | @ -98,6 +91,8 @@ void ConfigureCamera::connectEvents() { | ||||||
|     connect(ui->system_camera, |     connect(ui->system_camera, | ||||||
|             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, |             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, | ||||||
|             [=] { stopPreviewing(); }); |             [=] { stopPreviewing(); }); | ||||||
|  |     connect(ui->camera_flip, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), | ||||||
|  |             this, [=] { stopPreviewing(); }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConfigureCamera::updateCameraMode() { | void ConfigureCamera::updateCameraMode() { | ||||||
|  | @ -148,6 +143,8 @@ void ConfigureCamera::updateImageSourceUI() { | ||||||
|     } |     } | ||||||
|     ui->system_camera_label->setHidden(image_source != 2); |     ui->system_camera_label->setHidden(image_source != 2); | ||||||
|     ui->system_camera->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() { | void ConfigureCamera::recordConfig() { | ||||||
|  | @ -166,10 +163,12 @@ void ConfigureCamera::recordConfig() { | ||||||
|     if (current_selected == CameraPosition::RearBoth) { |     if (current_selected == CameraPosition::RearBoth) { | ||||||
|         camera_name[0] = camera_name[2] = implementation; |         camera_name[0] = camera_name[2] = implementation; | ||||||
|         camera_config[0] = camera_config[2] = config; |         camera_config[0] = camera_config[2] = config; | ||||||
|  |         camera_flip[0] = camera_flip[2] = ui->camera_flip->currentIndex(); | ||||||
|     } else if (current_selected != CameraPosition::Null) { |     } else if (current_selected != CameraPosition::Null) { | ||||||
|         int index = static_cast<int>(current_selected); |         int index = static_cast<int>(current_selected); | ||||||
|         camera_name[index] = implementation; |         camera_name[index] = implementation; | ||||||
|         camera_config[index] = config; |         camera_config[index] = config; | ||||||
|  |         camera_flip[index] = ui->camera_flip->currentIndex(); | ||||||
|     } |     } | ||||||
|     current_selected = getCameraSelection(); |     current_selected = getCameraSelection(); | ||||||
| } | } | ||||||
|  | @ -187,9 +186,9 @@ void ConfigureCamera::startPreviewing() { | ||||||
|     ui->preview_box->setToolTip(tr("Resolution: ") + QString::number(preview_width) + "*" + |     ui->preview_box->setToolTip(tr("Resolution: ") + QString::number(preview_width) + "*" + | ||||||
|                                 QString::number(preview_height)); |                                 QString::number(preview_height)); | ||||||
|     // Load previewing camera
 |     // Load previewing camera
 | ||||||
|     previewing_camera = |     previewing_camera = Camera::CreateCameraPreview( | ||||||
|         Camera::CreateCameraPreview(camera_name[camera_selection], camera_config[camera_selection], |         camera_name[camera_selection], camera_config[camera_selection], preview_width, | ||||||
|                                     preview_width, preview_height); |         preview_height, static_cast<Service::CAM::Flip>(camera_flip[camera_selection])); | ||||||
|     if (!previewing_camera) { |     if (!previewing_camera) { | ||||||
|         stopPreviewing(); |         stopPreviewing(); | ||||||
|         return; |         return; | ||||||
|  | @ -262,6 +261,7 @@ void ConfigureCamera::setConfiguration() { | ||||||
|     } else { |     } else { | ||||||
|         ui->camera_file->setText(QString::fromStdString(camera_config[index])); |         ui->camera_file->setText(QString::fromStdString(camera_config[index])); | ||||||
|     } |     } | ||||||
|  |     ui->camera_flip->setCurrentIndex(camera_flip[index]); | ||||||
|     updateImageSourceUI(); |     updateImageSourceUI(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -288,6 +288,7 @@ void ConfigureCamera::applyConfiguration() { | ||||||
|     stopPreviewing(); |     stopPreviewing(); | ||||||
|     Settings::values.camera_name = camera_name; |     Settings::values.camera_name = camera_name; | ||||||
|     Settings::values.camera_config = camera_config; |     Settings::values.camera_config = camera_config; | ||||||
|  |     Settings::values.camera_flip = camera_flip; | ||||||
|     Settings::Apply(); |     Settings::Apply(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -47,6 +47,7 @@ private: | ||||||
|     std::unique_ptr<Ui::ConfigureCamera> ui; |     std::unique_ptr<Ui::ConfigureCamera> ui; | ||||||
|     std::array<std::string, 3> camera_name; |     std::array<std::string, 3> camera_name; | ||||||
|     std::array<std::string, 3> camera_config; |     std::array<std::string, 3> camera_config; | ||||||
|  |     std::array<int, 3> camera_flip; | ||||||
|     int timer_id = 0; |     int timer_id = 0; | ||||||
|     int preview_width = 0; |     int preview_width = 0; | ||||||
|     int preview_height = 0; |     int preview_height = 0; | ||||||
|  |  | ||||||
|  | @ -1,8 +1,18 @@ | ||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| 
 |  | ||||||
| <ui version="4.0"> | <ui version="4.0"> | ||||||
|  <class>ConfigureCamera</class> |  <class>ConfigureCamera</class> | ||||||
|  <widget class="QWidget" name="ConfigureCamera"> |  <widget class="QWidget" name="ConfigureCamera"> | ||||||
|  |   <property name="geometry"> | ||||||
|  |    <rect> | ||||||
|  |     <x>0</x> | ||||||
|  |     <y>0</y> | ||||||
|  |     <width>400</width> | ||||||
|  |     <height>300</height> | ||||||
|  |    </rect> | ||||||
|  |   </property> | ||||||
|  |   <property name="windowTitle"> | ||||||
|  |    <string>Form</string> | ||||||
|  |   </property> | ||||||
|   <layout class="QVBoxLayout" name="verticalLayout"> |   <layout class="QVBoxLayout" name="verticalLayout"> | ||||||
|    <item> |    <item> | ||||||
|     <widget class="QGroupBox" name="groupBox"> |     <widget class="QGroupBox" name="groupBox"> | ||||||
|  | @ -127,7 +137,7 @@ | ||||||
|         <item> |         <item> | ||||||
|          <widget class="QComboBox" name="image_source"> |          <widget class="QComboBox" name="image_source"> | ||||||
|           <property name="toolTip"> |           <property name="toolTip"> | ||||||
|                       <string>Select where the image of the emulated camera come from. It may be an image or a real camera.</string> |            <string>Select where the image of the emulated camera comes from. It may be an image or a real camera.</string> | ||||||
|           </property> |           </property> | ||||||
|           <item> |           <item> | ||||||
|            <property name="text"> |            <property name="text"> | ||||||
|  | @ -179,6 +189,9 @@ | ||||||
|           <property name="frameShape"> |           <property name="frameShape"> | ||||||
|            <enum>QFrame::NoFrame</enum> |            <enum>QFrame::NoFrame</enum> | ||||||
|           </property> |           </property> | ||||||
|  |           <property name="toolTip"> | ||||||
|  |            <string>Select the system camera to use</string> | ||||||
|  |           </property> | ||||||
|           <property name="text"> |           <property name="text"> | ||||||
|            <string>Camera:</string> |            <string>Camera:</string> | ||||||
|           </property> |           </property> | ||||||
|  | @ -186,6 +199,21 @@ | ||||||
|         </item> |         </item> | ||||||
|         <item> |         <item> | ||||||
|          <widget class="QComboBox" name="system_camera"> |          <widget class="QComboBox" name="system_camera"> | ||||||
|  |           <property name="sizePolicy"> | ||||||
|  |            <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> | ||||||
|  |             <horstretch>0</horstretch> | ||||||
|  |             <verstretch>0</verstretch> | ||||||
|  |            </sizepolicy> | ||||||
|  |           </property> | ||||||
|  |           <property name="maximumSize"> | ||||||
|  |            <size> | ||||||
|  |             <width>250</width> | ||||||
|  |             <height>16777215</height> | ||||||
|  |            </size> | ||||||
|  |           </property> | ||||||
|  |           <property name="toolTip"> | ||||||
|  |            <string>Select the system camera to use</string> | ||||||
|  |           </property> | ||||||
|           <item> |           <item> | ||||||
|            <property name="text"> |            <property name="text"> | ||||||
|             <string><Default></string> |             <string><Default></string> | ||||||
|  | @ -195,8 +223,70 @@ | ||||||
|         </item> |         </item> | ||||||
|        </layout> |        </layout> | ||||||
|       </item> |       </item> | ||||||
|  |       <item> | ||||||
|  |        <layout class="QHBoxLayout" name="horizontalLayout_8"> | ||||||
|  |         <item> | ||||||
|  |          <widget class="QLabel" name="camera_flip_label"> | ||||||
|  |           <property name="frameShape"> | ||||||
|  |            <enum>QFrame::NoFrame</enum> | ||||||
|  |           </property> | ||||||
|  |           <property name="toolTip"> | ||||||
|  |            <string>Select the image flip to apply</string> | ||||||
|  |           </property> | ||||||
|  |           <property name="text"> | ||||||
|  |            <string>Flip:</string> | ||||||
|  |           </property> | ||||||
|  |          </widget> | ||||||
|  |         </item> | ||||||
|  |         <item> | ||||||
|  |          <widget class="QComboBox" name="camera_flip"> | ||||||
|  |           <property name="enabled"> | ||||||
|  |            <bool>true</bool> | ||||||
|  |           </property> | ||||||
|  |           <property name="sizePolicy"> | ||||||
|  |            <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> | ||||||
|  |             <horstretch>0</horstretch> | ||||||
|  |             <verstretch>0</verstretch> | ||||||
|  |            </sizepolicy> | ||||||
|  |           </property> | ||||||
|  |           <property name="maximumSize"> | ||||||
|  |            <size> | ||||||
|  |             <width>800</width> | ||||||
|  |             <height>16777215</height> | ||||||
|  |            </size> | ||||||
|  |           </property> | ||||||
|  |           <property name="toolTip"> | ||||||
|  |            <string>Select the image flip to apply</string> | ||||||
|  |           </property> | ||||||
|  |           <item> | ||||||
|  |            <property name="text"> | ||||||
|  |             <string>None</string> | ||||||
|  |            </property> | ||||||
|  |           </item> | ||||||
|  |           <item> | ||||||
|  |            <property name="text"> | ||||||
|  |             <string>Horizontal</string> | ||||||
|  |            </property> | ||||||
|  |           </item> | ||||||
|  |           <item> | ||||||
|  |            <property name="text"> | ||||||
|  |             <string>Vertical</string> | ||||||
|  |            </property> | ||||||
|  |           </item> | ||||||
|  |           <item> | ||||||
|  |            <property name="text"> | ||||||
|  |             <string>Reverse</string> | ||||||
|  |            </property> | ||||||
|  |           </item> | ||||||
|  |          </widget> | ||||||
|  |         </item> | ||||||
|  |        </layout> | ||||||
|  |       </item> | ||||||
|       <item> |       <item> | ||||||
|        <widget class="QCheckBox" name="prompt_before_load"> |        <widget class="QCheckBox" name="prompt_before_load"> | ||||||
|  |         <property name="toolTip"> | ||||||
|  |          <string>Select an image file every time before the camera is loaded</string> | ||||||
|  |         </property> | ||||||
|         <property name="text"> |         <property name="text"> | ||||||
|          <string>Prompt before load</string> |          <string>Prompt before load</string> | ||||||
|         </property> |         </property> | ||||||
|  |  | ||||||
|  | @ -17,28 +17,29 @@ void RegisterFactory(const std::string& name, std::unique_ptr<CameraFactory> fac | ||||||
|     factories[name] = std::move(factory); |     factories[name] = std::move(factory); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::unique_ptr<CameraInterface> CreateCamera(const std::string& name, const std::string& config) { | std::unique_ptr<CameraInterface> CreateCamera(const std::string& name, const std::string& config, | ||||||
|  |                                               const Service::CAM::Flip& flip) { | ||||||
|     auto pair = factories.find(name); |     auto pair = factories.find(name); | ||||||
|     if (pair != factories.end()) { |     if (pair != factories.end()) { | ||||||
|         return pair->second->Create(config); |         return pair->second->Create(config, flip); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (name != "blank") { |     if (name != "blank") { | ||||||
|         LOG_ERROR(Service_CAM, "Unknown camera \"%s\"", name.c_str()); |         NGLOG_ERROR(Service_CAM, "Unknown camera {}", name); | ||||||
|     } |     } | ||||||
|     return std::make_unique<BlankCamera>(); |     return std::make_unique<BlankCamera>(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::unique_ptr<CameraInterface> CreateCameraPreview(const std::string& name, | std::unique_ptr<CameraInterface> CreateCameraPreview(const std::string& name, | ||||||
|                                                      const std::string& config, int width, |                                                      const std::string& config, int width, | ||||||
|                                                      int height) { |                                                      int height, const Service::CAM::Flip& flip) { | ||||||
|     auto pair = factories.find(name); |     auto pair = factories.find(name); | ||||||
|     if (pair != factories.end()) { |     if (pair != factories.end()) { | ||||||
|         return pair->second->CreatePreview(config, width, height); |         return pair->second->CreatePreview(config, width, height, flip); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (name != "blank") { |     if (name != "blank") { | ||||||
|         LOG_ERROR(Service_CAM, "Unknown camera \"%s\"", name.c_str()); |         NGLOG_ERROR(Service_CAM, "Unknown camera {}", name); | ||||||
|     } |     } | ||||||
|     return std::make_unique<BlankCamera>(); |     return std::make_unique<BlankCamera>(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -18,22 +18,26 @@ public: | ||||||
|      * Creates a camera object based on the configuration string. |      * Creates a camera object based on the configuration string. | ||||||
|      * @param config Configuration string to create the camera. The implementation can decide the |      * @param config Configuration string to create the camera. The implementation can decide the | ||||||
|      *               meaning of this string. |      *               meaning of this string. | ||||||
|  |      * @param flip The image flip to apply | ||||||
|      * @returns a unique_ptr to the created camera object. |      * @returns a unique_ptr to the created camera object. | ||||||
|      */ |      */ | ||||||
|     virtual std::unique_ptr<CameraInterface> Create(const std::string& config) const = 0; |     virtual std::unique_ptr<CameraInterface> Create(const std::string& config, | ||||||
|  |                                                     const Service::CAM::Flip& flip) = 0; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Creates a camera object for preview based on the configuration string. |      * Creates a camera object for preview based on the configuration string. | ||||||
|      * @param config Configuration string to create the camera. The implementation can decide the |      * @param config Configuration string to create the camera. The implementation can decide the | ||||||
|      *               meaning of this string. |      *               meaning of this string. | ||||||
|  |      * @param flip The image flip to apply | ||||||
|      * @returns a unique_ptr to the created camera object. |      * @returns a unique_ptr to the created camera object. | ||||||
|      * Note: The default implementation for this is to call Create(). Derived classes may have other |      * 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. |      * occurs. | ||||||
|      */ |      */ | ||||||
|     virtual std::unique_ptr<CameraInterface> CreatePreview(const std::string& config, int width, |     virtual std::unique_ptr<CameraInterface> CreatePreview(const std::string& config, int width, | ||||||
|                                                            int height) const { |                                                            int height, | ||||||
|         return Create(config); |                                                            const Service::CAM::Flip& flip) { | ||||||
|  |         return Create(config, flip); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -50,7 +54,8 @@ void RegisterFactory(const std::string& name, std::unique_ptr<CameraFactory> fac | ||||||
|  * @param config Configuration string to create the camera. The meaning of this string is |  * @param config Configuration string to create the camera. The meaning of this string is | ||||||
|  *     defined by the factory. |  *     defined by the factory. | ||||||
|  */ |  */ | ||||||
| std::unique_ptr<CameraInterface> CreateCamera(const std::string& name, const std::string& config); | std::unique_ptr<CameraInterface> CreateCamera(const std::string& name, const std::string& config, | ||||||
|  |                                               const Service::CAM::Flip& flip); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Creates a camera from the factory for previewing. |  * Creates a camera from the factory for previewing. | ||||||
|  | @ -60,6 +65,6 @@ std::unique_ptr<CameraInterface> CreateCamera(const std::string& name, const std | ||||||
|  */ |  */ | ||||||
| std::unique_ptr<CameraInterface> CreateCameraPreview(const std::string& name, | std::unique_ptr<CameraInterface> CreateCameraPreview(const std::string& name, | ||||||
|                                                      const std::string& config, int width, |                                                      const std::string& config, int width, | ||||||
|                                                      int height); |                                                      int height, const Service::CAM::Flip& flip); | ||||||
| 
 | 
 | ||||||
| } // namespace Camera
 | } // namespace Camera
 | ||||||
|  |  | ||||||
|  | @ -1041,8 +1041,9 @@ void Module::ReloadCameraDevices() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Module::LoadCameraImplementation(CameraConfig& camera, int camera_id) { | void Module::LoadCameraImplementation(CameraConfig& camera, int camera_id) { | ||||||
|     camera.impl = Camera::CreateCamera(Settings::values.camera_name[camera_id], |     camera.impl = Camera::CreateCamera( | ||||||
|                                        Settings::values.camera_config[camera_id]); |         Settings::values.camera_name[camera_id], Settings::values.camera_config[camera_id], | ||||||
|  |         static_cast<Service::CAM::Flip>(Settings::values.camera_flip[camera_id])); | ||||||
|     camera.impl->SetFlip(camera.contexts[0].flip); |     camera.impl->SetFlip(camera.contexts[0].flip); | ||||||
|     camera.impl->SetEffect(camera.contexts[0].effect); |     camera.impl->SetEffect(camera.contexts[0].effect); | ||||||
|     camera.impl->SetFormat(camera.contexts[0].format); |     camera.impl->SetFormat(camera.contexts[0].format); | ||||||
|  |  | ||||||
|  | @ -140,6 +140,7 @@ struct Values { | ||||||
|     // Camera
 |     // Camera
 | ||||||
|     std::array<std::string, Service::CAM::NumCameras> camera_name; |     std::array<std::string, Service::CAM::NumCameras> camera_name; | ||||||
|     std::array<std::string, Service::CAM::NumCameras> camera_config; |     std::array<std::string, Service::CAM::NumCameras> camera_config; | ||||||
|  |     std::array<int, Service::CAM::NumCameras> camera_flip; | ||||||
| 
 | 
 | ||||||
|     // Debugging
 |     // Debugging
 | ||||||
|     bool use_gdbstub; |     bool use_gdbstub; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue