File indexing completed on 2024-04-28 03:43:13

0001 /*
0002     SPDX-FileCopyrightText: 2012 Jasem Mutlaq <mutlaqja@ikarustech.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "ui_capture.h"
0010 
0011 #include "sequencejob.h"
0012 #include "ekos/manager/meridianflipstate.h"
0013 #include "customproperties.h"
0014 #include "ekos/ekos.h"
0015 #include "indi/indicamera.h"
0016 #include "indi/indidustcap.h"
0017 #include "indi/indidome.h"
0018 #include "indi/indilightbox.h"
0019 #include "indi/indimount.h"
0020 #include "ui_limits.h"
0021 
0022 #include <QTimer>
0023 #include <QUrl>
0024 #include <QDBusInterface>
0025 
0026 #include <memory>
0027 
0028 class DSLRInfo;
0029 class QProgressIndicator;
0030 class QTableWidgetItem;
0031 class KDirWatch;
0032 class RotatorSettings;
0033 
0034 /**
0035  * @namespace Ekos
0036  * @short Ekos is an advanced Astrophotography tool for Linux.
0037  * It is based on a modular extensible framework to perform common astrophotography tasks. This includes highly accurate GOTOs using astrometry solver, ability to measure and correct polar alignment errors ,
0038  * auto-focus & auto-guide capabilities, and capture of single or stack of images with filter wheel support.\n
0039  * Features:
0040  * - Control your telescope, CCD (& DSLRs), filter wheel, focuser, guider, adaptive optics unit, and any INDI-compatible auxiliary device from Ekos.
0041  * - Extremely accurate GOTOs using astrometry.net solver (both Online and Offline solvers supported).
0042  * - Load & Slew: Load a FITS image, slew to solved coordinates, and center the mount on the exact image coordinates in order to get the same desired frame.
0043  * - Measure & Correct Polar Alignment errors using astrometry.net solver.
0044  * - Auto and manual focus modes using Half-Flux-Radius (HFR) method.
0045  * - Automated unattended meridian flip. Ekos performs post meridian flip alignment, calibration, and guiding to resume the capture session.
0046  * - Automatic focus between exposures when a user-configurable HFR limit is exceeded.
0047  * - Automatic focus between exposures when the temperature has changed a lot since last focus.
0048  * - Auto guiding with support for automatic dithering between exposures and support for Adaptive Optics devices in addition to traditional guiders.
0049  * - Powerful sequence queue for batch capture of images with optional prefixes, timestamps, filter wheel selection, and much more!
0050  * - Export and import sequence queue sets as Ekos Sequence Queue (.esq) files.
0051  * - Center the telescope anywhere in a captured FITS image or any FITS with World Coordinate System (WCS) header.
0052  * - Automatic flat field capture, just set the desired ADU and let Ekos does the rest!
0053  * - Automatic abort and resumption of exposure tasks if guiding errors exceed a user-configurable value.
0054  * - Support for dome slaving.
0055  * - Complete integration with KStars Observation Planner and SkyMap
0056  * - Integrate with all INDI native devices.
0057  * - Powerful scripting capabilities via \ref EkosDBusInterface "DBus."
0058  *
0059  * The primary class is Ekos::Manager. It handles startup and shutdown of local and remote INDI devices, manages and orchesterates the various Ekos modules, and provides advanced DBus
0060  * interface to enable unattended scripting.
0061  *
0062  * @author Jasem Mutlaq
0063  * @version 1.9
0064  */
0065 namespace Ekos
0066 {
0067 
0068 class CaptureDeviceAdaptor;
0069 class CaptureModuleState;
0070 class CaptureProcess;
0071 class ScriptsManager;
0072 
0073 /**
0074  *@class Capture
0075  *@short Captures single or sequence of images from a CCD.
0076  * The capture class support capturing single or multiple images from a CCD, it provides a
0077  * powerful sequence queue with filter selection. Any sequence queue can be saved as
0078  * Ekos Sequence Queue (.esq). All image capture operations are saved as Sequence Jobs
0079  * that encapsulate all the different options in a capture process. The user may select in
0080  * sequence autofocusing by setting limits for HFR, execution time or temperature delta. When the limit
0081  * is exceeded, it automatically trigger autofocus operation. The capture process can also be
0082  * linked with guide module. If guiding deviations exceed a certain threshold, the capture operation aborts until
0083  * the guiding deviation resume to acceptable levels and the capture operation is resumed.
0084  *
0085  * Controlling the capturing execution is a complex process, that is controlled by
0086  * these classes:
0087  * - this class, that controll the UI and is the interface for all DBUS functions
0088  * - {@see CaptureModuleState} holds all state informations
0089  * - {@see CaptureProcess} holds the business logic that controls the process
0090  * For ore details about the capturing execution process, please visit {@see CaptureProcess}.
0091  *
0092  *@author Jasem Mutlaq
0093  *@version 1.4
0094  */
0095 class Capture : public QWidget, public Ui::Capture
0096 {
0097         Q_OBJECT
0098         Q_CLASSINFO("D-Bus Interface", "org.kde.kstars.Ekos.Capture")
0099         Q_PROPERTY(Ekos::CaptureState status READ status NOTIFY newStatus)
0100         Q_PROPERTY(QString targetName READ getTargetName WRITE setTargetName)
0101         Q_PROPERTY(QString observerName READ getObserverName WRITE setObserverName)
0102         Q_PROPERTY(QString opticalTrain READ opticalTrain WRITE setOpticalTrain)
0103         Q_PROPERTY(QString camera READ camera)
0104         Q_PROPERTY(QString filterWheel READ filterWheel)
0105         Q_PROPERTY(QString filter READ filter WRITE setFilter)
0106         Q_PROPERTY(bool coolerControl READ hasCoolerControl WRITE setCoolerControl)
0107         Q_PROPERTY(QStringList logText READ logText NOTIFY newLog)
0108 
0109     public:
0110         typedef enum
0111         {
0112             NOT_PREVIEW,
0113             LOCAL_PREVIEW,
0114             REMOTE_PREVIEW
0115         } FilenamePreviewType;
0116 
0117         Capture(bool standAlone = false);
0118         ~Capture();
0119 
0120         /** @defgroup CaptureDBusInterface Ekos DBus Interface - Capture Module
0121              * Ekos::Capture interface provides advanced scripting capabilities to capture image sequences.
0122              * @{
0123             */
0124 
0125 
0126         /** DBUS interface function.
0127              * select the CCD device from the available CCD drivers.
0128              * @param device The CCD device name
0129              */
0130         Q_SCRIPTABLE QString camera();
0131 
0132         /** DBUS interface function.
0133              * select the filter device from the available filter drivers. The filter device can be the same as the CCD driver if the filter functionality was embedded within the driver.
0134              * @param device The filter device name
0135              */
0136         Q_SCRIPTABLE QString filterWheel();
0137 
0138         /** DBUS interface function.
0139              * select the filter name from the available filters in case a filter device is active.
0140              * @param filter The filter name
0141              */
0142         Q_SCRIPTABLE bool setFilter(const QString &filter);
0143         Q_SCRIPTABLE QString filter();
0144 
0145         /** DBUS interface function.
0146              * Aborts any current jobs and remove all sequence queue jobs.
0147              */
0148         Q_SCRIPTABLE Q_NOREPLY void clearSequenceQueue();
0149 
0150         /** DBUS interface function.
0151              * Returns the overall sequence queue status. If there are no jobs pending, it returns "Invalid". If all jobs are idle, it returns "Idle". If all jobs are complete, it returns "Complete". If one or more jobs are aborted
0152              * it returns "Aborted" unless it was temporarily aborted due to guiding deviations, then it would return "Suspended". If one or more jobs have errors, it returns "Error". If any jobs is under progress, returns "Running".
0153              */
0154         Q_SCRIPTABLE QString getSequenceQueueStatus()
0155         {
0156             return state()->sequenceQueueStatus();
0157         }
0158 
0159         /** DBUS interface function.
0160              * Loads the Ekos Sequence Queue file in the Sequence Queue. Jobs are appended to existing jobs.
0161              * @param fileURL full URL of the filename
0162              * @param targetName override the target in the sequence queue file (necessary for using the target of the scheduler)
0163              */
0164         Q_SCRIPTABLE bool loadSequenceQueue(const QString &fileURL, QString targetName = "");
0165 
0166         /** DBUS interface function.
0167              * Saves the Sequence Queue to the Ekos Sequence Queue file.
0168              * @param fileURL full URL of the filename
0169              */
0170         Q_SCRIPTABLE bool saveSequenceQueue(const QString &path);
0171 
0172         /** DBUS interface function.
0173              * Enables or disables the maximum guiding deviation and sets its value.
0174              * @param enable If true, enable the guiding deviation check, otherwise, disable it.
0175              * @param value if enable is true, it sets the maximum guiding deviation in arcsecs. If the value is exceeded, the capture operation is aborted until the value falls below the value threshold.
0176              */
0177         Q_SCRIPTABLE Q_NOREPLY void setMaximumGuidingDeviation(bool enable, double value);
0178 
0179         /** DBUS interface function.
0180              * Enables or disables the in sequence focus and sets Half-Flux-Radius (HFR) limit.
0181              * @param enable If true, enable the in sequence auto focus check, otherwise, disable it.
0182              * @param HFR if enable is true, it sets HFR in pixels. After each exposure, the HFR is re-measured and if it exceeds the specified value, an autofocus operation will be commanded.
0183              */
0184         Q_SCRIPTABLE Q_NOREPLY void setInSequenceFocus(bool enable, double HFR);
0185 
0186         /** DBUS interface function.
0187              * Does the CCD has a cooler control (On/Off) ?
0188              */
0189         Q_SCRIPTABLE bool hasCoolerControl();
0190 
0191         /** DBUS interface function.
0192              * Set the CCD cooler ON/OFF
0193              *
0194              */
0195         Q_SCRIPTABLE bool setCoolerControl(bool enable);
0196 
0197         /** DBUS interface function.
0198              * @return Returns the percentage of completed captures in all active jobs
0199              */
0200         Q_SCRIPTABLE double getProgressPercentage()
0201         {
0202             return state()->progressPercentage();
0203         }
0204 
0205         /** DBUS interface function.
0206              * @return Returns the number of jobs in the sequence queue.
0207              */
0208         Q_SCRIPTABLE int getJobCount()
0209         {
0210             return state()->allJobs().count();
0211         }
0212 
0213         /** DBUS interface function.
0214              * @return Returns the number of pending uncompleted jobs in the sequence queue.
0215              */
0216         Q_SCRIPTABLE int getPendingJobCount()
0217         {
0218             return state()->pendingJobCount();
0219         }
0220 
0221         /** DBUS interface function.
0222              * @return Returns ID of current active job if any, or -1 if there are no active jobs.
0223              */
0224         Q_SCRIPTABLE int getActiveJobID()
0225         {
0226             return state()->activeJobID();
0227         }
0228 
0229         /** DBUS interface function.
0230              * @return Returns time left in seconds until active job is estimated to be complete.
0231              */
0232         Q_SCRIPTABLE int getActiveJobRemainingTime()
0233         {
0234             return state()->activeJobRemainingTime();
0235         }
0236 
0237         /** DBUS interface function.
0238              * @return Returns overall time left in seconds until all jobs are estimated to be complete
0239              */
0240         Q_SCRIPTABLE int getOverallRemainingTime()
0241         {
0242             return state()->overallRemainingTime();
0243         }
0244 
0245         /** DBUS interface function.
0246              * @param id job number. Job IDs start from 0 to N-1.
0247              * @return Returns the job state (Idle, In Progress, Error, Aborted, Complete)
0248              */
0249         Q_SCRIPTABLE QString getJobState(int id)
0250         {
0251             return state()->jobState(id);
0252         }
0253 
0254         /** DBUS interface function.
0255              * @param id job number. Job IDs start from 0 to N-1.
0256              * @return Returns the job filter name.
0257              */
0258         Q_SCRIPTABLE QString getJobFilterName(int id)
0259         {
0260             return state()->jobFilterName(id);
0261         }
0262 
0263         /** DBUS interface function.
0264              * @param id job number. Job IDs start from 0 to N-1.
0265              * @return Returns The number of images completed capture in the job.
0266              */
0267         Q_SCRIPTABLE int getJobImageProgress(int id)
0268         {
0269             return state()->jobImageProgress(id);
0270         }
0271 
0272         /** DBUS interface function.
0273              * @param id job number. Job IDs start from 0 to N-1.
0274              * @return Returns the total number of images to capture in the job.
0275              */
0276         Q_SCRIPTABLE int getJobImageCount(int id)
0277         {
0278             return state()->jobImageCount(id);
0279         }
0280 
0281         /** DBUS interface function.
0282              * @param id job number. Job IDs start from 0 to N-1.
0283              * @return Returns the number of seconds left in an exposure operation.
0284              */
0285         Q_SCRIPTABLE double getJobExposureProgress(int id)
0286         {
0287             return state()->jobExposureProgress(id);
0288         }
0289 
0290         /** DBUS interface function.
0291              * @param id job number. Job IDs start from 0 to N-1.
0292              * @return Returns the total requested exposure duration in the job.
0293              */
0294         Q_SCRIPTABLE double getJobExposureDuration(int id)
0295         {
0296             return state()->jobExposureDuration(id);
0297         }
0298 
0299         /** DBUS interface function.
0300              * @param id job number. Job IDs start from 0 to N-1.
0301              * @return Returns the frame type (light, dark, ...) of the job.
0302              */
0303         Q_SCRIPTABLE CCDFrameType getJobFrameType(int id)
0304         {
0305             return state()->jobFrameType(id);
0306         }
0307 
0308         /** DBUS interface function.
0309              * Clear in-sequence focus settings. It sets the autofocus HFR to zero so that next autofocus value is remembered for the in-sequence focusing.
0310              */
0311         Q_SCRIPTABLE Q_NOREPLY void clearAutoFocusHFR();
0312 
0313         /** DBUS interface function.
0314              * Jobs will NOT be checked for progress against the file system and will be always assumed as new jobs.
0315              */
0316         Q_SCRIPTABLE Q_NOREPLY void ignoreSequenceHistory();
0317 
0318         /** DBUS interface function.
0319              * Set count of already completed frames. This is required when we have identical external jobs
0320              * with identical paths, but we need to continue where we left off. For example, if we have 3 identical
0321              * jobs, each capturing 5 images. Let's suppose 9 images were captured before. If the count for this signature
0322              * is set to 1, then we continue to capture frame #2 even though the number of completed images is already
0323              * larger than required count (5). It is mostly used in conjunction with Ekos Scheduler.
0324              */
0325         Q_SCRIPTABLE Q_NOREPLY void setCapturedFramesMap(const QString &signature, int count)
0326         {
0327             state()->setCapturedFramesCount(signature, static_cast<ushort>(count));
0328         };
0329 
0330 
0331         /** DBUS interface function.
0332          *  List of logging entries for the capture module.
0333          */
0334         Q_SCRIPTABLE QStringList logText()
0335         {
0336             return m_LogText;
0337         }
0338 
0339         /** DBUS interface function.
0340          *  Single text string holding all log lines for the capture module.
0341          */
0342         Q_SCRIPTABLE QString getLogText()
0343         {
0344             return m_LogText.join("\n");
0345         }
0346 
0347         /** DBUS interface function.
0348          *  Status of the capture module
0349          */
0350         Q_SCRIPTABLE CaptureState status()
0351         {
0352             return state()->getCaptureState();
0353         }
0354         /** @} end of group CaptureDBusInterface */
0355 
0356 
0357         // ////////////////////////////////////////////////////////////////////
0358         // Changing the devices used by Capture
0359         // ////////////////////////////////////////////////////////////////////
0360 
0361         /**
0362          * @brief Add new Camera
0363          * @param device pointer to camera device.
0364          * @return True if added successfully, false if duplicate or failed to add.
0365         */
0366         bool updateCamera();
0367 
0368         /**
0369          * @brief Add new Filter Wheel
0370          * @param name device name of the new filter wheel
0371         */
0372         void setFilterWheel(QString name);
0373 
0374         /**
0375          * @brief Add new Rotator
0376          * @param name name of the new rotator
0377         */
0378         void setRotator(QString name);
0379 
0380         /**
0381          * @brief setDome Set dome device
0382          * @param device pointer to dome device
0383          * @return true if successfull, false otherewise.
0384          */
0385         bool setDome(ISD::Dome *device);
0386 
0387         /**
0388          * @brief Generic method for removing any connected device.
0389          */
0390         void removeDevice(const QSharedPointer<ISD::GenericDevice> &device);
0391 
0392         /**
0393          * @brief registerNewModule Register an Ekos module as it arrives via DBus
0394          * and create the appropriate DBus interface to communicate with it.
0395          * @param name of module
0396          */
0397         void registerNewModule(const QString &name);
0398 
0399         // ////////////////////////////////////////////////////////////////////
0400         // Synchronize UI with device parameters
0401         // ////////////////////////////////////////////////////////////////////
0402 
0403         void syncFrameType(const QString &name);
0404         void syncCameraInfo();
0405 
0406         // ////////////////////////////////////////////////////////////////////
0407         // Optical Train handling
0408         // ////////////////////////////////////////////////////////////////////
0409         void setupOpticalTrainManager();
0410         void refreshOpticalTrain();
0411 
0412         QString opticalTrain() const
0413         {
0414             return opticalTrainCombo->currentText();
0415         }
0416         void setOpticalTrain(const QString &value)
0417         {
0418             opticalTrainCombo->setCurrentText(value);
0419         }
0420 
0421         // ////////////////////////////////////////////////////////////////////
0422         // Rotator
0423         // ////////////////////////////////////////////////////////////////////
0424         const QSharedPointer<RotatorSettings> &RotatorControl() const
0425         {
0426             return m_RotatorControlPanel;
0427         }
0428 
0429         // ////////////////////////////////////////////////////////////////////
0430         // Filter Manager and filters
0431         // ////////////////////////////////////////////////////////////////////
0432         void setupFilterManager();
0433 
0434         const QSharedPointer<FilterManager> &filterManager() const
0435         {
0436             return m_FilterManager;
0437         }
0438 
0439         /**
0440          * @brief checkFilter Refreshes the filter wheel information in the capture module.
0441          */
0442         void refreshFilterSettings();
0443 
0444         /**
0445          * @brief shortcut for updating the current filter information for the state machine
0446          */
0447         void updateCurrentFilterPosition();
0448 
0449         // ////////////////////////////////////////////////////////////////////
0450         // Read and write access for EkosLive
0451         // ////////////////////////////////////////////////////////////////////
0452 
0453         /**
0454          * @brief getSequence Return the JSON representation of the current sequeue queue
0455          * @return Reference to JSON array containing sequence queue jobs.
0456          */
0457         const QJsonArray &getSequence() const
0458         {
0459             return state()->getSequence();
0460         }
0461 
0462         /**
0463          * @brief setSettings Set capture settings
0464          * @param settings list of settings
0465          */
0466         void setPresetSettings(const QJsonObject &settings);
0467 
0468         /**
0469          * @brief getSettings get current capture settings as a JSON Object
0470          * @return settings as JSON object
0471          */
0472         QJsonObject getPresetSettings();
0473 
0474         /**
0475          * @brief setFileSettings Set File Settings
0476          * @param settings as JSON object
0477          */
0478         void setFileSettings(const QJsonObject &settings);
0479         /**
0480          * @brief getFileSettings Compile file setting
0481          * @return File settings as JSON object
0482          */
0483         QJsonObject getFileSettings();
0484 
0485         /**
0486          * @brief setCalibrationSettings Set Calibration settings
0487          * @param settings as JSON object
0488          */
0489         void setCalibrationSettings(const QJsonObject &settings)
0490         {
0491             state()->setCalibrationSettings(settings);
0492         }
0493 
0494         /**
0495          * @brief getCalibrationSettings Get Calibration settings
0496          * @return settings as JSON object
0497          */
0498         QJsonObject getCalibrationSettings()
0499         {
0500             return state()->calibrationSettings();
0501         }
0502 
0503         /**
0504          * @brief setLimitSettings Set limit settings
0505          * @param settings as JSON Object
0506          */
0507         void setLimitSettings(const QJsonObject &settings);
0508         /**
0509          * @brief getLimitSettings Get Limit Settings
0510          * @return settings as JSON Object
0511          */
0512         QJsonObject getLimitSettings();
0513 
0514         /**
0515          * @brief setVideoLimits sets the buffer size and max preview fps for live preview
0516          * @param maxBufferSize in bytes
0517          * @param maxPreviewFPS number of frames per second
0518          * @return True if value is updated, false otherwise.
0519          */
0520         bool setVideoLimits(uint16_t maxBufferSize, uint16_t maxPreviewFPS);
0521 
0522         // ////////////////////////////////////////////////////////////////////
0523         // DSLR handling
0524         // ////////////////////////////////////////////////////////////////////
0525 
0526         /**
0527          * @brief addDSLRInfo Save DSLR Info the in the database. If the interactive dialog was open, close it.
0528          * @param model Camera name
0529          * @param maxW Maximum width in pixels
0530          * @param maxH Maximum height in pixels
0531          * @param pixelW Pixel horizontal size in microns
0532          * @param pixelH Pizel vertical size in microns
0533          */
0534         void addDSLRInfo(const QString &model, uint32_t maxW, uint32_t maxH, double pixelW, double pixelH);
0535 
0536         void openExposureCalculatorDialog();
0537 
0538         void onStandAloneShow(QShowEvent* event);
0539 
0540         QSharedPointer<CaptureDeviceAdaptor> m_captureDeviceAdaptor;
0541 
0542     public slots:
0543         // ////////////////////////////////////////////////////////////////////
0544         // Main capturing actions
0545         // ////////////////////////////////////////////////////////////////////
0546 
0547         /** \addtogroup CaptureDBusInterface
0548              *  @{
0549              */
0550 
0551         /** DBUS interface function.
0552              * @brief Start the execution of the Capture::SequenceJob list #jobs.
0553              *
0554              * Starting the execution of the Capture::SequenceJob list selects the first job
0555              * from the list that may be executed and starts to prepare the job (@see prepareJob()).
0556              *
0557              * Several factors determine, which of the jobs will be selected:
0558              * - First, the list is searched to find the first job that is marked as idle or aborted.
0559              * -  If none is found, it is checked whether ignoring job progress is set. If yes,
0560              *    all jobs are are reset (@see reset()) and the first one from the list is selected.
0561              *    If no, the user is asked whether the jobs should be reset. If the user declines,
0562              *    starting is aborted.
0563              */
0564         Q_SCRIPTABLE Q_NOREPLY void start();
0565 
0566         /** DBUS interface function.
0567              * Stops currently running jobs:
0568              *           CAPTURE_IDLE: capture in idle state waiting for further action (e.g. single sequence
0569              *                         is complete, next one starting)
0570              *       CAPTURE_COMPLETE: all capture sequences are complete
0571              *          CAPTURE_ABORT: capture aborted either by user interaction or by a technical error
0572              *        CAPTURE_SUSPEND: capture suspended and waiting to be restarted
0573              * @param targetState status of the job after stop
0574              */
0575         Q_SCRIPTABLE Q_NOREPLY void stop(CaptureState targetState = CAPTURE_IDLE);
0576 
0577         /** DBUS interface function.
0578              * Aborts all jobs and mark current state as ABORTED. It simply calls stop(CAPTURE_ABORTED)
0579              */
0580         Q_SCRIPTABLE Q_NOREPLY void abort()
0581         {
0582             stop(CAPTURE_ABORTED);
0583         }
0584 
0585         /** DBUS interface function.
0586              * Aborts all jobs and mark current state as SUSPENDED. It simply calls stop(CAPTURE_SUSPENDED)
0587              * The only difference between SUSPENDED and ABORTED it that capture module can automatically resume a suspended
0588              * state on its own without external trigger once the right conditions are met. When whatever reason caused the module
0589              * to go into suspended state ceases to exist, the capture module automatically resumes. On the other hand, ABORTED state
0590              * must be started via an external programmatic or user trigger (e.g. click the start button again).
0591              */
0592         Q_SCRIPTABLE Q_NOREPLY void suspend()
0593         {
0594             stop(CAPTURE_SUSPENDED);
0595         }
0596         /** DBUS interface function.
0597          * @brief pause Pauses the Sequence Queue progress AFTER the current capture is complete.
0598          */
0599         Q_SCRIPTABLE Q_NOREPLY void pause();
0600 
0601         /** DBUS interface function.
0602          * @brief toggleSequence Toggle sequence state depending on its current state.
0603          * 1. If paused, then resume sequence.
0604          * 2. If idle or completed, then start sequence.
0605          * 3. Otherwise, abort current sequence.
0606          */
0607         Q_SCRIPTABLE Q_NOREPLY void toggleSequence();
0608 
0609 
0610         /** DBUS interface function.
0611              * Toggle video streaming if supported by the device.
0612              * @param enabled Set to true to start video streaming, false to stop it if active.
0613              */
0614         Q_SCRIPTABLE Q_NOREPLY void toggleVideo(bool enabled);
0615 
0616 
0617         /** DBus interface function
0618          * @brief restartCamera Restarts the INDI driver associated with a camera. Remote and Local drivers are supported.
0619          * @param name Name of camera to restart. If a driver defined multiple cameras, they would be removed and added again
0620          * after driver restart.
0621          */
0622         Q_SCRIPTABLE Q_NOREPLY void restartCamera(const QString &name);
0623 
0624         /** DBus interface function
0625          * @brief Set the name of the target to be captured.
0626          */
0627         Q_SCRIPTABLE Q_NOREPLY void setTargetName(const QString &newTargetName);
0628 
0629         Q_SCRIPTABLE QString getTargetName();
0630 
0631         /** DBus interface function
0632          * @brief Set the observer name.
0633          */
0634         Q_SCRIPTABLE Q_NOREPLY void setObserverName(const QString &value)
0635         {
0636             state()->setObserverName(value);
0637         };
0638         Q_SCRIPTABLE QString getObserverName()
0639         {
0640             return state()->observerName();
0641         }
0642 
0643 
0644         /** @}*/
0645 
0646         /**
0647          * @brief process shortcut for the process engine
0648          */
0649         QPointer<CaptureProcess> process() const
0650         {
0651             return m_captureProcess;
0652         }
0653 
0654         // ////////////////////////////////////////////////////////////////////
0655         // Capture actions
0656         // ////////////////////////////////////////////////////////////////////
0657         /**
0658          * @brief captureStarted Change the UI after the capturing process
0659          * has been started.
0660          */
0661         void jobStarting();
0662         /**
0663          * @brief capturePreview Capture a single preview image
0664          */
0665         void capturePreview();
0666 
0667         /**
0668          * @brief startFraming Like captureOne but repeating.
0669          */
0670         void startFraming();
0671 
0672         /**
0673          * @brief generateDarkFlats Generate a list of dark flat jobs from available flat frames.
0674          */
0675         void generateDarkFlats();
0676 
0677         /**
0678          * @brief updateJobFromUI Update all job attributes from the UI settings.
0679          */
0680         void updateJobFromUI(SequenceJob *job, FilenamePreviewType filenamePreview = NOT_PREVIEW);
0681 
0682         /**
0683          * @brief addJob Add a new job to the UI. This is used when a job is loaded from a capture sequence file. In
0684          * contrast to {@see #createJob()}, the job's attributes are taken from the file and only the UI gehts updated.
0685          */
0686         void addJob(SequenceJob *job);
0687 
0688         /**
0689          * @brief createJob Create a new job with the settings given in the GUI.
0690          * @param jobtype batch, preview, looping or dark flat job.
0691          * @param filenamePreview if the job is to generate a preview filename
0692          * @return pointer to job created or nullptr otherwise.
0693          */
0694         SequenceJob *createJob(SequenceJob::SequenceJobType jobtype = SequenceJob::JOBTYPE_BATCH,
0695                                FilenamePreviewType filenamePreview = NOT_PREVIEW);
0696 
0697         /**
0698          * @brief jobEditFinished Editing of an existing job finished, update its
0699          *        attributes from the UI settings. The job under edit is taken from the
0700          *        selection in the job table.
0701          * @return true if job updated succeeded.
0702          */
0703         void editJobFinished();
0704 
0705         // ////////////////////////////////////////////////////////////////////
0706         // public capture settings
0707         // ////////////////////////////////////////////////////////////////////
0708         /**
0709          * @brief seqCount Set required number of images to capture in one sequence job
0710          * @param count number of images to capture
0711          */
0712         void setCount(uint16_t count)
0713         {
0714             captureCountN->setValue(count);
0715         }
0716 
0717         /**
0718          * @brief setDelay Set delay between capturing images within a sequence in seconds
0719          * @param delay numbers of seconds to wait before starting the next image.
0720          */
0721         void setDelay(uint16_t delay)
0722         {
0723             captureDelayN->setValue(delay);
0724         }
0725 
0726         /**
0727          * @brief Slot receiving the update of the current target distance.
0728          * @param targetDiff distance to the target in arcseconds.
0729          */
0730         void updateTargetDistance(double targetDiff);
0731 
0732         /**
0733              * @brief checkCamera Refreshes the CCD information in the capture module.
0734              */
0735         void refreshCameraSettings();
0736 
0737         /**
0738              * @brief processCCDNumber Process number properties arriving from CCD. Currently, only CCD and Guider frames are processed.
0739              * @param nvp pointer to number property.
0740              */
0741         void processCameraNumber(INDI::Property prop);
0742 
0743 
0744         /**
0745          * @brief removeJob Remove a job sequence from the queue
0746          * @param index Row index for job to remove, if left as -1 (default), the currently selected row will be removed.
0747          *        if no row is selected, the last job shall be removed.
0748          * @param true if sequence is removed. False otherwise.
0749          */
0750         bool removeJob(int index = -1);
0751 
0752         /**
0753          * @brief MeridianFlipState Access to the meridian flip state machine
0754          */
0755         QSharedPointer<MeridianFlipState> getMeridianFlipState()
0756         {
0757             return state()->getMeridianFlipState();
0758         }
0759         void setMeridianFlipState(QSharedPointer<MeridianFlipState> newstate);
0760 
0761         // ////////////////////////////////////////////////////////////////////
0762         // UI controls
0763         // ////////////////////////////////////////////////////////////////////
0764 
0765         void removeJobFromQueue();
0766 
0767         /**
0768           * @brief moveJobUp Move the job in the sequence queue one place up or down.
0769           */
0770         void moveJob(bool up);
0771 
0772         /**
0773          * @brief setTemperature Set the target CCD temperature in the GUI settings.
0774          */
0775         void setTargetTemperature(double temperature)
0776         {
0777             cameraTemperatureN->setValue(temperature);
0778         }
0779 
0780         void setForceTemperature(bool enabled)
0781         {
0782             cameraTemperatureS->setChecked(enabled);
0783         }
0784 
0785         /**
0786          * @brief updateTargetName React upon a new capture target name
0787          */
0788         void newTargetName(const QString &name);
0789 
0790         /**
0791          * @brief showTemperatureRegulation Toggle temperature regulation dialog which sets temperature ramp and threshold
0792          */
0793         void showTemperatureRegulation();
0794 
0795         /**
0796          * @brief updateStartButtons Update the start and the pause button to new states of capturing
0797          * @param start start capturing
0798          * @param pause pause capturing
0799          */
0800         void updateStartButtons(bool start, bool pause = false);
0801 
0802         // Clear Camera Configuration
0803         void clearCameraConfiguration();
0804 
0805         // ////////////////////////////////////////////////////////////////////
0806         // slots handling device and module events
0807         // ////////////////////////////////////////////////////////////////////
0808 
0809         /**
0810          * @brief captureStarted Manage the result when capturing has been started
0811          */
0812         void captureRunning();
0813 
0814         /**
0815              * @brief setGuideDeviation Set the guiding deviation as measured by the guiding module. Abort capture
0816              *        if deviation exceeds user value. Resume capture if capture was aborted and guiding
0817              *         deviations are below user value.
0818              * @param delta_ra Deviation in RA in arcsecs from the selected guide star.
0819              * @param delta_dec Deviation in DEC in arcsecs from the selected guide star.
0820              */
0821         void setGuideDeviation(double delta_ra, double delta_dec);
0822 
0823         void setGuideChip(ISD::CameraChip *guideChip);
0824 
0825         /**
0826              * @brief updateCCDTemperature Update CCD temperature in capture module.
0827              * @param value Temperature in celcius.
0828              */
0829         void updateCCDTemperature(double value);
0830 
0831         // Auto Focus
0832         /**
0833          * @brief setFocusStatus Forward the new focus state to the capture module state machine
0834          */
0835         void setFocusStatus(FocusState newstate);
0836 
0837         /**
0838          * @brief updateFocusStatus Handle new focus state
0839          */
0840         void updateFocusStatus(FocusState newstate);
0841 
0842         // Adaptive Focus
0843         /**
0844          * @brief focusAdaptiveComplete Forward the new focus state to the capture module state machine
0845          */
0846         void focusAdaptiveComplete(bool success)
0847         {
0848             // directly forward it to the state machine
0849             state()->updateAdaptiveFocusState(success);
0850         }
0851 
0852         /**
0853          * @brief updateAdaptiveFocusStatus Handle new focus state
0854          */
0855 
0856         void setFocusTemperatureDelta(double focusTemperatureDelta, double absTemperature);
0857 
0858         /**
0859          * @brief setHFR Receive the measured HFR value of the latest frame
0860          */
0861         void setHFR(double newHFR, int position, bool inAutofocus);
0862 
0863         // Filter
0864         void setFilterStatus(FilterState filterState);
0865 
0866         // Guide
0867         void setGuideStatus(GuideState newstate);
0868 
0869         // Align
0870 
0871         void setAlignStatus(Ekos::AlignState newstate);
0872         void setAlignResults(double solverPA, double ra, double de, double pixscale);
0873 
0874         // Update Mount module status
0875         void setMountStatus(ISD::Mount::Status newState);
0876 
0877         // ////////////////////////////////////////////////////////////////////
0878         // Module logging
0879         // ////////////////////////////////////////////////////////////////////
0880         Q_SCRIPTABLE void clearLog();
0881         void appendLogText(const QString &);
0882 
0883 
0884     private slots:
0885 
0886         // ////////////////////////////////////////////////////////////////////
0887         // UI controls
0888         // ////////////////////////////////////////////////////////////////////
0889         void checkFrameType(int index);
0890         void updateCaptureCountDown(int deltaMillis);
0891         void saveFITSDirectory();
0892 
0893         // Sequence Queue
0894         void loadSequenceQueue();
0895         void saveSequenceQueue();
0896         void saveSequenceQueueAs();
0897 
0898         // Jobs
0899         void resetJobs();
0900         bool selectJob(QModelIndex i);
0901         void editJob(QModelIndex i);
0902         void resetJobEdit(bool cancelled = false);
0903 
0904         // Flat field
0905         void openCalibrationDialog();
0906 
0907         // Observer
0908         void showObserverDialog();
0909 
0910         // Cooler
0911         void setCoolerToggled(bool enabled);
0912 
0913         // ////////////////////////////////////////////////////////////////////
0914         // slots handling device and module events
0915         // ////////////////////////////////////////////////////////////////////
0916 
0917         // Script Manager
0918         void handleScriptsManager();
0919 
0920         void setVideoStreamEnabled(bool enabled);
0921 
0922         /**
0923          * @brief Listen to device property changes (temperature, rotator) that are triggered by
0924          *        SequenceJob.
0925          */
0926         void updatePrepareState(CaptureState prepareState);
0927 
0928         // Rotator
0929         void updateRotatorAngle(double value);
0930         void setRotatorReversed(bool toggled);
0931 
0932         /**
0933          * @brief setDownloadProgress update the Capture Module and Summary
0934          *        Screen's estimate of how much time is left in the download
0935          */
0936         void updateDownloadProgress(double downloadTimeLeft);
0937 
0938     signals:
0939         Q_SCRIPTABLE void newLog(const QString &text);
0940         Q_SCRIPTABLE void meridianFlipStarted();
0941         Q_SCRIPTABLE void guideAfterMeridianFlip();
0942         Q_SCRIPTABLE void newStatus(CaptureState status);
0943         Q_SCRIPTABLE void captureComplete(const QVariantMap &metadata);
0944 
0945         void newFilterStatus(FilterState state);
0946 
0947         void ready();
0948 
0949         // communication with other modules
0950         void checkFocus(double);
0951         void runAutoFocus(bool);
0952         void resetFocus();
0953         void abortFocus();
0954         void adaptiveFocus();
0955         void suspendGuiding();
0956         void resumeGuiding();
0957         void captureTarget(QString targetName);
0958         void newImage(SequenceJob *job, const QSharedPointer<FITSData> &data);
0959         void newExposureProgress(SequenceJob *job);
0960         void newDownloadProgress(double);
0961         void sequenceChanged(const QJsonArray &sequence);
0962         void settingsUpdated(const QJsonObject &settings);
0963         void newLocalPreview(const QString &preview);
0964         void dslrInfoRequested(const QString &cameraName);
0965         void driverTimedout(const QString &deviceName);
0966 
0967         // Signals for the Analyze tab.
0968         void captureStarting(double exposureSeconds, const QString &filter);
0969         void captureAborted(double exposureSeconds);
0970 
0971         // Filter Manager
0972         void filterManagerUpdated(ISD::FilterWheel *device);
0973 
0974         void trainChanged();
0975 
0976 
0977     private:
0978         // ////////////////////////////////////////////////////////////////////
0979         // capture process steps
0980         // ////////////////////////////////////////////////////////////////////
0981         /**
0982          * @brief captureImageStarted Image capturing for the active job has started.
0983          */
0984         void captureImageStarted();
0985 
0986         /**
0987          * @brief jobPreparationStarted Preparation actions for the current active job have beenstarted.
0988          */
0989         void jobExecutionPreparationStarted();
0990 
0991         /**
0992          * @brief jobPrepared Select the job that is currently in preparation.
0993          */
0994         void jobPrepared(SequenceJob *job);
0995 
0996         /**
0997          * @brief imageCapturingCompleted Capturing a single frame completed
0998          */
0999         void imageCapturingCompleted();
1000 
1001         /**
1002          * @brief captureStopped Capturing has stopped
1003          */
1004         void captureStopped();
1005 
1006         /**
1007          * @brief processFITSfinished processing new FITS data received from camera finished.
1008          * @param success true iff processing was successful
1009          */
1010         void processingFITSfinished(bool success);
1011 
1012         // Propagate meridian flip state changes to the UI
1013         void updateMeridianFlipStage(MeridianFlipState::MFStage stage);
1014 
1015         // ////////////////////////////////////////////////////////////////////
1016         // Job table handling
1017         // ////////////////////////////////////////////////////////////////////
1018 
1019 
1020         /**
1021          * @brief updateJobTable Update the table row values for the given sequence job. If the job
1022          * is null, all rows will be updated
1023          * @param job as identifier for the row
1024          * @param full if false, then only the status and the counter will be updated.
1025          */
1026         void updateJobTable(SequenceJob *job, bool full = false);
1027 
1028 
1029         /**
1030          * @brief Update the style of the job's row, depending on the job's state
1031          */
1032         void updateRowStyle(SequenceJob *job);
1033 
1034         /**
1035          * @brief updateCellStyle Update the cell's style. If active is true, set a bold and italic font and
1036          * a regular font otherwise.
1037          */
1038         void updateCellStyle(QTableWidgetItem *cell, bool active);
1039 
1040         /**
1041          * @brief updateJobTableCountCell Update the job counter in the job table of a sigle job
1042          */
1043         void updateJobTableCountCell(SequenceJob *job, QTableWidgetItem *countCell);
1044 
1045         // ////////////////////////////////////////////////////////////////////
1046         // helper functions
1047         // ////////////////////////////////////////////////////////////////////
1048         // check if the upload paths are filled correctly
1049         bool checkUploadPaths(FilenamePreviewType filenamePreview);
1050 
1051         // create a new row in the job table and fill it with the given job's values
1052         void createNewJobTableRow(SequenceJob *job);
1053 
1054         // Create a Json job from the current job table row
1055         QJsonObject createJsonJob(SequenceJob *job, int currentRow);
1056 
1057         // shortcut for the module state
1058         QSharedPointer<CaptureModuleState> state() const
1059         {
1060             return m_captureModuleState;
1061         }
1062         // shortcut to device adapter
1063         QSharedPointer<CaptureDeviceAdaptor> devices()
1064         {
1065             return m_captureDeviceAdaptor;
1066         }
1067         // shortcut for the active job
1068         SequenceJob *activeJob() const
1069         {
1070             return state()->getActiveJob();
1071         }
1072         // Shortcut to the active camera held in the device adaptor
1073         ISD::Camera *activeCamera();
1074 
1075         // Filename preview
1076         void generatePreviewFilename();
1077         QString previewFilename(FilenamePreviewType = LOCAL_PREVIEW);
1078 
1079         void setBusy(bool enable);
1080 
1081         /* Capture */
1082         void createDSLRDialog();
1083 
1084         void resetFrameToZero();
1085 
1086         /**
1087          * @brief Sync refocus options to the GUI settings
1088          */
1089         void syncRefocusOptionsFromGUI();
1090 
1091         /**
1092          * @brief currentScope Retrieve the scope parameters from the optical train.
1093          */
1094         QJsonObject currentScope();
1095 
1096         /**
1097          * @brief currentReducer Retrieve the reducer parameters from the optical train.
1098          */
1099         double currentReducer();
1100 
1101         /**
1102          * @brief currentAperture Determine the current aperture
1103          * @return
1104          */
1105         double currentAperture();
1106 
1107         // ////////////////////////////////////////////////////////////////////
1108         // UI controls
1109         // ////////////////////////////////////////////////////////////////////
1110         /**
1111          * @brief setBinning Set binning
1112          * @param horBin Horizontal binning
1113          * @param verBin Vertical binning
1114          */
1115         void setBinning(int horBin, int verBin)
1116         {
1117             captureBinHN->setValue(horBin);
1118             captureBinVN->setValue(verBin);
1119         }
1120 
1121         /**
1122          * @brief setISO Set index of ISO list.
1123          * @param index index of ISO list.
1124          */
1125         void setISO(int index)
1126         {
1127             captureISOS->setCurrentIndex(index);
1128         }
1129 
1130         // reset = 0 --> Do not reset
1131         // reset = 1 --> Full reset
1132         // reset = 2 --> Only update limits if needed
1133         void updateFrameProperties(int reset = 0);
1134 
1135         /**
1136          * @brief updateCaptureFormats Update encoding and transfer formats
1137          */
1138         void updateCaptureFormats();
1139 
1140         /**
1141          * @brief updateHFRCheckAlgo Update the in-sequence HFR check algorithm
1142          */
1143         void updateHFRCheckAlgo();
1144 
1145         /**
1146          * @brief syncGUIToJob Update UI to job settings
1147          */
1148         void syncGUIToJob(SequenceJob *job);
1149         /**
1150          * @brief syncGUIToState Update UI to general settings from Options
1151          */
1152         void syncGUIToGeneralSettings();
1153 
1154         // DSLR Info
1155         void cullToDSLRLimits();
1156         //void syncDriverToDSLRLimits();
1157 
1158         // selection of a job
1159         void selectedJobChanged(QModelIndex current, QModelIndex previous);
1160 
1161         // Change filter name in INDI
1162         void editFilterName();
1163         bool editFilterNameInternal(const QStringList &labels, QStringList &newLabels);
1164 
1165         // ////////////////////////////////////////////////////////////////////
1166         // device control
1167         // ////////////////////////////////////////////////////////////////////
1168         // Gain
1169         // This sets and gets the custom properties target gain
1170         // it does not access the ccd gain property
1171         void setGain(double value);
1172         double getGain();
1173 
1174         void setOffset(double value);
1175         double getOffset();
1176 
1177         void setStandAloneGain(double value);
1178         void setStandAloneOffset(double value);
1179 
1180         /**
1181          * @brief processCCDNumber Process number properties arriving from CCD. Currently, only CCD and Guider frames are processed.
1182          * @param nvp pointer to number property.
1183          */
1184         void processCCDNumber(INumberVectorProperty *nvp);
1185 
1186         // Disable all the widgets that aren't used in stand-alone mode.
1187         void initStandAlone();
1188 
1189         // ////////////////////////////////////////////////////////////////////
1190         // Attributes
1191         // ////////////////////////////////////////////////////////////////////
1192         double seqExpose { 0 };
1193         int seqTotalCount;
1194         int seqCurrentCount { 0 };
1195 
1196         QPointer<CaptureProcess> m_captureProcess;
1197         QSharedPointer<CaptureModuleState> m_captureModuleState;
1198 
1199         QPointer<QDBusInterface> mountInterface;
1200 
1201         QStringList m_LogText;
1202         bool m_JobUnderEdit { false };
1203 
1204         // Flat field automation
1205         QMap<ScriptTypes, QString> m_Scripts;
1206 
1207         QUrl dirPath;
1208 
1209         std::unique_ptr<CustomProperties> customPropertiesDialog;
1210         std::unique_ptr<DSLRInfo> dslrInfoDialog;
1211 
1212         // Controls
1213         double GainSpinSpecialValue { INVALID_VALUE };
1214         double OffsetSpinSpecialValue { INVALID_VALUE };
1215 
1216         // sub dialogs
1217         std::unique_ptr<Ui::Limits> m_LimitsUI;
1218         QPointer<QDialog> m_LimitsDialog;
1219         QPointer<ScriptsManager> m_scriptsManager;
1220 
1221 
1222         QVariantMap m_Metadata;
1223 
1224         QSharedPointer<FilterManager> m_FilterManager;
1225         QSharedPointer<RotatorSettings> m_RotatorControlPanel;
1226 
1227         bool m_standAlone {false};
1228         bool m_standAloneUseCcdGain { true};
1229         bool m_standAloneUseCcdOffset { true};
1230 };
1231 
1232 }