File indexing completed on 2024-07-21 06:28:20

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 }