File indexing completed on 2024-04-28 11:24:40
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 "indiconcretedevice.h" 0010 #include "indicamerachip.h" 0011 0012 #include "wsmedia.h" 0013 #include "auxiliary/imageviewer.h" 0014 #include "fitsviewer/fitsdata.h" 0015 #include "fitsviewer/fitsviewer.h" 0016 #include "ekos/capture/placeholderpath.h" 0017 0018 #include <QStringList> 0019 #include <QPointer> 0020 #include <QtConcurrent> 0021 0022 #include <memory> 0023 0024 class FITSData; 0025 class FITSView; 0026 class QTimer; 0027 class StreamWG; 0028 0029 /** 0030 * \namespace ISD 0031 * 0032 * ISD is a collection of INDI Standard Devices. It encapsulates common types of INDI devices such as telescopes and CCDs. 0033 * 0034 */ 0035 namespace ISD 0036 { 0037 class CameraChip; 0038 0039 /** 0040 * @class Camera 0041 * Camera class controls an INDI Camera device. It can be used to issue and abort capture commands, receive and process BLOBs, 0042 * and return information on the capabilities of the camera. 0043 * 0044 * @author Jasem Mutlaq 0045 */ 0046 class Camera : public ConcreteDevice 0047 { 0048 Q_OBJECT 0049 Q_PROPERTY(bool StreamingEnabled MEMBER m_StreamingEnabled) 0050 0051 public: 0052 explicit Camera(ISD::GenericDevice *parent); 0053 virtual ~Camera() override; 0054 0055 typedef enum { UPLOAD_CLIENT, UPLOAD_LOCAL, UPLOAD_BOTH } UploadMode; 0056 enum BlobType 0057 { 0058 BLOB_IMAGE, 0059 BLOB_FITS, 0060 BLOB_XISF, 0061 BLOB_RAW, 0062 BLOB_OTHER 0063 } BType; 0064 typedef enum { TELESCOPE_PRIMARY, TELESCOPE_GUIDE, TELESCOPE_UNKNOWN } TelescopeType; 0065 typedef enum 0066 { 0067 ERROR_CAPTURE, /** INDI Camera error */ 0068 ERROR_SAVE, /** Saving to disk error */ 0069 ERROR_LOAD, /** Loading image buffer error */ 0070 ERROR_VIEWER /** Loading in FITS Viewer Error */ 0071 } ErrorType; 0072 0073 void registerProperty(INDI::Property prop) override; 0074 void removeProperty(INDI::Property prop) override; 0075 0076 void processSwitch(INDI::Property prop) override; 0077 void processText(INDI::Property prop) override; 0078 void processNumber(INDI::Property prop) override; 0079 bool processBLOB(INDI::Property prop) override; 0080 0081 // Does it an on-chip dedicated guide head? 0082 bool hasGuideHead(); 0083 // Does it report temperature? 0084 bool hasCooler(); 0085 // Can temperature be controlled? 0086 bool canCool() 0087 { 0088 return CanCool; 0089 } 0090 // Does it have active cooler on/off controls? 0091 bool hasCoolerControl(); 0092 bool setCoolerControl(bool enable); 0093 bool isCoolerOn(); 0094 // Does it have a video stream? 0095 bool hasVideoStream() 0096 { 0097 return HasVideoStream; 0098 } 0099 0100 // Temperature controls 0101 bool getTemperature(double *value); 0102 bool setTemperature(double value); 0103 0104 // Temperature Regulation 0105 bool getTemperatureRegulation(double &ramp, double &threshold); 0106 bool setTemperatureRegulation(double ramp, double threshold); 0107 0108 bool setScopeInfo(double focalLength, double aperture); 0109 0110 // Utility functions 0111 void setSeqPrefix(const QString &preFix) 0112 { 0113 seqPrefix = preFix; 0114 } 0115 void setPlaceholderPath(const Ekos::PlaceholderPath &php) 0116 { 0117 placeholderPath = php; 0118 } 0119 void setNextSequenceID(int count) 0120 { 0121 nextSequenceID = count; 0122 } 0123 0124 // Gain controls 0125 bool hasGain() 0126 { 0127 return gainN != nullptr; 0128 } 0129 bool getGain(double *value); 0130 IPerm getGainPermission() const 0131 { 0132 return gainPerm; 0133 } 0134 bool setGain(double value); 0135 bool getGainMinMaxStep(double *min, double *max, double *step); 0136 0137 // offset controls 0138 bool hasOffset() 0139 { 0140 return offsetN != nullptr; 0141 } 0142 bool getOffset(double *value); 0143 IPerm getOffsetPermission() const 0144 { 0145 return offsetPerm; 0146 } 0147 bool setOffset(double value); 0148 bool getOffsetMinMaxStep(double *min, double *max, double *step); 0149 0150 // Rapid Guide 0151 bool configureRapidGuide(CameraChip *targetChip, bool autoLoop, bool sendImage = false, bool showMarker = false); 0152 bool setRapidGuide(CameraChip *targetChip, bool enable); 0153 0154 // Upload Settings 0155 void updateUploadSettings(const QString &uploadDirectory, const QString &uploadFile); 0156 UploadMode getUploadMode(); 0157 bool setUploadMode(UploadMode mode); 0158 0159 // Encoding Format 0160 const QString &getEncodingFormat() const 0161 { 0162 return m_EncodingFormat; 0163 } 0164 bool setEncodingFormat(const QString &value); 0165 const QStringList &getEncodingFormats() const 0166 { 0167 return m_EncodingFormats; 0168 } 0169 0170 // FITS Viewer Stretch values 0171 // TODO: Need to remove all FITSViewer related functions from INDI::Camera 0172 Q_SCRIPTABLE void setStretchValues(double shadows, double midtones, double highlights); 0173 Q_SCRIPTABLE void setAutoStretch(); 0174 Q_SCRIPTABLE void toggleHiPSOverlay(); 0175 0176 // Capture Format 0177 const QStringList &getCaptureFormats() const 0178 { 0179 return m_CaptureFormats; 0180 } 0181 QString getCaptureFormat() const; 0182 bool setCaptureFormat(const QString &format); 0183 0184 // BLOB control 0185 bool isBLOBEnabled(); 0186 bool setBLOBEnabled(bool enable, const QString &prop = QString()); 0187 0188 // Video Stream 0189 bool setVideoStreamEnabled(bool enable); 0190 bool resetStreamingFrame(); 0191 bool setStreamingFrame(int x, int y, int w, int h); 0192 bool isStreamingEnabled(); 0193 bool setStreamExposure(double duration); 0194 bool getStreamExposure(double *duration); 0195 bool setStreamLimits(uint16_t maxBufferSize, uint16_t maxPreviewFPS); 0196 0197 // Video Recording 0198 bool setSERNameDirectory(const QString &filename, const QString &directory); 0199 bool getSERNameDirectory(QString &filename, QString &directory); 0200 bool startRecording(); 0201 bool startDurationRecording(double duration); 0202 bool startFramesRecording(uint32_t frames); 0203 bool stopRecording(); 0204 0205 // Telescope type 0206 TelescopeType getTelescopeType() 0207 { 0208 return telescopeType; 0209 } 0210 bool setTelescopeType(TelescopeType type); 0211 0212 // Update FITS Header 0213 bool setFITSHeaders(const QList<FITSData::Record> &values); 0214 0215 CameraChip *getChip(CameraChip::ChipType cType); 0216 0217 bool setFastExposureEnabled(bool enable); 0218 bool isFastExposureEnabled() const 0219 { 0220 return m_FastExposureEnabled; 0221 } 0222 bool setFastCount(uint32_t count); 0223 0224 const QMap<QString, double> &getExposurePresets() const 0225 { 0226 return m_ExposurePresets; 0227 } 0228 const QPair<double, double> getExposurePresetsMinMax() const 0229 { 0230 return m_ExposurePresetsMinMax; 0231 } 0232 0233 public slots: 0234 void StreamWindowHidden(); 0235 // Blob manager 0236 void setBLOBManager(const char *device, INDI::Property prop); 0237 0238 protected slots: 0239 void setWSBLOB(const QByteArray &message, const QString &extension); 0240 0241 signals: 0242 void newTemperatureValue(double value); 0243 void newExposureValue(ISD::CameraChip *chip, double value, IPState state); 0244 void newGuideStarData(ISD::CameraChip *chip, double dx, double dy, double fit); 0245 void newBLOBManager(INDI::Property prop); 0246 void newRemoteFile(QString); 0247 void coolerToggled(bool enabled); 0248 void error(ErrorType type); 0249 // Video 0250 void videoStreamToggled(bool enabled); 0251 void videoRecordToggled(bool enabled); 0252 void newFPS(double instantFPS, double averageFPS); 0253 void newVideoFrame(const QSharedPointer<QImage> &frame); 0254 // Data 0255 void newImage(const QSharedPointer<FITSData> &data); 0256 // View 0257 void newView(const QSharedPointer<FITSView> &view); 0258 0259 private: 0260 void processStream(INDI::Property prop); 0261 bool generateFilename(bool batch_mode, const QString &extension, QString *filename); 0262 // Saves an image to disk on a separate thread. 0263 bool writeImageFile(const QString &filename, INDI::Property prop, bool is_fits); 0264 bool WriteImageFileInternal(const QString &filename, char *buffer, const size_t size); 0265 // Creates or finds the FITSViewer. 0266 // TODO: Need to remove all FITSViewer related functions from INDI::Camera 0267 QSharedPointer<FITSViewer> getFITSViewer(); 0268 void handleImage(CameraChip *targetChip, const QString &filename, INDI::Property prop, QSharedPointer<FITSData> data); 0269 0270 bool HasGuideHead { false }; 0271 bool HasCooler { false }; 0272 bool CanCool { false }; 0273 bool HasCoolerControl { false }; 0274 bool HasVideoStream { false }; 0275 bool m_FastExposureEnabled { false }; 0276 QString seqPrefix; 0277 Ekos::PlaceholderPath placeholderPath; 0278 0279 int nextSequenceID { 0 }; 0280 std::unique_ptr<StreamWG> streamWindow; 0281 int streamW { 0 }; 0282 int streamH { 0 }; 0283 int normalTabID { -1 }; 0284 int calibrationTabID { -1 }; 0285 int focusTabID { -1 }; 0286 int guideTabID { -1 }; 0287 int alignTabID { -1 }; 0288 0289 INDI::Property primaryCCDBLOB; 0290 0291 std::unique_ptr<CameraChip> primaryChip; 0292 std::unique_ptr<CameraChip> guideChip; 0293 std::unique_ptr<WSMedia> m_Media; 0294 QString m_EncodingFormat {"FITS"}; 0295 QStringList m_EncodingFormats; 0296 QStringList m_CaptureFormats; 0297 bool m_StreamingEnabled {true}; 0298 int m_CaptureFormatIndex {-1}; 0299 TelescopeType telescopeType { TELESCOPE_UNKNOWN }; 0300 0301 // Gain, since it is spread among different vector properties, let's try to find the property itself. 0302 INumber *gainN { nullptr }; 0303 IPerm gainPerm { IP_RO }; 0304 0305 INumber *offsetN { nullptr }; 0306 IPerm offsetPerm { IP_RO }; 0307 0308 QSharedPointer<FITSViewer> m_FITSViewerWindow; 0309 QPointer<ImageViewer> m_ImageViewerWindow; 0310 0311 QDateTime m_LastNotificationTS; 0312 0313 // Typically for DSLRs 0314 QMap<QString, double> m_ExposurePresets; 0315 QPair<double, double> m_ExposurePresetsMinMax; 0316 0317 // Used when writing the image fits file to disk in a separate thread. 0318 char *fileWriteBuffer { nullptr }; 0319 int fileWriteBufferSize { 0 }; 0320 QString fileWriteFilename; 0321 QFuture<void> fileWriteThread; 0322 }; 0323 }