[libcamera-devel] [PATCH v5 2/3] qcam: Add a GUI way to use capture script

Utkarsh Tiwari utkarsh02t at gmail.com
Tue Jul 26 21:41:22 CEST 2022


Implement an Open Capture Script button which would allow the user
to open a Capture Script (*.yaml).
This button has two states :
    - Open Capture Script
    - Stop the execution of current capture script

When being clicked in open state, present them with a QFileDialog to
allow user to select a single file.

Introduce a queueCount_ to keep track of the requests queued.

When stopping the execution of the capture script the queueCount_ is not
reseted and the capture is continues as it is (i.e it is not stopped or
restarted).

Requests are queued with any controls the script matching the current
queueCount_.

Signed-off-by: Utkarsh Tiwari <utkarsh02t at gmail.com>
Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
---
 Changes from v4
	- Reworded the commit message to clarify button states and
	queueCount_ reseting.

 src/qcam/assets/feathericons/feathericons.qrc |  2 +
 src/qcam/main_window.cpp                      | 68 +++++++++++++++++++
 src/qcam/main_window.h                        |  6 ++
 src/qcam/meson.build                          |  2 +
 4 files changed, 78 insertions(+)

diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc
index c5302040..6b08395a 100644
--- a/src/qcam/assets/feathericons/feathericons.qrc
+++ b/src/qcam/assets/feathericons/feathericons.qrc
@@ -3,9 +3,11 @@
 <qresource>
 	<file>aperture.svg</file>
 	<file>camera-off.svg</file>
+	<file>file.svg</file>
 	<file>play-circle.svg</file>
 	<file>save.svg</file>
 	<file>stop-circle.svg</file>
 	<file>x-circle.svg</file>
+	<file>x-square.svg</file>
 </qresource>
 </RCC>
diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp
index 4e773c31..9dc96fbb 100644
--- a/src/qcam/main_window.cpp
+++ b/src/qcam/main_window.cpp
@@ -20,6 +20,7 @@
 #include <QImage>
 #include <QImageWriter>
 #include <QInputDialog>
+#include <QMessageBox>
 #include <QMutexLocker>
 #include <QStandardPaths>
 #include <QStringList>
@@ -233,6 +234,13 @@ int MainWindow::createToolbars()
 	saveRaw_ = action;
 #endif
 
+	/* Open Script... action. */
+	action = toolbar_->addAction(QIcon::fromTheme("document-open",
+						      QIcon(":file.svg")),
+				     "Open Capture Script");
+	connect(action, &QAction::triggered, this, &MainWindow::chooseScript);
+	scriptExecAction_ = action;
+
 	return 0;
 }
 
@@ -256,6 +264,60 @@ void MainWindow::updateTitle()
 	setWindowTitle(title_ + " : " + QString::number(fps, 'f', 2) + " fps");
 }
 
+/**
+ * \brief Load a capture script for handling the capture session.
+ *
+ * If already capturing, it would restart the capture.
+ */
+void MainWindow::chooseScript()
+{
+	if (script_) {
+		/*
+		 * This is the second valid press of load script button,
+		 * It indicates stopping, Stop and set button for new script.
+		 */
+		script_.reset();
+		scriptExecAction_->setIcon(QIcon::fromTheme("document-open",
+							    QIcon(":file.svg")));
+		scriptExecAction_->setText("Open Capture Script");
+		return;
+	}
+
+	QString scriptFile = QFileDialog::getOpenFileName(this, "Open Capture Script", QDir::currentPath(),
+							  "Capture Script (*.yaml)");
+	if (scriptFile.isEmpty())
+		return;
+
+	/*
+	 * If we are already capturing,
+	 * stop so we don't have stuck image in viewfinder.
+	 */
+	bool wasCapturing = isCapturing_;
+	if (isCapturing_)
+		toggleCapture(false);
+
+	script_ = std::make_unique<CaptureScript>(camera_, scriptFile.toStdString());
+	if (!script_->valid()) {
+		script_.reset();
+		QMessageBox::critical(this, "Invalid Script",
+				      "Couldn't load the capture script");
+		if (wasCapturing)
+			toggleCapture(true);
+		return;
+	}
+
+	/*
+	 * Valid script verified
+	 * Set the button to indicate stopping availibility.
+	 */
+	scriptExecAction_->setIcon(QIcon(":x-square.svg"));
+	scriptExecAction_->setText("Stop Script execution");
+
+	/* Start capture again if we were capturing before. */
+	if (wasCapturing)
+		toggleCapture(true);
+}
+
 /* -----------------------------------------------------------------------------
  * Camera Selection
  */
@@ -511,6 +573,7 @@ int MainWindow::startCapture()
 	previousFrames_ = 0;
 	framesCaptured_ = 0;
 	lastBufferTime_ = 0;
+	queueCount_ = 0;
 
 	ret = camera_->start();
 	if (ret) {
@@ -790,5 +853,10 @@ void MainWindow::renderComplete(FrameBuffer *buffer)
 
 int MainWindow::queueRequest(Request *request)
 {
+	if (script_)
+		request->controls() = script_->frameControls(queueCount_);
+
+	queueCount_++;
+
 	return camera_->queueRequest(request);
 }
diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h
index bc844711..eb398c1d 100644
--- a/src/qcam/main_window.h
+++ b/src/qcam/main_window.h
@@ -26,6 +26,7 @@
 #include <QQueue>
 #include <QTimer>
 
+#include "../cam/capture_script.h"
 #include "../cam/stream_options.h"
 
 #include "viewfinder.h"
@@ -87,11 +88,14 @@ private:
 	void processHotplug(HotplugEvent *e);
 	void processViewfinder(libcamera::FrameBuffer *buffer);
 
+	void chooseScript();
+
 	/* UI elements */
 	QToolBar *toolbar_;
 	QAction *startStopAction_;
 	QComboBox *cameraCombo_;
 	QAction *saveRaw_;
+	QAction *scriptExecAction_;
 	ViewFinder *viewfinder_;
 
 	QIcon iconPlay_;
@@ -125,6 +129,8 @@ private:
 	QElapsedTimer frameRateInterval_;
 	uint32_t previousFrames_;
 	uint32_t framesCaptured_;
+	uint32_t queueCount_;
 
 	std::vector<std::unique_ptr<libcamera::Request>> requests_;
+	std::unique_ptr<CaptureScript> script_;
 };
diff --git a/src/qcam/meson.build b/src/qcam/meson.build
index c46f4631..67074252 100644
--- a/src/qcam/meson.build
+++ b/src/qcam/meson.build
@@ -15,6 +15,7 @@ endif
 qcam_enabled = true
 
 qcam_sources = files([
+    '../cam/capture_script.cpp',
     '../cam/image.cpp',
     '../cam/options.cpp',
     '../cam/stream_options.cpp',
@@ -37,6 +38,7 @@ qcam_resources = files([
 qcam_deps = [
     libatomic,
     libcamera_public,
+    libyaml,
     qt5_dep,
 ]
 
-- 
2.25.1



More information about the libcamera-devel mailing list