Show a patch.

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

{
    "id": 17099,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/17099/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/17099/",
    "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": "<20220812124651.27496-4-utkarsh02t@gmail.com>",
    "date": "2022-08-12T12:46:43",
    "name": "[libcamera-devel,v2,03/11] qcam: Add GUI way to change control values",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "1362fae24a8d9e7f6cb37ad9d954694fbfc52ef6",
    "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/17099/mbox/",
    "series": [
        {
            "id": 3410,
            "url": "https://patchwork.libcamera.org/api/1.1/series/3410/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3410",
            "date": "2022-08-12T12:46:40",
            "name": "Introduce control interaction to qcam",
            "version": 2,
            "mbox": "https://patchwork.libcamera.org/series/3410/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/17099/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/17099/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 DDA1DBE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 12 Aug 2022 12:47:12 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 9B3A663334;\n\tFri, 12 Aug 2022 14:47:12 +0200 (CEST)",
            "from mail-pg1-x535.google.com (mail-pg1-x535.google.com\n\t[IPv6:2607:f8b0:4864:20::535])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 83CAB63328\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 12 Aug 2022 14:47:10 +0200 (CEST)",
            "by mail-pg1-x535.google.com with SMTP id 12so720158pga.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 12 Aug 2022 05:47:10 -0700 (PDT)",
            "from localhost.localdomain ([2404:bd00:3:dc0d:d8e:96a2:2dbe:5a83])\n\tby smtp.gmail.com with ESMTPSA id\n\te6-20020a17090a728600b001f069352d73sm1431785pjg.25.2022.08.12.05.47.06\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tFri, 12 Aug 2022 05:47:08 -0700 (PDT)"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1660308432;\n\tbh=naxmq4pAh7h/eoNWdQ3P0xc3xcUhSSB+XP1uNsOQW+A=;\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=MXAQKDWF5rFOtxQycOfwClgyCZ2wGQToF7oA8eDk3mG+w4l/TLI1C2v4E9S+ba6Wz\n\t2on4wivTZfy0FCObe8p90MNea5C+UKdlcRYtVLukhFV5TqOQUepYBnNdTutn5QAAnp\n\t65/GwXSd9Ovgbpxw/dv/rzSv0mqju039IAyC92Mb3wQM5jZF8wRSDCnNf5yzkaFNA9\n\tgGBfOISk9xBeOeT1Pvk+FPKk7f1LBC9qmrD1HySh7fe4tDBHaMPkoqtpO1od178J2+\n\tFYsZgTyPv1uLDLyy7dDQqV8QmgY3ENk2B0ticR7+mUW+eWYTSp0nufM0dxIpwxrexH\n\tkE3xzPtc8+1bw==",
            "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112;\n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:from:to:cc;\n\tbh=x7UaddQYAA5WjaMHvFJtpiORxx5fo0lFeM0wW38ro28=;\n\tb=pOA0+LdROBGPYHLgAHXZUj6gk8/IuDmkwZg7UuH5NVtY0JBlooGLGV+lpGiV1aniRH\n\tw5fpAw299Y0UxLktrwSFzyKHVG07fgTgsDuH1gJZOP5oZ7ryES7wS/W5FcBXaIV7WyEa\n\ti1w8lP6ZODXQE0GosyrwtVRAPyfK1Fe7SbQ3FsZIWyZbBgGHsT/K+7ApJvZf/c38IH3b\n\t6Ck7ioZbsUIyfaN+3gCYuX2yNcaXlUcuAa6ClZorC9JLyrLpl3Y9aXVmSJ4BF7gEQXsi\n\tSCd05KNx/Na3UC8YblQqHUprTztbTk3c4BuB9Wvm1GsBUtEqgTPR/5OO0v9UvDYIYzD/\n\tRKDQ=="
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"pOA0+LdR\"; dkim-atps=neutral",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc;\n\tbh=x7UaddQYAA5WjaMHvFJtpiORxx5fo0lFeM0wW38ro28=;\n\tb=k5me8ZxziIsRZgzfW5lM35KRhI7CdGgdjcauignnWWCoBcmBQgDtEZlKKsv/HjLKW9\n\t3WtmhxltbT7b/x7C8Yg1E+9swo1kNbO1toDtI4ENbRO8b4K88t7V2hXjA1aFOl7Rvfaq\n\tBA5EjALtCBd+1N5P8ZcAl+zYRCpoXlLvK6xBtB6H0sg76T+UmccnGGW0mOwb+wxWTSQ5\n\tzj1TaJMy1cYeOvv+R/IL7K/bRXIth9Lzeu2Nf/2401UljVxIZ3VdwqIpkTPWBlz3oiXl\n\tTJBHqT2Z52GlAFLUgstc0Tff8/pjyU18oiTQpbohjgn+KlfMwXaABmYFQpp+ynMD5jbK\n\tMzIw==",
        "X-Gm-Message-State": "ACgBeo2aYPf4dcWywaimHKD+PvfzIb39Aw0T6SAMNRGsmr8f61M6+IKg\n\tFdvhf+UFLbY0LdSlDjzkNzXkFTUENBI=",
        "X-Google-Smtp-Source": "AA6agR77vjzNilKlD0qLIUc7/cUoNd0now+5LKy6aHVu1a5mWswxkRRQUpiRuolRdBc4AJekC26zsw==",
        "X-Received": "by 2002:a05:6a00:1705:b0:52f:6028:5c33 with SMTP id\n\th5-20020a056a00170500b0052f60285c33mr3789379pfc.29.1660308428646; \n\tFri, 12 Aug 2022 05:47:08 -0700 (PDT)",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Fri, 12 Aug 2022 18:16:43 +0530",
        "Message-Id": "<20220812124651.27496-4-utkarsh02t@gmail.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20220812124651.27496-1-utkarsh02t@gmail.com>",
        "References": "<20220812124651.27496-1-utkarsh02t@gmail.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH v2 03/11] qcam: Add GUI way to change\n\tcontrol values",
        "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": "Introduce GUI ability to change control values currently only for\nboolean control types.\n\nEach of the ControlFrame first identifies the type of control it is and\nthen accordingly constructs the widget that would help the user to\ninteract with it.\n\nThe current model of connecting the controls change info to the\nMaindWindow is as follows.\n\n            +-----------+\n            |Main Window|\n            +-----^-----+\n                  |\n                  |\n          +-------+-------+\n          |Settings Dialog|\n          +--^----^------^+\n             |    |      |\n      +------+    |      +-----+\n      |           |            |\n+-----+---+  +----+----+  +----+----+\n|Various  |  | Tabs    |  |   ...   |\n++---+----+  +---+---+-+  ++--+--+--+\n |   |           |   |     |  |  |\n |   |           |   |     |  |  |\n |   |           |   |     |  |  |\n\nImplement a controlLatch mechanism to update thec ontrolList. As the\nSettings QDialog and ControlFrame processing the change in control lie\nin the same thread there would be no race to access the ControlList.\n\nThis allows us to use to shared_ptr to the ControlList\nto help us the same function from MaindWindow::queueRequest()\nand the controlListChanged() signal.\n\nWe clear the controlList_ in MainWindow::queueRequest() and not in the\nMainWindow::controlListLatch() because when in controlListLatch() we\nneed to clear it when we don't have script nor the alerted by the signal.\nBut what Can happen is that we have controlListLatch() is triggered by the\nsignal and then immediately called by the queueRequest() which would\nclear the controlList and it would not end up getting set.\n\nSigned-off-by: Utkarsh Tiwari <utkarsh02t@gmail.com>\n---\nDifference from v1:\n\t1. Now using infromScriptRest() to change the script button state.\n src/qcam/main_window.cpp            | 40 +++++++++++++++--\n src/qcam/main_window.h              |  3 ++\n src/qcam/settings/control_frame.cpp | 70 +++++++++++++++++++++++++++++\n src/qcam/settings/control_frame.h   | 11 +++++\n src/qcam/settings/controls_tab.cpp  | 19 +++++++-\n src/qcam/settings/controls_tab.h    | 10 +++++\n src/qcam/settings/settings_dialog.h |  5 +++\n 7 files changed, 154 insertions(+), 4 deletions(-)",
    "diff": "diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp\nindex 7861c34b..87cdad82 100644\n--- a/src/qcam/main_window.cpp\n+++ b/src/qcam/main_window.cpp\n@@ -101,7 +101,7 @@ private:\n MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options)\n \t: saveRaw_(nullptr), cameraSelectorDialog_(nullptr), options_(options),\n \t  cm_(cm), allocator_(nullptr), isCapturing_(false), captureRaw_(false),\n-\t  firstCameraSelect_(true)\n+\t  firstCameraSelect_(true), controlList_(ControlList())\n {\n \tint ret;\n \n@@ -276,6 +276,8 @@ void MainWindow::openSettingsDialog()\n \t}\n \n \tsettingsDialog_ = new SettingsDialog(camera_, this);\n+\tconnect(settingsDialog_, &SettingsDialog::controlListChanged,\n+\t\tthis, &MainWindow::controlListLatch);\n \tsettingsDialog_->show();\n }\n \n@@ -863,10 +865,42 @@ void MainWindow::renderComplete(FrameBuffer *buffer)\n \n int MainWindow::queueRequest(Request *request)\n {\n-\tif (script_)\n-\t\trequest->controls() = script_->frameControls(queueCount_);\n+\t/*\n+\t * Call the controlListLatch with a nullptr to indicate that it\n+\t * has been called by us and not by the signal.\n+\t */\n+\n+\tcontrolListLatch(nullptr);\n+\trequest->controls() = controlList_;\n+\n+\t/* Clear controlList_ to remove old controls that have been set.*/\n+\tif (controlList_.size())\n+\t\tcontrolList_.clear();\n \n \tqueueCount_++;\n \n \treturn camera_->queueRequest(request);\n }\n+\n+void MainWindow::controlListLatch(std::shared_ptr<const libcamera::ControlList> controlList)\n+{\n+\t/*\n+\t * If we have been given a non-null shared_ptr then it means we\n+\t * have been alerted by the SettingsWindow::controlListChanged signal.\n+\t */\n+\n+\tif (controlList) {\n+\t\tcontrolList_ = *(controlList);\n+\n+\t\t/* Shut down the capture script */\n+\t\tif (script_) {\n+\t\t\tscript_.reset();\n+\t\t\tcameraSelectorDialog_->informScriptReset();\n+\t\t}\n+\n+\t\treturn;\n+\t}\n+\n+\tif (script_)\n+\t\tcontrolList_ = script_->frameControls(queueCount_);\n+}\ndiff --git a/src/qcam/main_window.h b/src/qcam/main_window.h\nindex 856a71b1..8137e736 100644\n--- a/src/qcam/main_window.h\n+++ b/src/qcam/main_window.h\n@@ -75,6 +75,8 @@ private Q_SLOTS:\n \n \tvoid renderComplete(libcamera::FrameBuffer *buffer);\n \n+\tvoid controlListLatch(std::shared_ptr<const libcamera::ControlList> controlList);\n+\n private:\n \tint createToolbars();\n \n@@ -145,4 +147,5 @@ private:\n \tstd::vector<std::unique_ptr<libcamera::Request>> requests_;\n \tstd::unique_ptr<CaptureScript> script_;\n \tstd::string scriptPath_;\n+\tlibcamera::ControlList controlList_;\n };\ndiff --git a/src/qcam/settings/control_frame.cpp b/src/qcam/settings/control_frame.cpp\nindex 79cf67eb..273ce79b 100644\n--- a/src/qcam/settings/control_frame.cpp\n+++ b/src/qcam/settings/control_frame.cpp\n@@ -9,7 +9,9 @@\n \n #include <libcamera/controls.h>\n \n+#include <QCheckBox>\n #include <QFrame>\n+#include <QHBoxLayout>\n #include <QLabel>\n #include <QString>\n #include <QVBoxLayout>\n@@ -30,6 +32,7 @@ ControlFrame::ControlFrame(const ControlId *control,\n \t * ownership to its parent widget.\n \t */\n \tframeVLayout->addWidget(defaultValueLabel());\n+\tframeVLayout->addWidget(controlInteraction());\n \n \tsetFrameStyle(QFrame::StyledPanel);\n }\n@@ -47,6 +50,73 @@ QLabel *ControlFrame::defaultValueLabel(QWidget *parent)\n \treturn defaultValLabel;\n }\n \n+QWidget *ControlFrame::controlInteraction(QWidget *parent)\n+{\n+\tQWidget *containerWidget = new QWidget(parent);\n+\n+\tswitch (control_->type()) {\n+\tcase ControlTypeBool: {\n+\t\tQHBoxLayout *HCheckBoxLayout = new QHBoxLayout(containerWidget);\n+\n+\t\tHCheckBoxLayout->addWidget(new QLabel(\"Enabled :\"));\n+\n+\t\tcontrolCheckBox_ = new QCheckBox;\n+\t\t/*\n+\t\t * In the start we are not sure what is exactly the state of\n+\t\t * the control. Do not assume. Set in partially checked state.\n+\t\t */\n+\t\tcontrolCheckBox_->setCheckState(Qt::PartiallyChecked);\n+\n+\t\tconnect(controlCheckBox_, &QCheckBox::stateChanged,\n+\t\t\tthis, &ControlFrame::notifyControlChange);\n+\n+\t\tHCheckBoxLayout->addWidget(controlCheckBox_);\n+\n+\t\t/* Align it with the name of the control. */\n+\t\tHCheckBoxLayout->setAlignment(Qt::AlignLeft);\n+\t\tHCheckBoxLayout->setMargin(0);\n+\t\treturn containerWidget;\n+\t}\n+\tdefault:\n+\t\treturn (new QLabel(\"Currently Unavailable\"));\n+\t}\n+}\n+\n+/* -----------------------------------------------------------------------------\n+ * Qt Slots\n+ */\n+\n+void ControlFrame::notifyControlChange()\n+{\n+\tControlValue controlValue = ControlValue();\n+\n+\tswitch (control_->type()) {\n+\tcase ControlTypeBool:\n+\n+\t\t/*\n+\t\t * When clicked for the first time, the switch comes from a\n+\t\t * partially checked state. Turn the triset off so we can have\n+\t\t * only enabled and disabled states.\n+\t\t */\n+\t\tcontrolCheckBox_->setTristate(false);\n+\t\t/*\n+\t\t * When this function is invoked, the checkbox can only be in\n+\t\t * the Checked or Unchecked State (after the first time).\n+\t\t */\n+\t\tif (controlCheckBox_->checkState() == Qt::CheckState::Checked)\n+\t\t\tcontrolValue.set<bool>(true);\n+\t\telse\n+\t\t\tcontrolValue.set<bool>(false);\n+\n+\t\tbreak;\n+\tdefault:\n+\t\t/* Nothing to emit so return */\n+\t\treturn;\n+\t}\n+\n+\tQ_EMIT controlChanged(control_, controlValue);\n+}\n+\n /* -----------------------------------------------------------------------------\n  * Helpers\n  */\ndiff --git a/src/qcam/settings/control_frame.h b/src/qcam/settings/control_frame.h\nindex 280f07e0..61005ea5 100644\n--- a/src/qcam/settings/control_frame.h\n+++ b/src/qcam/settings/control_frame.h\n@@ -9,6 +9,7 @@\n \n #include <libcamera/controls.h>\n \n+#include <QCheckBox>\n #include <QFrame>\n #include <QLabel>\n #include <QWidget>\n@@ -23,13 +24,23 @@ public:\n \t\t     QWidget *parent);\n \t~ControlFrame() = default;\n \n+Q_SIGNALS:\n+\tvoid controlChanged(const libcamera::ControlId *controlId,\n+\t\t\t    const libcamera::ControlValue);\n+\n+private Q_SLOTS:\n+\tvoid notifyControlChange();\n+\n private:\n \tconst libcamera::ControlId *control_;\n \tconst libcamera::ControlInfo &controlInfo_;\n \n \t/* Widgets */\n+\tQWidget *controlInteraction(QWidget *parent = nullptr);\n \tQLabel *defaultValueLabel(QWidget *parent = nullptr);\n \n+\tQCheckBox *controlCheckBox_;\n+\n \t/* Helper Hunctions */\n \tQString getDefaultValueQStr();\n };\ndiff --git a/src/qcam/settings/controls_tab.cpp b/src/qcam/settings/controls_tab.cpp\nindex adc24326..0777d708 100644\n--- a/src/qcam/settings/controls_tab.cpp\n+++ b/src/qcam/settings/controls_tab.cpp\n@@ -17,9 +17,11 @@\n \n #include \"control_frame.h\"\n \n+using namespace libcamera;\n+\n ControlsTab::ControlsTab(std::shared_ptr<libcamera::Camera> camera_,\n \t\t\t QWidget *parent)\n-\t: QWidget(parent)\n+\t: QWidget(parent), controlList_(std::make_shared<ControlList>())\n {\n \t/* Main Layout for the tab */\n \tQGridLayout *controlGLayout = new QGridLayout(this);\n@@ -27,6 +29,8 @@ ControlsTab::ControlsTab(std::shared_ptr<libcamera::Camera> camera_,\n \tint controlCount = 0;\n \tfor (auto &[control, info] : camera_->controls()) {\n \t\tControlFrame *controlFrame = new ControlFrame(control, info, this);\n+\t\tconnect(controlFrame, &ControlFrame::controlChanged,\n+\t\t\tthis, &ControlsTab::controlChanged);\n \n \t\tcontrolGLayout->addWidget(controlFrame, controlCount / 2,\n \t\t\t\t\t  controlCount % 2);\n@@ -36,3 +40,16 @@ ControlsTab::ControlsTab(std::shared_ptr<libcamera::Camera> camera_,\n \tif (controlCount == 0)\n \t\tcontrolGLayout->addWidget(new QLabel(\"No controls available\"));\n }\n+\n+/* -----------------------------------------------------------------------------\n+ * Qt Slots\n+ */\n+\n+void ControlsTab::controlChanged(const libcamera::ControlId *controlId,\n+\t\t\t\t const libcamera::ControlValue controlValue)\n+{\n+\tcontrolList_->clear();\n+\n+\tcontrolList_->set(controlId->id(), controlValue);\n+\tQ_EMIT controlListChanged(controlList_);\n+}\ndiff --git a/src/qcam/settings/controls_tab.h b/src/qcam/settings/controls_tab.h\nindex 6a63f334..5bac7d48 100644\n--- a/src/qcam/settings/controls_tab.h\n+++ b/src/qcam/settings/controls_tab.h\n@@ -21,4 +21,14 @@ class ControlsTab : public QWidget\n public:\n \tControlsTab(std::shared_ptr<libcamera::Camera> camera_, QWidget *parent);\n \t~ControlsTab() = default;\n+\n+Q_SIGNALS:\n+\tvoid controlListChanged(const std::shared_ptr<const libcamera::ControlList>);\n+\n+public Q_SLOTS:\n+\tvoid controlChanged(const libcamera::ControlId *controlId,\n+\t\t\t    const libcamera::ControlValue controlValue);\n+\n+private:\n+\tstd::shared_ptr<libcamera::ControlList> controlList_;\n };\ndiff --git a/src/qcam/settings/settings_dialog.h b/src/qcam/settings/settings_dialog.h\nindex c2fa61ea..e6efd876 100644\n--- a/src/qcam/settings/settings_dialog.h\n+++ b/src/qcam/settings/settings_dialog.h\n@@ -32,8 +32,13 @@ public:\n \n \t\tControlsTab *controlsTab = new ControlsTab(camera, this);\n \t\tsettingTabWidget->addTab(controlsTab, \"Controls\");\n+\t\tconnect(controlsTab, &ControlsTab::controlListChanged,\n+\t\t\tthis, &SettingsDialog::controlListChanged);\n \n \t\tsetWindowTitle(\"Settings\");\n \t}\n \t~SettingsDialog() = default;\n+\n+Q_SIGNALS:\n+\tvoid controlListChanged(std::shared_ptr<const libcamera::ControlList>);\n };\n",
    "prefixes": [
        "libcamera-devel",
        "v2",
        "03/11"
    ]
}