1 /* 2 SPDX-FileCopyrightText: 2012 Jasem Mutlaq <mutlaqja@ikarustech.com> 3 4 SPDX-License-Identifier: GPL-2.0-or-later 5 */ 6 7 #pragma once 8 9 #include "indistd.h" 10 #include "wsmedia.h" 11 #include "auxiliary/imageviewer.h" 12 #include "fitsviewer/fitscommon.h" 13 #include "fitsviewer/fitsview.h" 14 #include "fitsviewer/fitsviewer.h" 15 #include "ekos/capture/placeholderpath.h" 16 17 #include <QStringList> 18 #include <QPointer> 19 #include <QtConcurrent> 20 21 #include <memory> 22 23 class FITSData; 24 class FITSView; 25 class QTimer; 26 class StreamWG; 27 28 /** 29 * \namespace ISD 30 * 31 * ISD is a collection of INDI Standard Devices. It encapsulates common types of INDI devices such as telescopes and CCDs. 32 * 33 */ 34 namespace ISD 35 { 36 class CCD; 37 38 /** 39 * @class CCDChip 40 * CCDChip class controls a particular chip in CCD device. While most amateur CCDs only have a single chip on the CCD, some 41 * CCDs have additional chips targetted for guiding purposes. 42 */ 43 class CCDChip 44 { 45 public: 46 typedef enum { PRIMARY_CCD, GUIDE_CCD } ChipType; 47 48 CCDChip(ISD::CCD *ccd, ChipType cType); 49 50 FITSView *getImageView(FITSMode imageType); 51 void setImageView(FITSView *image, FITSMode imageType); setCaptureMode(FITSMode mode)52 void setCaptureMode(FITSMode mode) 53 { 54 captureMode = mode; 55 } setCaptureFilter(FITSScale fType)56 void setCaptureFilter(FITSScale fType) 57 { 58 captureFilter = fType; 59 } 60 61 // Common commands 62 bool getFrame(int *x, int *y, int *w, int *h); 63 bool getFrameMinMax(int *minX, int *maxX, int *minY, int *maxY, int *minW, int *maxW, int *minH, int *maxH); 64 bool setFrame(int x, int y, int w, int h, bool force = false); 65 66 bool resetFrame(); 67 bool capture(double exposure); 68 bool setFrameType(CCDFrameType fType); 69 bool setFrameType(const QString &name); 70 CCDFrameType getFrameType(); 71 bool setBinning(int bin_x, int bin_y); 72 bool setBinning(CCDBinType binType); 73 CCDBinType getBinning(); 74 bool getBinning(int *bin_x, int *bin_y); 75 bool getMaxBin(int *max_xbin, int *max_ybin); getType()76 ChipType getType() const 77 { 78 return type; 79 } getCCD()80 ISD::CCD *getCCD() 81 { 82 return parentCCD; 83 } 84 85 // Set Image Info 86 bool setImageInfo(uint16_t width, uint16_t height, double pixelX, double pixelY, uint8_t bitdepth); 87 // Get Image Info 88 bool getImageInfo(uint16_t &width, uint16_t &height, double &pixelX, double &pixelY, uint8_t &bitdepth); 89 // Bayer Info 90 bool getBayerInfo(uint16_t &offsetX, uint16_t &offsetY, QString &pattern); 91 92 bool isCapturing(); 93 bool abortExposure(); 94 getCaptureMode()95 FITSMode getCaptureMode() const 96 { 97 return captureMode; 98 } getCaptureFilter()99 FITSScale getCaptureFilter() const 100 { 101 return captureFilter; 102 } isBatchMode()103 bool isBatchMode() const 104 { 105 return batchMode; 106 } setBatchMode(bool enable)107 void setBatchMode(bool enable) 108 { 109 batchMode = enable; 110 } getFrameTypes()111 QStringList getFrameTypes() const 112 { 113 return frameTypes; 114 } addFrameLabel(const QString & label)115 void addFrameLabel(const QString &label) 116 { 117 frameTypes << label; 118 } clearFrameTypes()119 void clearFrameTypes() 120 { 121 frameTypes.clear(); 122 } 123 124 bool canBin() const; 125 void setCanBin(bool value); 126 127 bool canSubframe() const; 128 void setCanSubframe(bool value); 129 130 bool canAbort() const; 131 void setCanAbort(bool value); 132 133 const QSharedPointer<FITSData> &getImageData() const; setImageData(const QSharedPointer<FITSData> & data)134 void setImageData(const QSharedPointer<FITSData> &data) 135 { 136 imageData = data; 137 } 138 139 int getISOIndex() const; 140 bool setISOIndex(int value); 141 142 QStringList getISOList() const; 143 144 private: 145 QPointer<FITSView> normalImage, focusImage, guideImage, calibrationImage, alignImage; 146 QSharedPointer<FITSData> imageData { nullptr }; 147 FITSMode captureMode { FITS_NORMAL }; 148 FITSScale captureFilter { FITS_NONE }; 149 INDI::BaseDevice *baseDevice { nullptr }; 150 ClientManager *clientManager { nullptr }; 151 ChipType type; 152 bool batchMode { false }; 153 QStringList frameTypes; 154 bool CanBin { false }; 155 bool CanSubframe { false }; 156 bool CanAbort { false }; 157 ISD::CCD *parentCCD { nullptr }; 158 }; 159 160 /** 161 * @class CCD 162 * CCD class controls an INDI CCD device. It can be used to issue and abort capture commands, receive and process BLOBs, 163 * and return information on the capabilities of the CCD. 164 * 165 * @author Jasem Mutlaq 166 */ 167 class CCD : public DeviceDecorator 168 { 169 Q_OBJECT 170 171 public: 172 explicit CCD(GDInterface *iPtr); 173 virtual ~CCD() override; 174 175 typedef enum { UPLOAD_CLIENT, UPLOAD_LOCAL, UPLOAD_BOTH } UploadMode; 176 typedef enum { FORMAT_FITS, FORMAT_NATIVE } TransferFormat; 177 enum BlobType 178 { 179 BLOB_IMAGE, 180 BLOB_FITS, 181 BLOB_RAW, 182 BLOB_OTHER 183 } BType; 184 typedef enum { TELESCOPE_PRIMARY, TELESCOPE_GUIDE, TELESCOPE_UNKNOWN } TelescopeType; 185 typedef enum 186 { 187 ERROR_CAPTURE, /** INDI Camera error */ 188 ERROR_SAVE, /** Saving to disk error */ 189 ERROR_LOAD, /** Loading image buffer error */ 190 ERROR_VIEWER /** Loading in FITS Viewer Error */ 191 } ErrorType; 192 193 void registerProperty(INDI::Property prop) override; 194 void removeProperty(const QString &name) override; 195 void processSwitch(ISwitchVectorProperty *svp) override; 196 void processText(ITextVectorProperty *tvp) override; 197 void processNumber(INumberVectorProperty *nvp) override; 198 void processLight(ILightVectorProperty *lvp) override; 199 void processBLOB(IBLOB *bp) override; 200 getType()201 DeviceFamily getType() override 202 { 203 return dType; 204 } 205 206 // Does it an on-chip dedicated guide head? 207 bool hasGuideHead(); 208 // Does it report temperature? 209 bool hasCooler(); 210 // Can temperature be controlled? canCool()211 bool canCool() 212 { 213 return CanCool; 214 } 215 // Does it have active cooler on/off controls? 216 bool hasCoolerControl(); 217 bool setCoolerControl(bool enable); 218 bool isCoolerOn(); 219 // Does it have a video stream? hasVideoStream()220 bool hasVideoStream() 221 { 222 return HasVideoStream; 223 } 224 225 // Temperature controls 226 bool getTemperature(double *value); 227 bool setTemperature(double value); 228 229 // Temperature Regulation 230 bool getTemperatureRegulation(double &ramp, double &threshold); 231 bool setTemperatureRegulation(double ramp, double threshold); 232 233 // Utility functions setISOMode(bool enable)234 void setISOMode(bool enable) 235 { 236 ISOMode = enable; 237 } setSeqPrefix(const QString & preFix)238 void setSeqPrefix(const QString &preFix) 239 { 240 seqPrefix = preFix; 241 } setPlaceholderPath(Ekos::PlaceholderPath php)242 void setPlaceholderPath(Ekos::PlaceholderPath php) 243 { 244 placeholderPath = php; 245 } setNextSequenceID(int count)246 void setNextSequenceID(int count) 247 { 248 nextSequenceID = count; 249 } 250 251 // Gain controls hasGain()252 bool hasGain() 253 { 254 return gainN != nullptr; 255 } 256 bool getGain(double *value); getGainPermission()257 IPerm getGainPermission() const 258 { 259 return gainPerm; 260 } 261 bool setGain(double value); 262 bool getGainMinMaxStep(double *min, double *max, double *step); 263 264 // offset controls hasOffset()265 bool hasOffset() 266 { 267 return offsetN != nullptr; 268 } 269 bool getOffset(double *value); getOffsetPermission()270 IPerm getOffsetPermission() const 271 { 272 return offsetPerm; 273 } 274 bool setOffset(double value); 275 bool getOffsetMinMaxStep(double *min, double *max, double *step); 276 277 // Rapid Guide 278 bool configureRapidGuide(CCDChip *targetChip, bool autoLoop, bool sendImage = false, bool showMarker = false); 279 bool setRapidGuide(CCDChip *targetChip, bool enable); 280 281 // Upload Settings 282 void updateUploadSettings(const QString &remoteDir); 283 UploadMode getUploadMode(); 284 bool setUploadMode(UploadMode mode); 285 286 // Transfer Format getTransferFormat()287 TransferFormat getTransferFormat() 288 { 289 return transferFormat; 290 } 291 bool setTransformFormat(CCD::TransferFormat format); 292 293 // BLOB control 294 bool isBLOBEnabled(); 295 bool setBLOBEnabled(bool enable, const QString &prop = QString()); 296 297 // Video Stream 298 bool setVideoStreamEnabled(bool enable); 299 bool resetStreamingFrame(); 300 bool setStreamingFrame(int x, int y, int w, int h); 301 bool isStreamingEnabled(); 302 bool setStreamExposure(double duration); 303 bool getStreamExposure(double *duration); 304 bool setStreamLimits(uint16_t maxBufferSize, uint16_t maxPreviewFPS); 305 306 // Video Recording 307 bool setSERNameDirectory(const QString &filename, const QString &directory); 308 bool getSERNameDirectory(QString &filename, QString &directory); 309 bool startRecording(); 310 bool startDurationRecording(double duration); 311 bool startFramesRecording(uint32_t frames); 312 bool stopRecording(); 313 314 // Telescope type getTelescopeType()315 TelescopeType getTelescopeType() 316 { 317 return telescopeType; 318 } 319 bool setTelescopeType(TelescopeType type); 320 321 // Update FITS Header 322 bool setFITSHeader(const QMap<QString, QString> &values); 323 324 CCDChip *getChip(CCDChip::ChipType cType); 325 326 TransferFormat getTargetTransferFormat() const; 327 void setTargetTransferFormat(const TransferFormat &value); 328 329 bool setFastExposureEnabled(bool enable); isFastExposureEnabled()330 bool isFastExposureEnabled() const 331 { 332 return m_FastExposureEnabled; 333 } 334 bool setFastCount(uint32_t count); 335 getExposurePresets()336 const QMap<QString, double> &getExposurePresets() const 337 { 338 return m_ExposurePresets; 339 } getExposurePresetsMinMax()340 const QPair<double, double> getExposurePresetsMinMax() const 341 { 342 return m_ExposurePresetsMinMax; 343 } 344 345 public slots: 346 //void FITSViewerDestroyed(); 347 void StreamWindowHidden(); 348 // Blob manager 349 void setBLOBManager(const char *device, INDI::Property prop); 350 351 protected slots: 352 void setWSBLOB(const QByteArray &message, const QString &extension); 353 354 signals: 355 void newTemperatureValue(double value); 356 void newExposureValue(ISD::CCDChip *chip, double value, IPState state); 357 void newGuideStarData(ISD::CCDChip *chip, double dx, double dy, double fit); 358 void newBLOBManager(INDI::Property prop); 359 void newRemoteFile(QString); 360 void videoStreamToggled(bool enabled); 361 void videoRecordToggled(bool enabled); 362 void newFPS(double instantFPS, double averageFPS); 363 void newVideoFrame(const QSharedPointer<QImage> &frame); 364 void coolerToggled(bool enabled); 365 void ready(); 366 void error(ErrorType type); 367 void newImage(const QSharedPointer<FITSData> &data); 368 369 private: 370 void processStream(IBLOB *bp); 371 void loadImageInView(ISD::CCDChip *targetChip, const QSharedPointer<FITSData> &data); 372 bool generateFilename(bool batch_mode, const QString &extension, QString *filename); 373 // Saves an image to disk on a separate thread. 374 bool writeImageFile(const QString &filename, IBLOB *bp, bool is_fits); 375 bool WriteImageFileInternal(const QString &filename, char *buffer, const size_t size); 376 // Creates or finds the FITSViewer. 377 QPointer<FITSViewer> getFITSViewer(); 378 void handleImage(CCDChip *targetChip, const QString &filename, IBLOB *bp, QSharedPointer<FITSData> data); 379 380 bool ISOMode { true }; 381 bool HasGuideHead { false }; 382 bool HasCooler { false }; 383 bool CanCool { false }; 384 bool HasCoolerControl { false }; 385 bool HasVideoStream { false }; 386 bool m_FastExposureEnabled { false }; 387 QString seqPrefix; 388 Ekos::PlaceholderPath placeholderPath; 389 390 int nextSequenceID { 0 }; 391 std::unique_ptr<StreamWG> streamWindow; 392 int streamW { 0 }; 393 int streamH { 0 }; 394 int normalTabID { -1 }; 395 int calibrationTabID { -1 }; 396 int focusTabID { -1 }; 397 int guideTabID { -1 }; 398 int alignTabID { -1 }; 399 400 //char BLOBFilename[MAXINDIFILENAME + 1]; 401 IBLOB *primaryCCDBLOB { nullptr }; 402 403 std::unique_ptr<QTimer> readyTimer; 404 std::unique_ptr<CCDChip> primaryChip; 405 std::unique_ptr<CCDChip> guideChip; 406 std::unique_ptr<WSMedia> m_Media; 407 TransferFormat transferFormat { FORMAT_FITS }; 408 TransferFormat targetTransferFormat { FORMAT_FITS }; 409 TelescopeType telescopeType { TELESCOPE_UNKNOWN }; 410 411 // Gain, since it is spread among different vector properties, let's try to find the property itself. 412 INumber *gainN { nullptr }; 413 IPerm gainPerm { IP_RO }; 414 415 INumber *offsetN { nullptr }; 416 IPerm offsetPerm { IP_RO }; 417 418 QPointer<FITSViewer> m_FITSViewerWindow; 419 QPointer<ImageViewer> m_ImageViewerWindow; 420 421 QDateTime m_LastNotificationTS; 422 423 // Typically for DSLRs 424 QMap<QString, double> m_ExposurePresets; 425 QPair<double, double> m_ExposurePresetsMinMax; 426 427 // Used when writing the image fits file to disk in a separate thread. 428 char *fileWriteBuffer { nullptr }; 429 int fileWriteBufferSize { 0 }; 430 QString fileWriteFilename; 431 QFuture<void> fileWriteThread; 432 }; 433 } 434