[{"id":23713,"web_url":"https://patchwork.libcamera.org/comment/23713/","msgid":"<165669573360.1516045.12584394031188499896@Monstersaurus>","date":"2022-07-01T17:15:33","subject":"Re: [libcamera-devel] [PATCH v3 2/3] qcam: Add a GUI way to use\n\tcapture script","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Utkarsh Tiwari via libcamera-devel (2022-06-27 04:01:58)\n> Implement an Open Capture Script button which would allow the user\n> to open a Capture Script (*.yaml).\n> This button has two states Open and Stop.\n> \n> Open state allows user to load a capture script.\n> When clicked in open state present them with a QFileDialog\n> to allow user to select a single file.\n> \n> Stop state stops the execution of the current capture script.\n> \n> Introduce a queueCount_ to keep track of the requests queued.\n> \n> When stopping the execution no count is reset and the\n> capture continues as it is.\n> \n> Requests are queued with any controls the script matching\n> the current queueCount_\n> \n> Signed-off-by: Utkarsh Tiwari <utkarsh02t@gmail.com>\n> ---\n>  src/qcam/assets/feathericons/feathericons.qrc |  2 +\n>  src/qcam/main_window.cpp                      | 66 +++++++++++++++++++\n>  src/qcam/main_window.h                        |  6 ++\n>  src/qcam/meson.build                          |  2 +\n>  4 files changed, 76 insertions(+)\n> \n> diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc\n> index c5302040..6b08395a 100644\n> --- a/src/qcam/assets/feathericons/feathericons.qrc\n> +++ b/src/qcam/assets/feathericons/feathericons.qrc\n> @@ -3,9 +3,11 @@\n>  <qresource>\n>         <file>aperture.svg</file>\n>         <file>camera-off.svg</file>\n> +       <file>file.svg</file>\n>         <file>play-circle.svg</file>\n>         <file>save.svg</file>\n>         <file>stop-circle.svg</file>\n>         <file>x-circle.svg</file>\n> +       <file>x-square.svg</file>\n>  </qresource>\n>  </RCC>\n> diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp\n> index adeb3181..e133b618 100644\n> --- a/src/qcam/main_window.cpp\n> +++ b/src/qcam/main_window.cpp\n> @@ -20,6 +20,7 @@\n>  #include <QImage>\n>  #include <QImageWriter>\n>  #include <QInputDialog>\n> +#include <QMessageBox>\n>  #include <QMutexLocker>\n>  #include <QStandardPaths>\n>  #include <QStringList>\n> @@ -232,6 +233,13 @@ int MainWindow::createToolbars()\n>         saveRaw_ = action;\n>  #endif\n>  \n> +       /* Open Script... action. */\n> +       action = toolbar_->addAction(QIcon::fromTheme(\"document-open\",\n> +                                                     QIcon(\":file.svg\")),\n> +                                    \"Open Capture Script\");\n> +       connect(action, &QAction::triggered, this, &MainWindow::chooseScript);\n> +       scriptExecAction_ = action;\n> +\n>         return 0;\n>  }\n>  \n> @@ -255,6 +263,58 @@ void MainWindow::updateTitle()\n>         setWindowTitle(title_ + \" : \" + QString::number(fps, 'f', 2) + \" fps\");\n>  }\n>  \n> +/**\n> + * \\brief Load a capture script for handling the capture session.\n> + *\n> + * If already capturing, it would restart the capture.\n> + */\n> +void MainWindow::chooseScript()\n> +{\n> +       if (script_) {\n> +               /*\n> +                * This is the second valid press of load script button,\n> +                * It indicates stopping, Stop and set button for new script.\n> +                */\n> +               script_.reset();\n> +               scriptExecAction_->setIcon(QIcon::fromTheme(\"document-open\",\n> +                                                           QIcon(\":file.svg\")));\n> +               scriptExecAction_->setText(\"Open Capture Script\");\n> +               return;\n> +       }\n> +\n> +       QString scriptFile = QFileDialog::getOpenFileName(this, \"Open Capture Script\", QDir::currentPath(),\n> +                                                         \"Capture Script (*.yaml)\");\n> +       if (scriptFile.isEmpty())\n> +               return;\n> +\n> +       /* If we are already capturing,\n> +        * stop so we don't have stuck image in viewfinder. */\n\nOur coding style uses block quotes with /* and */ on their own lines.\n\n\t/*\n\t * If we are already capturing, stop so we don't have a stuck\n\t * image in the viewfinder.\n\t */\n\nWhat causes a stuck image? Is it while the script is being loaded and\nparsed?\n\nIt seems reasonable to stop as we're going to have to do a restart\nanyway.\n\n\n> +       bool wasCapturing_ = isCapturing_;\n\nLocal variables don't use the _ at the end. That signifies that the\nvariable is a class variable.\n\nWith those fixed, you can add:\n\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> +       if(isCapturing_)\n> +               toggleCapture(false);\n> +\n> +       script_ = std::make_unique<CaptureScript>(camera_, scriptFile.toStdString());\n> +       if (!script_->valid()) {\n> +               script_.reset();\n> +               QMessageBox::critical(this, \"Invalid Script\",\n> +                                             \"Couldn't load the capture script\");\n> +               if(wasCapturing_)\n> +                       toggleCapture(true);\n> +               return;\n> +       }\n> +\n> +       /*\n> +        * Valid script verified\n> +        * Set the button to indicate stopping availibility.\n> +        */\n> +       scriptExecAction_->setIcon(QIcon(\":x-square.svg\"));\n> +       scriptExecAction_->setText(\"Stop Script execution\");\n> +\n> +       /* Start capture again if we were capturing before. */\n> +       if(wasCapturing_)\n> +               toggleCapture(true);\n> +}\n> +\n>  /* -----------------------------------------------------------------------------\n>   * Camera Selection\n>   */\n> @@ -510,6 +570,7 @@ int MainWindow::startCapture()\n>         previousFrames_ = 0;\n>         framesCaptured_ = 0;\n>         lastBufferTime_ = 0;\n> +       queueCount_ = 0;\n>  \n>         ret = camera_->start();\n>         if (ret) {\n> @@ -789,5 +850,10 @@ void MainWindow::renderComplete(FrameBuffer *buffer)\n>  \n>  int MainWindow::queueRequest(Request *request)\n>  {\n> +       if (script_)\n> +               request->controls() = script_->frameControls(queueCount_);\n> +\n> +       queueCount_++;\n> +\n>         return camera_->queueRequest(request);\n>  }\n> diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h\n> index c3e4b665..2cdf7169 100644\n> --- a/src/qcam/main_window.h\n> +++ b/src/qcam/main_window.h\n> @@ -26,6 +26,7 @@\n>  #include <libcamera/request.h>\n>  #include <libcamera/stream.h>\n>  \n> +#include \"../cam/capture_script.h\"\n>  #include \"../cam/stream_options.h\"\n>  #include \"viewfinder.h\"\n>  \n> @@ -86,11 +87,14 @@ private:\n>         void processHotplug(HotplugEvent *e);\n>         void processViewfinder(libcamera::FrameBuffer *buffer);\n>  \n> +       void chooseScript();\n> +\n>         /* UI elements */\n>         QToolBar *toolbar_;\n>         QAction *startStopAction_;\n>         QComboBox *cameraCombo_;\n>         QAction *saveRaw_;\n> +       QAction *scriptExecAction_;\n>         ViewFinder *viewfinder_;\n>  \n>         QIcon iconPlay_;\n> @@ -124,6 +128,8 @@ private:\n>         QElapsedTimer frameRateInterval_;\n>         uint32_t previousFrames_;\n>         uint32_t framesCaptured_;\n> +       uint32_t queueCount_;\n>  \n>         std::vector<std::unique_ptr<libcamera::Request>> requests_;\n> +       std::unique_ptr<CaptureScript> script_;\n>  };\n> diff --git a/src/qcam/meson.build b/src/qcam/meson.build\n> index c46f4631..67074252 100644\n> --- a/src/qcam/meson.build\n> +++ b/src/qcam/meson.build\n> @@ -15,6 +15,7 @@ endif\n>  qcam_enabled = true\n>  \n>  qcam_sources = files([\n> +    '../cam/capture_script.cpp',\n>      '../cam/image.cpp',\n>      '../cam/options.cpp',\n>      '../cam/stream_options.cpp',\n> @@ -37,6 +38,7 @@ qcam_resources = files([\n>  qcam_deps = [\n>      libatomic,\n>      libcamera_public,\n> +    libyaml,\n>      qt5_dep,\n>  ]\n>  \n> -- \n> 2.25.1\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 609B6BE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri,  1 Jul 2022 17:15:38 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 99E866564E;\n\tFri,  1 Jul 2022 19:15:37 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A526E60552\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri,  1 Jul 2022 19:15:36 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 1F38025C;\n\tFri,  1 Jul 2022 19:15:36 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1656695737;\n\tbh=z8M4Q0EUwgx6/Vd0AzD5+ZkEdlJx1l3zdHR8oY3UfHI=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=13+b8SqFX99DxVLLq1GfZGs3UJUvASioUxr/3Yl8BYDoR1Ei2hEbwhSwipbD+zjA/\n\t2sYrAjvOXlha1oKqL2U0RY4dufXvLPR0Qx8LrRPcBxXkHs/lk2bXw+yz3+HztQyjWX\n\twC3/LU4Iqa6tpMs/1Nh6ojSE7liw9V2rF1rnehTUowTT6zanF7zSa4KpxV3M9nr7XP\n\tMs8HXl8gDw3LbvF61IZGtDG9Gh/4pgH7/3cMPi+pTgObD97ztQBBoIhO+W9tDKbZry\n\tsKEsHBlQ6V+shKKG7K89CtEB716ZocyB921E/a/7vMk/V9pFTtcbKXpLAzys//oWKI\n\tH/oci1QmvuIPA==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1656695736;\n\tbh=z8M4Q0EUwgx6/Vd0AzD5+ZkEdlJx1l3zdHR8oY3UfHI=;\n\th=In-Reply-To:References:Subject:From:To:Date:From;\n\tb=LwbwfNrCy06Ga6I21jsH5k1mG2oopO2vd7lcVpYFgitNRvOCJ0dLjohZAUA+476ds\n\t4WaY0133Hcg15Sz57Abi52zqWdVjwD/M/ODMDz8aJsK2DmOPfZTMDzelZwOSJVk49B\n\tajAuo8G1L0nX3ddLGSbCjKoGSBWQ3UahZ1c8JLRg="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"LwbwfNrC\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20220627030159.30730-3-utkarsh02t@gmail.com>","References":"<20220627030159.30730-1-utkarsh02t@gmail.com>\n\t<20220627030159.30730-3-utkarsh02t@gmail.com>","To":"Utkarsh Tiwari <utkarsh02t@gmail.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Fri, 01 Jul 2022 18:15:33 +0100","Message-ID":"<165669573360.1516045.12584394031188499896@Monstersaurus>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH v3 2/3] qcam: Add a GUI way to use\n\tcapture script","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]