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 }