[libcamera-devel] [PATCH v7 6/8] qcam: CamSelectDialog: Add capture script button

Utkarsh Tiwari utkarsh02t at gmail.com
Wed Aug 10 06:30:56 CEST 2022


Hi Kieran thanks for the review.

I accept all the grammetical mistakes.

On Wed, Aug 10, 2022 at 3:29 AM Kieran Bingham <
kieran.bingham at ideasonboard.com> wrote:

> Quoting Utkarsh Tiwari via libcamera-devel (2022-08-09 21:50:40)
> > 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
>
> "When clicked in an open state, present the user with" ...
>
> > allow user to select a single file. When the script is loaded the button
>
> "to allow selecting a single file." ...
>
> > 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
>
> s/reseted/reset/
>
> s/capture is continues/capture continues/
>
> > restarted).
> >
> > Requests are queued with any controls the script matching the current
> > queueCount_.
> >
> > Signed-off-by: Utkarsh Tiwari <utkarsh02t at gmail.com>
> > ---
> > Difference:
> >         1. override accept and reject to handle capture script paths.
> >  src/qcam/cam_select_dialog.cpp | 68 ++++++++++++++++++++++++++++++++--
> >  src/qcam/cam_select_dialog.h   | 21 ++++++++++-
> >  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..f3df9970 100644
> > --- a/src/qcam/cam_select_dialog.cpp
> > +++ b/src/qcam/cam_select_dialog.cpp
> > @@ -20,8 +20,8 @@
> >  #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 +39,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 +60,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 +72,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 +130,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_;
>
> What is this for ?
>
>
> > +       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 359df811..56d90596 100644
> > --- a/src/qcam/cam_select_dialog.h
> > +++ b/src/qcam/cam_select_dialog.h
> > @@ -17,8 +17,10 @@
> >  #include <QComboBox>
> >  #include <QDialog>
> >  #include <QDialogButtonBox>
> > +#include <QFileDialog>
> >  #include <QFormLayout>
> >  #include <QLabel>
> > +#include <QPushButton>
> >  #include <QString>
> >
> >  class CameraSelectorDialog : public QDialog
> > @@ -26,12 +28,14 @@ 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);
> >
> > @@ -41,11 +45,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 3feabcff..d73fb42a 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>
> > @@ -151,6 +153,9 @@ MainWindow::MainWindow(CameraManager *cm, const
> OptionsParser::Options &options)
> >                 return;
> >         }
> >
> > +       /* Start capture script. */
> > +       loadCaptureScript();
> > +
> >         startStopAction_->setChecked(true);
> >  }
> >
> > @@ -289,10 +294,53 @@ 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, unconditionally. */
> > -       cameraSelectorDialog_ = new CameraSelectorDialog(cm_, this);
> > +       cameraSelectorDialog_ = new CameraSelectorDialog(cm_,
> scriptRunning, this);
> > +
> > +       connect(cameraSelectorDialog_,
> &CameraSelectorDialog::stopCaptureScript,
> > +               this, &MainWindow::stopCaptureScript);
>
> I fear that creating a new dialog box every time we choose a camera
> means that every call here leaks at least a CameraSelectorDialog
> allocation, *and* because we're connecting more signals - we're going to
> end up with duplicted signals?
>
> Ah shoots this should be done in the MainWindow constructor.

> >
> >         /*
> >          * Use the camera specified on the command line, if any, or
> display the
> > @@ -305,6 +353,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();
> > @@ -502,6 +553,7 @@ int MainWindow::startCapture()
> >         previousFrames_ = 0;
> >         framesCaptured_ = 0;
> >         lastBufferTime_ = 0;
> > +       queueCount_ = 0;
> >
> >         ret = camera_->start();
> >         if (ret) {
> > @@ -779,5 +831,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 bd6f0172..887f1db1 100644
> > --- a/src/qcam/main_window.h
> > +++ b/src/qcam/main_window.h
> > @@ -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_;
> >  };
> > 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
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.libcamera.org/pipermail/libcamera-devel/attachments/20220810/a0c4397a/attachment.htm>


More information about the libcamera-devel mailing list