Message ID | 20220810150349.414043-7-utkarsh02t@gmail.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
On Wed, Aug 10, 2022 at 08:33:47PM +0530, Utkarsh Tiwari wrote: > 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 clicked in an open state, present the user with a QFileDialog to > allow selecting 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 > reset and the capture 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 v7: > 1. Fix grammetical errors in the commit message > 2. Intialize the cameraSelectorDialog_ to nullptr in Construct > so we construct the CameraSelectorDialog just once > src/qcam/cam_select_dialog.cpp | 69 ++++++++++++++++++++++++++++++++-- > src/qcam/cam_select_dialog.h | 20 +++++++++- > src/qcam/main_window.cpp | 59 ++++++++++++++++++++++++++++- > src/qcam/main_window.h | 7 ++++ > src/qcam/meson.build | 2 + > 5 files changed, 152 insertions(+), 5 deletions(-) > > diff --git a/src/qcam/cam_select_dialog.cpp b/src/qcam/cam_select_dialog.cpp > index f97ad6eb..0db0a5bd 100644 > --- a/src/qcam/cam_select_dialog.cpp > +++ b/src/qcam/cam_select_dialog.cpp > @@ -16,12 +16,13 @@ > #include <QComboBox> > #include <QDialog> > #include <QDialogButtonBox> > +#include <QFileDialog> > #include <QFormLayout> > #include <QString> > > CameraSelectorDialog::CameraSelectorDialog(libcamera::CameraManager *cameraManager, > - QWidget *parent) > - : QDialog(parent), cm_(cameraManager) > + bool isScriptRunning, QWidget *parent) > + : QDialog(parent), cm_(cameraManager), isScriptRunning_(isScriptRunning) > { > /* Use a QFormLayout for the dialog. */ > QFormLayout *layout = new QFormLayout(this); > @@ -39,6 +40,16 @@ CameraSelectorDialog::CameraSelectorDialog(libcamera::CameraManager *cameraManag > connect(cameraIdComboBox_, &QComboBox::currentTextChanged, > this, &CameraSelectorDialog::handleCameraChange); > > + captureScriptButton_ = new QPushButton; > + connect(captureScriptButton_, &QPushButton::clicked, > + this, &CameraSelectorDialog::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 *buttonBox = > new QDialogButtonBox(QDialogButtonBox::Ok | > @@ -50,10 +61,10 @@ CameraSelectorDialog::CameraSelectorDialog(libcamera::CameraManager *cameraManag > this, &QDialog::reject); > > /* Set the layout. */ > - > layout->addRow("Camera:", cameraIdComboBox_); > layout->addRow("Location:", cameraLocation_); > layout->addRow("Model:", cameraModel_); > + layout->addRow("Capture Script:", captureScriptButton_); > layout->addWidget(buttonBox); > } > > @@ -62,6 +73,11 @@ std::string CameraSelectorDialog::getCameraId() > return cameraIdComboBox_->currentText().toStdString(); > } > > +std::string CameraSelectorDialog::getCaptureScript() > +{ > + return scriptPath_; > +} > + > /* Hotplug / Unplug Support. */ > void CameraSelectorDialog::cameraAdded(libcamera::Camera *camera) > { > @@ -115,3 +131,50 @@ void CameraSelectorDialog::updateCamInfo(const std::shared_ptr<libcamera::Camera > > cameraModel_->setText(QString::fromStdString(model)); > } > + > +/* Capture script support. */ > +void CameraSelectorDialog::handleCaptureScriptButton() > +{ > + if (isScriptRunning_) { > + Q_EMIT stopCaptureScript(); > + isScriptRunning_ = false; > + captureScriptButton_->setText("Open"); > + } else { > + selectedScriptPath_ = QFileDialog::getOpenFileName(this, > + "Run Capture Script", QDir::currentPath(), > + "Capture Script (*.yaml)") > + .toStdString(); > + > + if (!selectedScriptPath_.empty()) > + captureScriptButton_->setText("Loaded"); > + else > + captureScriptButton_->setText("Open"); > + } > +} > + > +void CameraSelectorDialog::accept() > +{ > + scriptPath_ = selectedScriptPath_; > + QDialog::accept(); > +} > + > +void CameraSelectorDialog::reject() > +{ > + if (isScriptRunning_) > + selectedScriptPath_ = scriptPath_; > + QDialog::reject(); > +} > + > +void CameraSelectorDialog::informScriptReset() > +{ > + isScriptRunning_ = false; > + scriptPath_.clear(); add this to also reset any selected files already this is necessary when dealing with interactive controls selectedScriptPath_.clear(); captureWidgetLayout_->removeWidget(scriptPathLabel_); > + captureScriptButton_->setText("Open"); > +} > + > +void CameraSelectorDialog::informScriptRunning(std::string scriptPath) > +{ > + isScriptRunning_ = true; > + scriptPath_ = scriptPath; > + captureScriptButton_->setText("Stop"); > +} > diff --git a/src/qcam/cam_select_dialog.h b/src/qcam/cam_select_dialog.h > index 16475af6..bbdf897e 100644 > --- a/src/qcam/cam_select_dialog.h > +++ b/src/qcam/cam_select_dialog.h > @@ -17,18 +17,21 @@ > #include <QComboBox> > #include <QDialog> > #include <QLabel> > +#include <QPushButton> > > class CameraSelectorDialog : public QDialog > { > Q_OBJECT > public: > CameraSelectorDialog(libcamera::CameraManager *cameraManager, > - QWidget *parent); > + bool isScriptRunning, QWidget *parent); > > ~CameraSelectorDialog() = default; > > std::string getCameraId(); > > + std::string getCaptureScript(); > + > /* Hotplug / Unplug Support. */ > void cameraAdded(libcamera::Camera *camera); > > @@ -38,11 +41,26 @@ public: > void updateCamInfo(const std::shared_ptr<libcamera::Camera> &camera); > void handleCameraChange(); > > + /* Capture script support. */ > + void handleCaptureScriptButton(); > + void informScriptReset(); > + void informScriptRunning(std::string scriptPath); > + void accept() override; > + void reject() override; > + > +Q_SIGNALS: > + void stopCaptureScript(); > + > private: > libcamera::CameraManager *cm_; > > + bool isScriptRunning_; > + std::string scriptPath_; > + std::string selectedScriptPath_; > + > /* UI elements. */ > QComboBox *cameraIdComboBox_; > QLabel *cameraLocation_; > QLabel *cameraModel_; > + QPushButton *captureScriptButton_; > }; > diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp > index bf40572a..3c7c3173 100644 > --- a/src/qcam/main_window.cpp > +++ b/src/qcam/main_window.cpp > @@ -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> > @@ -152,6 +154,9 @@ MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options) > return; > } > > + /* Start capture script. */ > + loadCaptureScript(); > + > startStopAction_->setChecked(true); > } > > @@ -290,11 +295,54 @@ void MainWindow::switchCamera() > startStopAction_->setChecked(true); > } > > +void MainWindow::stopCaptureScript() > +{ > + if (script_) { > + script_.reset(); > + cameraSelectorDialog_->informScriptReset(); > + } > +} > + > +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(); > + cameraSelectorDialog_->informScriptReset(); > + > + QMessageBox::critical(this, "Invalid Script", > + "Couldn't load the capture script"); > + > + } else > + cameraSelectorDialog_->informScriptRunning(scriptPath_); > + > + /* Start capture again if we were capturing before. */ > + if (wasCapturing) > + toggleCapture(true); > +} > + > std::string MainWindow::chooseCamera() > { > + bool scriptRunning = script_ != nullptr; > + > /* Construct the selection dialog, only the first time. */ > if (!cameraSelectorDialog_) > - cameraSelectorDialog_ = new CameraSelectorDialog(cm_, this); > + cameraSelectorDialog_ = new CameraSelectorDialog(cm_, scriptRunning, this); > + > + connect(cameraSelectorDialog_, &CameraSelectorDialog::stopCaptureScript, > + this, &MainWindow::stopCaptureScript); > > /* > * Use the camera specified on the command line, if any, or display the > @@ -309,6 +357,9 @@ std::string MainWindow::chooseCamera() > std::string cameraId = cameraSelectorDialog_->getCameraId(); > cameraSelectButton_->setText(QString::fromStdString(cameraId)); > > + scriptPath_ = cameraSelectorDialog_->getCaptureScript(); > + loadCaptureScript(); > + > return cameraId; > } else > return std::string(); > @@ -506,6 +557,7 @@ int MainWindow::startCapture() > previousFrames_ = 0; > framesCaptured_ = 0; > lastBufferTime_ = 0; > + queueCount_ = 0; > > ret = camera_->start(); > if (ret) { > @@ -783,5 +835,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 d161365a..10994b67 100644 > --- a/src/qcam/main_window.h > +++ b/src/qcam/main_window.h > @@ -27,6 +27,7 @@ > #include <QQueue> > #include <QTimer> > > +#include "../cam/capture_script.h" > #include "../cam/stream_options.h" > > #include "cam_select_dialog.h" > @@ -89,6 +90,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_; > }; > diff --git a/src/qcam/meson.build b/src/qcam/meson.build > index 61861ea6..70a18d7e 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', > @@ -39,6 +40,7 @@ qcam_resources = files([ > qcam_deps = [ > libatomic, > libcamera_public, > + libyaml, > qt5_dep, > ] > > -- > 2.25.1 >
diff --git a/src/qcam/cam_select_dialog.cpp b/src/qcam/cam_select_dialog.cpp index f97ad6eb..0db0a5bd 100644 --- a/src/qcam/cam_select_dialog.cpp +++ b/src/qcam/cam_select_dialog.cpp @@ -16,12 +16,13 @@ #include <QComboBox> #include <QDialog> #include <QDialogButtonBox> +#include <QFileDialog> #include <QFormLayout> #include <QString> CameraSelectorDialog::CameraSelectorDialog(libcamera::CameraManager *cameraManager, - QWidget *parent) - : QDialog(parent), cm_(cameraManager) + bool isScriptRunning, QWidget *parent) + : QDialog(parent), cm_(cameraManager), isScriptRunning_(isScriptRunning) { /* Use a QFormLayout for the dialog. */ QFormLayout *layout = new QFormLayout(this); @@ -39,6 +40,16 @@ CameraSelectorDialog::CameraSelectorDialog(libcamera::CameraManager *cameraManag connect(cameraIdComboBox_, &QComboBox::currentTextChanged, this, &CameraSelectorDialog::handleCameraChange); + captureScriptButton_ = new QPushButton; + connect(captureScriptButton_, &QPushButton::clicked, + this, &CameraSelectorDialog::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 *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | @@ -50,10 +61,10 @@ CameraSelectorDialog::CameraSelectorDialog(libcamera::CameraManager *cameraManag this, &QDialog::reject); /* Set the layout. */ - layout->addRow("Camera:", cameraIdComboBox_); layout->addRow("Location:", cameraLocation_); layout->addRow("Model:", cameraModel_); + layout->addRow("Capture Script:", captureScriptButton_); layout->addWidget(buttonBox); } @@ -62,6 +73,11 @@ std::string CameraSelectorDialog::getCameraId() return cameraIdComboBox_->currentText().toStdString(); } +std::string CameraSelectorDialog::getCaptureScript() +{ + return scriptPath_; +} + /* Hotplug / Unplug Support. */ void CameraSelectorDialog::cameraAdded(libcamera::Camera *camera) { @@ -115,3 +131,50 @@ void CameraSelectorDialog::updateCamInfo(const std::shared_ptr<libcamera::Camera cameraModel_->setText(QString::fromStdString(model)); } + +/* Capture script support. */ +void CameraSelectorDialog::handleCaptureScriptButton() +{ + if (isScriptRunning_) { + Q_EMIT stopCaptureScript(); + isScriptRunning_ = false; + captureScriptButton_->setText("Open"); + } else { + selectedScriptPath_ = QFileDialog::getOpenFileName(this, + "Run Capture Script", QDir::currentPath(), + "Capture Script (*.yaml)") + .toStdString(); + + if (!selectedScriptPath_.empty()) + captureScriptButton_->setText("Loaded"); + else + captureScriptButton_->setText("Open"); + } +} + +void CameraSelectorDialog::accept() +{ + scriptPath_ = selectedScriptPath_; + QDialog::accept(); +} + +void CameraSelectorDialog::reject() +{ + if (isScriptRunning_) + selectedScriptPath_ = scriptPath_; + QDialog::reject(); +} + +void CameraSelectorDialog::informScriptReset() +{ + isScriptRunning_ = false; + scriptPath_.clear(); + captureScriptButton_->setText("Open"); +} + +void CameraSelectorDialog::informScriptRunning(std::string scriptPath) +{ + isScriptRunning_ = true; + scriptPath_ = scriptPath; + captureScriptButton_->setText("Stop"); +} diff --git a/src/qcam/cam_select_dialog.h b/src/qcam/cam_select_dialog.h index 16475af6..bbdf897e 100644 --- a/src/qcam/cam_select_dialog.h +++ b/src/qcam/cam_select_dialog.h @@ -17,18 +17,21 @@ #include <QComboBox> #include <QDialog> #include <QLabel> +#include <QPushButton> class CameraSelectorDialog : public QDialog { Q_OBJECT public: CameraSelectorDialog(libcamera::CameraManager *cameraManager, - QWidget *parent); + bool isScriptRunning, QWidget *parent); ~CameraSelectorDialog() = default; std::string getCameraId(); + std::string getCaptureScript(); + /* Hotplug / Unplug Support. */ void cameraAdded(libcamera::Camera *camera); @@ -38,11 +41,26 @@ public: void updateCamInfo(const std::shared_ptr<libcamera::Camera> &camera); void handleCameraChange(); + /* Capture script support. */ + void handleCaptureScriptButton(); + void informScriptReset(); + void informScriptRunning(std::string scriptPath); + void accept() override; + void reject() override; + +Q_SIGNALS: + void stopCaptureScript(); + private: libcamera::CameraManager *cm_; + bool isScriptRunning_; + std::string scriptPath_; + std::string selectedScriptPath_; + /* UI elements. */ QComboBox *cameraIdComboBox_; QLabel *cameraLocation_; QLabel *cameraModel_; + QPushButton *captureScriptButton_; }; diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index bf40572a..3c7c3173 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -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> @@ -152,6 +154,9 @@ MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options) return; } + /* Start capture script. */ + loadCaptureScript(); + startStopAction_->setChecked(true); } @@ -290,11 +295,54 @@ void MainWindow::switchCamera() startStopAction_->setChecked(true); } +void MainWindow::stopCaptureScript() +{ + if (script_) { + script_.reset(); + cameraSelectorDialog_->informScriptReset(); + } +} + +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(); + cameraSelectorDialog_->informScriptReset(); + + QMessageBox::critical(this, "Invalid Script", + "Couldn't load the capture script"); + + } else + cameraSelectorDialog_->informScriptRunning(scriptPath_); + + /* Start capture again if we were capturing before. */ + if (wasCapturing) + toggleCapture(true); +} + std::string MainWindow::chooseCamera() { + bool scriptRunning = script_ != nullptr; + /* Construct the selection dialog, only the first time. */ if (!cameraSelectorDialog_) - cameraSelectorDialog_ = new CameraSelectorDialog(cm_, this); + cameraSelectorDialog_ = new CameraSelectorDialog(cm_, scriptRunning, this); + + connect(cameraSelectorDialog_, &CameraSelectorDialog::stopCaptureScript, + this, &MainWindow::stopCaptureScript); /* * Use the camera specified on the command line, if any, or display the @@ -309,6 +357,9 @@ std::string MainWindow::chooseCamera() std::string cameraId = cameraSelectorDialog_->getCameraId(); cameraSelectButton_->setText(QString::fromStdString(cameraId)); + scriptPath_ = cameraSelectorDialog_->getCaptureScript(); + loadCaptureScript(); + return cameraId; } else return std::string(); @@ -506,6 +557,7 @@ int MainWindow::startCapture() previousFrames_ = 0; framesCaptured_ = 0; lastBufferTime_ = 0; + queueCount_ = 0; ret = camera_->start(); if (ret) { @@ -783,5 +835,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 d161365a..10994b67 100644 --- a/src/qcam/main_window.h +++ b/src/qcam/main_window.h @@ -27,6 +27,7 @@ #include <QQueue> #include <QTimer> +#include "../cam/capture_script.h" #include "../cam/stream_options.h" #include "cam_select_dialog.h" @@ -89,6 +90,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_; }; diff --git a/src/qcam/meson.build b/src/qcam/meson.build index 61861ea6..70a18d7e 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', @@ -39,6 +40,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 clicked in an open state, present the user with a QFileDialog to allow selecting 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 reset and the capture 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 v7: 1. Fix grammetical errors in the commit message 2. Intialize the cameraSelectorDialog_ to nullptr in Construct so we construct the CameraSelectorDialog just once src/qcam/cam_select_dialog.cpp | 69 ++++++++++++++++++++++++++++++++-- src/qcam/cam_select_dialog.h | 20 +++++++++- src/qcam/main_window.cpp | 59 ++++++++++++++++++++++++++++- src/qcam/main_window.h | 7 ++++ src/qcam/meson.build | 2 + 5 files changed, 152 insertions(+), 5 deletions(-)