Show a patch.

GET /api/1.1/patches/16373/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 16373,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/16373/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/16373/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api",
        "name": "libcamera",
        "link_name": "libcamera",
        "list_id": "libcamera_core",
        "list_email": "libcamera-devel@lists.libcamera.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20220627030159.30730-3-utkarsh02t@gmail.com>",
    "date": "2022-06-27T03:01:58",
    "name": "[libcamera-devel,v3,2/3] qcam: Add a GUI way to use capture script",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "40af6fb54e2a9c83fd664e70edae87a4c8a5fac6",
    "submitter": {
        "id": 114,
        "url": "https://patchwork.libcamera.org/api/1.1/people/114/?format=api",
        "name": "Utkarsh Tiwari",
        "email": "utkarsh02t@gmail.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/16373/mbox/",
    "series": [
        {
            "id": 3220,
            "url": "https://patchwork.libcamera.org/api/1.1/series/3220/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3220",
            "date": "2022-06-27T03:01:56",
            "name": "Introduce capture scripts to qcam",
            "version": 3,
            "mbox": "https://patchwork.libcamera.org/series/3220/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/16373/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/16373/checks/",
    "tags": {},
    "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 DFE38BD808\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 27 Jun 2022 03:02:16 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A01F26563B;\n\tMon, 27 Jun 2022 05:02:16 +0200 (CEST)",
            "from mail-pf1-x434.google.com (mail-pf1-x434.google.com\n\t[IPv6:2607:f8b0:4864:20::434])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id AFD3B65633\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 27 Jun 2022 05:02:14 +0200 (CEST)",
            "by mail-pf1-x434.google.com with SMTP id w6so7720528pfw.5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSun, 26 Jun 2022 20:02:14 -0700 (PDT)",
            "from localhost.localdomain\n\t([2406:3003:2005:1c27:cf57:31af:7925:f9e6])\n\tby smtp.gmail.com with ESMTPSA id\n\ts7-20020aa78d47000000b0051bba89c2bcsm5899378pfe.58.2022.06.26.20.02.10\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tSun, 26 Jun 2022 20:02:11 -0700 (PDT)"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1656298936;\n\tbh=kchz076yAq7g5k6a5eerV9zYjh5cFKK+MXG5bltsbew=;\n\th=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=UuaY2fWL0D7eXWwJ5MK3DqsJOozLhiILt/i3fTQupzxKyriVrj9vQKmSfq6pk0d84\n\t4MzqmrwpJQ7UxO78r36PenU/JU+GLxYPf8e+DltuE3rpDIfWIc+PgJp1nKQf8B4erX\n\tXSHeA7PovUZPTlEAiEHiJc5gug9pVIJdYsPf0q68JYuJsxrH4rXAkXlJ3CWbzXN4EZ\n\tCqU1hzJz+S2GsoVBRl1weSZ1t8Wza/fEuUHn89ukAOmT7l7ARAbCCvJ+zotNBQQxIY\n\tjl+pn/G4dbmIEF1+VAY6HjXSiUFPJ9mzV8otLu13f7FP1ikRMtcb/PJRla68SgMMRX\n\tdeAtyVHamogsQ==",
            "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references\n\t:mime-version:content-transfer-encoding;\n\tbh=GNK6U/WvuXK4SXU0wPhP4gevq0vBN26GKYSlu4X1K6s=;\n\tb=CsFcpyPbM1eHK7r5RZr32Tpc58+2NMzXrMc3WD7g6q2Rd3EuG9FmFBJZhGN4ZuAW28\n\t78joMi3eZi63n0uo1IJUMPTuX4xL6DOy9Xwp4swuKABrH/ajF43Jd5svceru784Aszv5\n\tNubpSxOSW7IHNMkfV88rZ9k4OeFJ4CpmOjlhVhFyIKaYy2YJP2jgCEl5lpGdqHMqmQgP\n\tpgiA/cEOSH1IIhziQ4UCb31QdPccAieTrAWgTIUZ2v/HWjaMjE6ir0edNLPUg6u0KjOt\n\tKyO1SWyvuL97sRwn9Hee4z/7ziZcj80S0XwYWCUHR+NjK6X3YycncjzTjY51BCX3Rnhs\n\tFJ5Q=="
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"CsFcpyPb\"; dkim-atps=neutral",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references:mime-version:content-transfer-encoding;\n\tbh=GNK6U/WvuXK4SXU0wPhP4gevq0vBN26GKYSlu4X1K6s=;\n\tb=zh2MjFjqgpOn+opgJCkkjyj11Tee9SwaDWVKcVzLG6POF6Xuabtx36oKYsAFF0105Y\n\tUAjW9c9yvBievrGYzAD7ATIWXDGuIJXKHaxpjaUxWd+YVqUns77rIgWKj6V6+y716Meu\n\ttkXRAdLFsmO4UaoPIi/tvQDx28RKYXxZzvDmWesAoODazrLTtI0D7XkYltJs70TK6p3i\n\ttiMc5yKtkMAm5Wopt7tpr0b2muhN4pVnONEVdUzdJZC2x518f9rKvtvRbBca0vxfPhAp\n\tI2IIWHPLLQOu87+4j7HmJV9T8vSXa14QfH6k1olf9ddZiZU1hyfljU0C+FxFcEvrKjbG\n\tKGbQ==",
        "X-Gm-Message-State": "AJIora+7KmxMxo4wufsqI+DrGhzC3XJ+eGSPfI1nYpUYEHKjZBeGCNoU\n\t3ZBf5mrLNMLv2QjbonbKHjjVkZIU8bbsHA==",
        "X-Google-Smtp-Source": "AGRyM1sHQNuYCrNGpUTVljd67vJymso+VPaR4J0FHDQ8FbLTWDBsdByxz3rjVx8ljRq2ZKX8OZbJZA==",
        "X-Received": "by 2002:a05:6a00:ad2:b0:4f1:2734:a3d9 with SMTP id\n\tc18-20020a056a000ad200b004f12734a3d9mr12259241pfl.61.1656298932972; \n\tSun, 26 Jun 2022 20:02:12 -0700 (PDT)",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Mon, 27 Jun 2022 11:01:58 +0800",
        "Message-Id": "<20220627030159.30730-3-utkarsh02t@gmail.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20220627030159.30730-1-utkarsh02t@gmail.com>",
        "References": "<20220627030159.30730-1-utkarsh02t@gmail.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH v3 2/3] qcam: Add a GUI way to use capture\n\tscript",
        "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": "Utkarsh Tiwari via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>",
        "Reply-To": "Utkarsh Tiwari <utkarsh02t@gmail.com>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "Implement an Open Capture Script button which would allow the user\nto open a Capture Script (*.yaml).\nThis button has two states Open and Stop.\n\nOpen state allows user to load a capture script.\nWhen clicked in open state present them with a QFileDialog\nto allow user to select a single file.\n\nStop state stops the execution of the current capture script.\n\nIntroduce a queueCount_ to keep track of the requests queued.\n\nWhen stopping the execution no count is reset and the\ncapture continues as it is.\n\nRequests are queued with any controls the script matching\nthe current queueCount_\n\nSigned-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(+)",
    "diff": "diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc\nindex 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 \t<file>aperture.svg</file>\n \t<file>camera-off.svg</file>\n+\t<file>file.svg</file>\n \t<file>play-circle.svg</file>\n \t<file>save.svg</file>\n \t<file>stop-circle.svg</file>\n \t<file>x-circle.svg</file>\n+\t<file>x-square.svg</file>\n </qresource>\n </RCC>\ndiff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp\nindex 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 \tsaveRaw_ = action;\n #endif\n \n+\t/* Open Script... action. */\n+\taction = toolbar_->addAction(QIcon::fromTheme(\"document-open\",\n+\t\t\t\t\t\t      QIcon(\":file.svg\")),\n+\t\t\t\t     \"Open Capture Script\");\n+\tconnect(action, &QAction::triggered, this, &MainWindow::chooseScript);\n+\tscriptExecAction_ = action;\n+\n \treturn 0;\n }\n \n@@ -255,6 +263,58 @@ void MainWindow::updateTitle()\n \tsetWindowTitle(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+\tif (script_) {\n+\t\t/*\n+\t\t * This is the second valid press of load script button,\n+\t\t * It indicates stopping, Stop and set button for new script.\n+\t\t */\n+\t\tscript_.reset();\n+\t\tscriptExecAction_->setIcon(QIcon::fromTheme(\"document-open\",\n+\t\t\t\t\t\t\t    QIcon(\":file.svg\")));\n+\t\tscriptExecAction_->setText(\"Open Capture Script\");\n+\t\treturn;\n+\t}\n+\n+\tQString scriptFile = QFileDialog::getOpenFileName(this, \"Open Capture Script\", QDir::currentPath(),\n+\t\t\t\t\t\t\t  \"Capture Script (*.yaml)\");\n+\tif (scriptFile.isEmpty())\n+\t\treturn;\n+\n+\t/* If we are already capturing,\n+\t * stop so we don't have stuck image in viewfinder. */\n+\tbool wasCapturing_ = isCapturing_;\n+\tif(isCapturing_)\n+\t\ttoggleCapture(false);\n+\n+\tscript_ = std::make_unique<CaptureScript>(camera_, scriptFile.toStdString());\n+\tif (!script_->valid()) {\n+\t\tscript_.reset();\n+\t\tQMessageBox::critical(this, \"Invalid Script\",\n+\t\t\t\t\t      \"Couldn't load the capture script\");\n+\t\tif(wasCapturing_)\n+\t\t\ttoggleCapture(true);\n+\t\treturn;\n+\t}\n+\n+\t/*\n+\t * Valid script verified\n+\t * Set the button to indicate stopping availibility.\n+\t */\n+\tscriptExecAction_->setIcon(QIcon(\":x-square.svg\"));\n+\tscriptExecAction_->setText(\"Stop Script execution\");\n+\n+\t/* Start capture again if we were capturing before. */\n+\tif(wasCapturing_)\n+\t\ttoggleCapture(true);\n+}\n+\n /* -----------------------------------------------------------------------------\n  * Camera Selection\n  */\n@@ -510,6 +570,7 @@ int MainWindow::startCapture()\n \tpreviousFrames_ = 0;\n \tframesCaptured_ = 0;\n \tlastBufferTime_ = 0;\n+\tqueueCount_ = 0;\n \n \tret = camera_->start();\n \tif (ret) {\n@@ -789,5 +850,10 @@ void MainWindow::renderComplete(FrameBuffer *buffer)\n \n int MainWindow::queueRequest(Request *request)\n {\n+\tif (script_)\n+\t\trequest->controls() = script_->frameControls(queueCount_);\n+\n+\tqueueCount_++;\n+\n \treturn camera_->queueRequest(request);\n }\ndiff --git a/src/qcam/main_window.h b/src/qcam/main_window.h\nindex 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 \tvoid processHotplug(HotplugEvent *e);\n \tvoid processViewfinder(libcamera::FrameBuffer *buffer);\n \n+\tvoid chooseScript();\n+\n \t/* UI elements */\n \tQToolBar *toolbar_;\n \tQAction *startStopAction_;\n \tQComboBox *cameraCombo_;\n \tQAction *saveRaw_;\n+\tQAction *scriptExecAction_;\n \tViewFinder *viewfinder_;\n \n \tQIcon iconPlay_;\n@@ -124,6 +128,8 @@ private:\n \tQElapsedTimer frameRateInterval_;\n \tuint32_t previousFrames_;\n \tuint32_t framesCaptured_;\n+\tuint32_t queueCount_;\n \n \tstd::vector<std::unique_ptr<libcamera::Request>> requests_;\n+\tstd::unique_ptr<CaptureScript> script_;\n };\ndiff --git a/src/qcam/meson.build b/src/qcam/meson.build\nindex 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",
    "prefixes": [
        "libcamera-devel",
        "v3",
        "2/3"
    ]
}