From patchwork Thu May 21 13:54:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 3835 Return-Path: Received: from o1.f.az.sendgrid.net (o1.f.az.sendgrid.net [208.117.55.132]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 66C55603D9 for ; Thu, 21 May 2020 15:54:27 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="j/P+5ob1"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=uajain.com; h=from:subject:in-reply-to:references:mime-version:to:cc: content-transfer-encoding:content-type; s=s1; bh=YYVNSzVIGlkduleifeiQvrWjcbhYk9UxIf31QLYEb04=; b=j/P+5ob1hT3tJH3R907kkFMju1aknQOHepIqZCXXFEIo7GpfFJvdCgU4llVXN7kIkVEa 2QmEX9mQ4Oxcjcbo8ztBkkk4N34Hn+52mTdGAsjJ7UmKQpr41boUj5WUl5DiJwf346NbSu eLIWoijMtSweOUDVgYy28IjolkxO8Tmxc= Received: by filterdrecv-p3iad2-8ddf98858-cq957 with SMTP id filterdrecv-p3iad2-8ddf98858-cq957-19-5EC68811-81 2020-05-21 13:54:26.061975347 +0000 UTC m=+4884416.209782124 Received: from mail.uajain.com (unknown) by ismtpd0007p1maa1.sendgrid.net (SG) with ESMTP id 5VvgiGk5SgWFKPJ3int_xg for ; Thu, 21 May 2020 13:54:25.633 +0000 (UTC) From: Umang Jain Date: Thu, 21 May 2020 13:54:26 +0000 (UTC) Message-Id: <20200521135416.13685-5-email@uajain.com> In-Reply-To: <20200521135416.13685-1-email@uajain.com> References: <20200521135416.13685-1-email@uajain.com> Mime-Version: 1.0 X-SG-EID: 1Q40EQ7YGir8a9gjSIAdTjhngY657NMk9ckeo4dbHZDiOpywc/L3L9rFqlwE4KPcmGfnt8UlNcpPI7X/q8AWBmiCvDjcK63MedTb+DWhuglfIl0VxLKPKJ8e1utqNA6dzdMLM+G7vGPLRcZvCzrTV/R7kb3JKs5f5FGch+UpqGksv20rQzQG3iohTs+2dFc5LZTxrF8cgx4FbKV9gg2FwxLYn8ikNX7aHyNOqezsuvxM1Ofish+XnwDo2G/3E6AcUVmwUAiaN1IEbJhilnzzmQ== To: libcamera-devel@lists.libcamera.org Subject: [libcamera-devel] [PATCH v3 4/5] qcam: main_window: Introduce initial hotplug support X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 21 May 2020 13:54:27 -0000 Hook up various QCam UI bits with hotplug support introduced in previous commits. This looks good-enough as first steps to see how the hotplugging functionality is turning out to be from application point-of-view. One can still think of few edge case nuances not yet covered under this implementation hence, those are intentionally kept out of scope for now. It might require some thinking and/or additional time on hand. Signed-off-by: Umang Jain --- src/qcam/main_window.cpp | 83 ++++++++++++++++++++++++++++++++++++++++ src/qcam/main_window.h | 6 +++ 2 files changed, 89 insertions(+) diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index 7de0895..ba96c27 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, PLUGEVENT event) + : QEvent(type()) + { + camera_ = camera; + plugEvent_ = event; + } + + ~HotplugEvent() + { + camera_.reset(); + } + + static Type type() + { + static int type = QEvent::registerEventType(); + return static_cast(type); + } + + PLUGEVENT getHotplugEvent() { return plugEvent_; } + Camera *getCamera() { return camera_.get(); } + +private: + std::shared_ptr 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_->newCameraAdded.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(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) +{ + 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) +{ + 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); + void removeCamera(std::shared_ptr camera); + void requestComplete(Request *request); void processCapture(); + void processHotplug(HotplugEvent *e); void processViewfinder(FrameBuffer *buffer); /* UI elements */