@@ -18,16 +18,19 @@
#include <QComboBox>
#include <QDialog>
#include <QDialogButtonBox>
+#include <QFileDialog>
#include <QFormLayout>
#include <QLabel>
+#include <QPushButton>
#include <QString>
class CamSelectDialog : public QDialog
{
Q_OBJECT
public:
- CamSelectDialog(libcamera::CameraManager *cameraManager, QWidget *parent)
- : QDialog(parent), cm_(cameraManager)
+ CamSelectDialog(libcamera::CameraManager *cameraManager,
+ bool isScriptRunning, QWidget *parent)
+ : QDialog(parent), cm_(cameraManager), isScriptRunning_(isScriptRunning)
{
/* Use a QFormLayout for the dialog. */
QFormLayout *camSelectDialogLayout = new QFormLayout(this);
@@ -48,6 +51,16 @@ public:
cameraIdComboBox_->currentText().toStdString()));
});
+ captureScriptButton_ = new QPushButton;
+ connect(captureScriptButton_, &QPushButton::clicked,
+ this, &CamSelectDialog::handleCaptureScriptButton);
+
+ /* Display the action that would be performed when button is clicked. */
+ if (isScriptRunning_)
+ captureScriptButton_->setText("Stop");
+ else
+ captureScriptButton_->setText("Open");
+
/* Setup the QDialogButton Box */
QDialogButtonBox *dialogButtonBox =
new QDialogButtonBox(QDialogButtonBox::Ok |
@@ -62,6 +75,7 @@ public:
camSelectDialogLayout->addRow("Camera: ", cameraIdComboBox_);
camSelectDialogLayout->addRow("Location: ", cameraLocation_);
camSelectDialogLayout->addRow("Model: ", cameraModel_);
+ camSelectDialogLayout->addRow("Capture Script: ", captureScriptButton_);
camSelectDialogLayout->addWidget(dialogButtonBox);
}
@@ -72,6 +86,11 @@ public:
return cameraIdComboBox_->currentText().toStdString();
}
+ std::string getCaptureScript()
+ {
+ return scriptPath_;
+ }
+
/* Hotplug / Unplug Support. */
void cameraAdded(libcamera::Camera *camera)
{
@@ -122,11 +141,35 @@ public:
cameraModel_->setText(QString());
}
+ /* Capture script support. */
+ void handleCaptureScriptButton()
+ {
+ if (isScriptRunning_) {
+ Q_EMIT stopCaptureScript();
+ isScriptRunning_ = false;
+ captureScriptButton_->setText("Open");
+ } else {
+ scriptPath_ = QFileDialog::getOpenFileName(this, "Run Capture Script",
+ QDir::currentPath(), "Capture Script (*.yaml)")
+ .toStdString();
+
+ if (!scriptPath_.empty())
+ captureScriptButton_->setText("Loaded");
+ }
+ }
+
+Q_SIGNALS:
+ void stopCaptureScript();
+
private:
libcamera::CameraManager *cm_;
+ bool isScriptRunning_;
+ std::string scriptPath_;
+
/* UI elements. */
QComboBox *cameraIdComboBox_;
QLabel *cameraLocation_;
QLabel *cameraModel_;
+ QPushButton *captureScriptButton_;
};
@@ -9,6 +9,7 @@
#include <assert.h>
#include <iomanip>
+#include <memory>
#include <string>
#include <libcamera/camera_manager.h>
@@ -19,6 +20,7 @@
#include <QFileDialog>
#include <QImage>
#include <QImageWriter>
+#include <QMessageBox>
#include <QMutexLocker>
#include <QStandardPaths>
#include <QStringList>
@@ -151,6 +153,9 @@ MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options)
return;
}
+ /* Start capture script. */
+ loadCaptureScript();
+
startStopAction_->setChecked(true);
}
@@ -290,14 +295,55 @@ void MainWindow::switchCamera()
startStopAction_->setChecked(true);
}
+void MainWindow::stopCaptureScript()
+{
+ if (script_) {
+ script_.reset();
+ }
+}
+
+void MainWindow::loadCaptureScript()
+{
+ if (scriptPath_.empty() || camera_ == nullptr)
+ return;
+
+ script_ = std::make_unique<CaptureScript>(camera_, scriptPath_);
+
+ /*
+ * If we are already capturing, stop so we don't have stuck image
+ * in viewfinder.
+ */
+ bool wasCapturing = isCapturing_;
+ if (isCapturing_)
+ toggleCapture(false);
+
+ if (!script_->valid()) {
+ script_.reset();
+
+ QMessageBox::critical(this, "Invalid Script",
+ "Couldn't load the capture script");
+ }
+
+ /* Start capture again if we were capturing before. */
+ if (wasCapturing)
+ toggleCapture(true);
+}
+
std::string MainWindow::chooseCamera()
{
- camSelectDialog_ = new CamSelectDialog(cm_, this);
+ bool scriptRunning = script_ != nullptr;
+ camSelectDialog_ = new CamSelectDialog(cm_, scriptRunning, this);
+
+ connect(camSelectDialog_, &CamSelectDialog::stopCaptureScript,
+ this, &MainWindow::stopCaptureScript);
if (camSelectDialog_->exec() == QDialog::Accepted) {
std::string cameraId = camSelectDialog_->getCameraId();
cameraSwitchButton_->setText(QString::fromStdString(cameraId));
+ scriptPath_ = camSelectDialog_->getCaptureScript();
+ loadCaptureScript();
+
return cameraId;
} else
return std::string();
@@ -504,6 +550,7 @@ int MainWindow::startCapture()
previousFrames_ = 0;
framesCaptured_ = 0;
lastBufferTime_ = 0;
+ queueCount_ = 0;
ret = camera_->start();
if (ret) {
@@ -783,5 +830,10 @@ void MainWindow::renderComplete(FrameBuffer *buffer)
int MainWindow::queueRequest(Request *request)
{
+ if (script_)
+ request->controls() = script_->frameControls(queueCount_);
+
+ queueCount_++;
+
return camera_->queueRequest(request);
}
@@ -28,6 +28,7 @@
#include <QQueue>
#include <QTimer>
+#include "../cam/capture_script.h"
#include "../cam/stream_options.h"
#include "cam_select_dialog.h"
@@ -90,6 +91,9 @@ private:
void processHotplug(HotplugEvent *e);
void processViewfinder(libcamera::FrameBuffer *buffer);
+ void loadCaptureScript();
+ void stopCaptureScript();
+
/* UI elements */
QToolBar *toolbar_;
QAction *startStopAction_;
@@ -130,6 +134,9 @@ 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_;
+ std::string scriptPath_;
};
@@ -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',
@@ -38,6 +39,7 @@ qcam_resources = files([
qcam_deps = [
libatomic,
libcamera_public,
+ libyaml,
qt5_dep,
]
Implement an Capture Script in CamSelectDialog button which would allow the user to open a Capture Script (*.yaml). This button has three states : - Open Capture Script - Loaded - 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. When the script is loaded the button displays "Loaded", the script has not been verified yet. Verifying the script and executing it happens after user presses Ok. 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@gmail.com> --- Difference from V1: No button on toolbar now it resides in CamSelectDialog src/qcam/cam_select_dialog.h | 47 +++++++++++++++++++++++++++++-- src/qcam/main_window.cpp | 54 +++++++++++++++++++++++++++++++++++- src/qcam/main_window.h | 7 +++++ src/qcam/meson.build | 2 ++ 4 files changed, 107 insertions(+), 3 deletions(-)