[libcamera-devel,v3,2/3] qcam: Add a GUI way to use capture script
diff mbox series

Message ID 20220627030159.30730-3-utkarsh02t@gmail.com
State Superseded
Headers show
Series
  • Introduce capture scripts to qcam
Related show

Commit Message

Utkarsh Tiwari June 27, 2022, 3:01 a.m. UTC
Implement an Open Capture Script button which would allow the user
to open a Capture Script (*.yaml).
This button has two states Open and Stop.

Open state allows user to load a capture script.
When clicked in open state present them with a QFileDialog
to allow user to select a single file.

Stop state stops the execution of the current capture script.

Introduce a queueCount_ to keep track of the requests queued.

When stopping the execution no count is reset and the
capture continues as it is.

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

Signed-off-by: Utkarsh Tiwari <utkarsh02t@gmail.com>
---
 src/qcam/assets/feathericons/feathericons.qrc |  2 +
 src/qcam/main_window.cpp                      | 66 +++++++++++++++++++
 src/qcam/main_window.h                        |  6 ++
 src/qcam/meson.build                          |  2 +
 4 files changed, 76 insertions(+)

Comments

Kieran Bingham July 1, 2022, 5:15 p.m. UTC | #1
Quoting Utkarsh Tiwari via libcamera-devel (2022-06-27 04:01:58)
> Implement an Open Capture Script button which would allow the user
> to open a Capture Script (*.yaml).
> This button has two states Open and Stop.
> 
> Open state allows user to load a capture script.
> When clicked in open state present them with a QFileDialog
> to allow user to select a single file.
> 
> Stop state stops the execution of the current capture script.
> 
> Introduce a queueCount_ to keep track of the requests queued.
> 
> When stopping the execution no count is reset and the
> capture continues as it is.
> 
> Requests are queued with any controls the script matching
> the current queueCount_
> 
> Signed-off-by: Utkarsh Tiwari <utkarsh02t@gmail.com>
> ---
>  src/qcam/assets/feathericons/feathericons.qrc |  2 +
>  src/qcam/main_window.cpp                      | 66 +++++++++++++++++++
>  src/qcam/main_window.h                        |  6 ++
>  src/qcam/meson.build                          |  2 +
>  4 files changed, 76 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 adeb3181..e133b618 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>
> @@ -232,6 +233,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;
>  }
>  
> @@ -255,6 +263,58 @@ 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. */

Our coding style uses block quotes with /* and */ on their own lines.

	/*
	 * If we are already capturing, stop so we don't have a stuck
	 * image in the viewfinder.
	 */

What causes a stuck image? Is it while the script is being loaded and
parsed?

It seems reasonable to stop as we're going to have to do a restart
anyway.


> +       bool wasCapturing_ = isCapturing_;

Local variables don't use the _ at the end. That signifies that the
variable is a class variable.

With those fixed, you can add:


Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

> +       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
>   */
> @@ -510,6 +570,7 @@ int MainWindow::startCapture()
>         previousFrames_ = 0;
>         framesCaptured_ = 0;
>         lastBufferTime_ = 0;
> +       queueCount_ = 0;
>  
>         ret = camera_->start();
>         if (ret) {
> @@ -789,5 +850,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 c3e4b665..2cdf7169 100644
> --- a/src/qcam/main_window.h
> +++ b/src/qcam/main_window.h
> @@ -26,6 +26,7 @@
>  #include <libcamera/request.h>
>  #include <libcamera/stream.h>
>  
> +#include "../cam/capture_script.h"
>  #include "../cam/stream_options.h"
>  #include "viewfinder.h"
>  
> @@ -86,11 +87,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_;
> @@ -124,6 +128,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
>

Patch
diff mbox series

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 adeb3181..e133b618 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>
@@ -232,6 +233,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;
 }
 
@@ -255,6 +263,58 @@  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
  */
@@ -510,6 +570,7 @@  int MainWindow::startCapture()
 	previousFrames_ = 0;
 	framesCaptured_ = 0;
 	lastBufferTime_ = 0;
+	queueCount_ = 0;
 
 	ret = camera_->start();
 	if (ret) {
@@ -789,5 +850,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 c3e4b665..2cdf7169 100644
--- a/src/qcam/main_window.h
+++ b/src/qcam/main_window.h
@@ -26,6 +26,7 @@ 
 #include <libcamera/request.h>
 #include <libcamera/stream.h>
 
+#include "../cam/capture_script.h"
 #include "../cam/stream_options.h"
 #include "viewfinder.h"
 
@@ -86,11 +87,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_;
@@ -124,6 +128,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,
 ]