[libcamera-devel,v2,4/5] qcam: main_window: Introduce hotplug support

Message ID 20200513172950.72685-5-email@uajain.com
State Accepted
Delegated to: Umang Jain
Headers show
Series
  • Introduce UVC hotplug support
Related show

Commit Message

Umang Jain May 13, 2020, 5:30 p.m. UTC
Signed-off-by: Umang Jain <email@uajain.com>
---
 src/qcam/main_window.cpp | 83 ++++++++++++++++++++++++++++++++++++++++
 src/qcam/main_window.h   |  6 +++
 2 files changed, 89 insertions(+)

Patch

diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp
index 7de0895..d595112 100644
--- a/src/qcam/main_window.cpp
+++ b/src/qcam/main_window.cpp
@@ -49,6 +49,43 @@  public:
 	}
 };
 
+/**
+ * \brief Custom QEvent to signal hotplug or unplug
+ */
+class HotplugEvent : public QEvent
+{
+public:
+	enum PLUGEVENT {
+		HOTPLUG,
+		UNPLUG
+	};
+
+	HotplugEvent(std::shared_ptr<Camera> camera, PLUGEVENT event)
+		: QEvent(type())
+	{
+		camera_ = camera;
+		plugEvent_ = event;
+	}
+
+	~HotplugEvent()
+	{
+		camera_.reset();
+	}
+
+	static Type type()
+	{
+		static int type = QEvent::registerEventType();
+		return static_cast<Type>(type);
+	}
+
+	PLUGEVENT getHotplugEvent() { return plugEvent_; }
+	Camera *getCamera() { return camera_.get(); }
+
+private:
+	std::shared_ptr<Camera> camera_;
+	PLUGEVENT plugEvent_;
+};
+
 MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options)
 	: saveRaw_(nullptr), options_(options), cm_(cm), allocator_(nullptr),
 	  isCapturing_(false), captureRaw_(false)
@@ -71,6 +108,10 @@  MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options)
 	setCentralWidget(viewfinder_);
 	adjustSize();
 
+	/* Hotplug/unplug support */
+	cm_->cameraAdded.connect(this, &MainWindow::addNewCamera);
+	cm_->cameraRemoved.connect(this, &MainWindow::removeCamera);
+
 	/* Open the camera and start capture. */
 	ret = openCamera();
 	if (ret < 0) {
@@ -95,6 +136,9 @@  bool MainWindow::event(QEvent *e)
 	if (e->type() == CaptureEvent::type()) {
 		processCapture();
 		return true;
+	} else if (e->type() == HotplugEvent::type()) {
+		processHotplug(static_cast<HotplugEvent *>(e));
+		return true;
 	}
 
 	return QMainWindow::event(e);
@@ -525,6 +569,45 @@  void MainWindow::stopCapture()
 	setWindowTitle(title_);
 }
 
+/* -----------------------------------------------------------------------------
+ * Camera hotplugging support
+ */
+
+void MainWindow::processHotplug(HotplugEvent *e)
+{
+	Camera *camera = e->getCamera();
+	HotplugEvent::PLUGEVENT event = e->getHotplugEvent();
+
+	if (event == HotplugEvent::PLUGEVENT::HOTPLUG) {
+		cameraCombo_->addItem(QString::fromStdString(camera->name()));
+	} else if (event == HotplugEvent::PLUGEVENT::UNPLUG) {
+		int camIndex = cameraCombo_->findText(QString::fromStdString(camera->name()));
+
+		/* Check if the currently-streaming camera is removed. */
+		if (camera == camera_.get()) {
+			toggleCapture(false);
+			cameraCombo_->setCurrentIndex(0);
+		}
+		cameraCombo_->removeItem(camIndex);
+	}
+}
+
+void MainWindow::addNewCamera(std::shared_ptr<Camera> camera)
+{
+	qInfo() << "Adding new camera:" << camera->name().c_str();
+	QCoreApplication::postEvent(this,
+				    new HotplugEvent(std::move(camera),
+						     HotplugEvent::PLUGEVENT::HOTPLUG));
+}
+
+void MainWindow::removeCamera(std::shared_ptr<Camera> camera)
+{
+	qInfo() << "Removing camera:" << camera->name().c_str();
+	QCoreApplication::postEvent(this,
+				    new HotplugEvent(std::move(camera),
+						     HotplugEvent::PLUGEVENT::UNPLUG));
+}
+
 /* -----------------------------------------------------------------------------
  * Image Save
  */
diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h
index 59fa2d9..9108780 100644
--- a/src/qcam/main_window.h
+++ b/src/qcam/main_window.h
@@ -32,6 +32,8 @@  using namespace libcamera;
 class QAction;
 class QComboBox;
 
+class HotplugEvent;
+
 enum {
 	OptCamera = 'c',
 	OptHelp = 'h',
@@ -87,8 +89,12 @@  private:
 	int startCapture();
 	void stopCapture();
 
+	void addNewCamera(std::shared_ptr<Camera> camera);
+	void removeCamera(std::shared_ptr<Camera> camera);
+
 	void requestComplete(Request *request);
 	void processCapture();
+	void processHotplug(HotplugEvent *e);
 	void processViewfinder(FrameBuffer *buffer);
 
 	/* UI elements */