8#include "indicamerachip.h"
10#include "config-kstars.h"
12#include "indi_debug.h"
14#include "clientmanager.h"
20#include "fitsviewer/fitsdata.h"
23#include <knotification.h>
24#include "auxiliary/ksmessagebox.h"
25#include "ksnotification.h"
26#include <QImageReader>
29#include <QtConcurrent>
31#include <basedevice.h>
33const QStringList RAWFormats = {
"cr2",
"cr3",
"crw",
"nef",
"raf",
"dng",
"arw",
"orf" };
35const QString &getFITSModeStringString(FITSMode mode)
37 return FITSModes[mode];
43Camera::Camera(GenericDevice *parent) : ConcreteDevice(parent)
45 primaryChip.reset(
new CameraChip(
this, CameraChip::PRIMARY_CCD));
47 m_Media.reset(
new WSMedia(
this));
48 connect(m_Media.get(), &WSMedia::newFile,
this, &Camera::setWSBLOB);
56 if (m_ImageViewerWindow)
57 m_ImageViewerWindow->close();
58 if (fileWriteThread.isRunning())
59 fileWriteThread.waitForFinished();
60 if (fileWriteBuffer !=
nullptr)
61 delete [] fileWriteBuffer;
64void Camera::setBLOBManager(
const char *device, INDI::Property prop)
66 if (!prop.getRegistered())
69 if (getDeviceName() == device)
70 emit newBLOBManager(prop);
73void Camera::registerProperty(INDI::Property prop)
75 if (prop.isNameMatch(
"GUIDER_EXPOSURE"))
78 guideChip.reset(
new CameraChip(
this, CameraChip::GUIDE_CCD));
80 else if (prop.isNameMatch(
"CCD_FRAME_TYPE"))
82 primaryChip->clearFrameTypes();
84 for (
auto &it : *prop.getSwitch())
85 primaryChip->addFrameLabel(it.getLabel());
87 else if (prop.isNameMatch(
"CCD_FRAME"))
89 auto np = prop.getNumber();
90 if (np && np->getPermission() != IP_RO)
91 primaryChip->setCanSubframe(
true);
93 else if (prop.isNameMatch(
"GUIDER_FRAME"))
95 auto np = prop.getNumber();
96 if (np && np->getPermission() != IP_RO)
97 guideChip->setCanSubframe(
true);
99 else if (prop.isNameMatch(
"CCD_BINNING"))
101 auto np = prop.getNumber();
102 if (np && np->getPermission() != IP_RO)
103 primaryChip->setCanBin(
true);
105 else if (prop.isNameMatch(
"GUIDER_BINNING"))
107 auto np = prop.getNumber();
108 if (np && np->getPermission() != IP_RO)
109 guideChip->setCanBin(
true);
111 else if (prop.isNameMatch(
"CCD_ABORT_EXPOSURE"))
113 auto sp = prop.getSwitch();
114 if (sp && sp->getPermission() != IP_RO)
115 primaryChip->setCanAbort(
true);
117 else if (prop.isNameMatch(
"GUIDER_ABORT_EXPOSURE"))
119 auto sp = prop.getSwitch();
120 if (sp && sp->getPermission() != IP_RO)
121 guideChip->setCanAbort(
true);
123 else if (prop.isNameMatch(
"CCD_TEMPERATURE"))
125 auto np = prop.getNumber();
127 CanCool = (np->getPermission() != IP_RO);
129 emit newTemperatureValue(np->at(0)->getValue());
131 else if (prop.isNameMatch(
"CCD_COOLER"))
134 HasCoolerControl =
true;
136 else if (prop.isNameMatch(
"CCD_VIDEO_STREAM"))
139 HasVideoStream =
true;
141 else if (prop.isNameMatch(
"CCD_CAPTURE_FORMAT"))
143 auto sp = prop.getSwitch();
146 m_CaptureFormats.clear();
147 for (
const auto &oneSwitch : *sp)
148 m_CaptureFormats << oneSwitch.getLabel();
150 m_CaptureFormatIndex = sp->findOnSwitchIndex();
153 else if (prop.isNameMatch(
"CCD_TRANSFER_FORMAT"))
155 auto sp = prop.getSwitch();
158 m_EncodingFormats.clear();
159 for (
const auto &oneSwitch : *sp)
160 m_EncodingFormats << oneSwitch.getLabel();
162 auto format = sp->findOnSwitch();
164 m_EncodingFormat = format->label;
167 else if (prop.isNameMatch(
"CCD_EXPOSURE_PRESETS"))
169 auto svp = prop.getSwitch();
174 for (
const auto &it : *svp)
181 if (parts.
count() == 2)
183 bool numOk =
false, denOk =
false;
184 double numerator = parts[0].toDouble(&numOk);
185 double denominator = parts[1].toDouble(&denOk);
186 if (numOk && denOk && denominator > 0)
189 value = numerator / denominator;
194 m_ExposurePresets.insert(key, value);
196 double min = 1e6, max = 1e-6;
197 for (
auto oneValue : m_ExposurePresets.values())
204 m_ExposurePresetsMinMax = qMakePair(min, max);
208 else if (prop.isNameMatch(
"CCD_FAST_TOGGLE"))
210 auto sp = prop.getSwitch();
212 m_FastExposureEnabled = sp->findOnSwitchIndex() == 0;
214 m_FastExposureEnabled =
false;
216 else if (prop.isNameMatch(
"TELESCOPE_TYPE"))
218 auto sp = prop.getSwitch();
221 auto format = sp->findWidgetByName(
"TELESCOPE_PRIMARY");
222 if (format && format->getState() == ISS_ON)
223 telescopeType = TELESCOPE_PRIMARY;
225 telescopeType = TELESCOPE_GUIDE;
228 else if (prop.isNameMatch(
"CCD_WEBSOCKET_SETTINGS"))
230 auto np = prop.getNumber();
231 m_Media->setURL(
QUrl(
QString(
"ws://%1:%2").arg(m_Parent->getClientManager()->getHost()).
arg(np->at(0)->getValue())));
232 m_Media->connectServer();
234 else if (prop.isNameMatch(
"CCD1"))
236 primaryCCDBLOB = prop;
239 else if ( (gainN ==
nullptr || offsetN ==
nullptr) && prop.getType() == INDI_NUMBER)
243 auto controlNP = prop.getNumber();
246 for (
auto &it : *controlNP)
251 if (name ==
"gain" || label ==
"gain")
254 gainPerm = controlNP->getPermission();
256 else if (name ==
"offset" || label ==
"offset")
259 offsetPerm = controlNP->getPermission();
265 ConcreteDevice::registerProperty(prop);
268void Camera::removeProperty(INDI::Property prop)
270 if (prop.isNameMatch(
"CCD_WEBSOCKET_SETTINGS"))
272 m_Media->disconnectServer();
276void Camera::processNumber(INDI::Property prop)
278 auto nvp = prop.getNumber();
279 if (nvp->isNameMatch(
"CCD_EXPOSURE"))
281 auto np = nvp->findWidgetByName(
"CCD_EXPOSURE_VALUE");
283 emit newExposureValue(primaryChip.get(), np->getValue(), nvp->getState());
284 if (nvp->getState() == IPS_ALERT)
285 emit
error(ERROR_CAPTURE);
287 else if (prop.isNameMatch(
"CCD_TEMPERATURE"))
290 auto np = nvp->findWidgetByName(
"CCD_TEMPERATURE_VALUE");
292 emit newTemperatureValue(np->getValue());
294 else if (prop.isNameMatch(
"GUIDER_EXPOSURE"))
296 auto np = nvp->findWidgetByName(
"GUIDER_EXPOSURE_VALUE");
298 emit newExposureValue(guideChip.get(), np->getValue(), nvp->getState());
300 else if (prop.isNameMatch(
"FPS"))
302 emit newFPS(nvp->at(0)->getValue(), nvp->at(1)->getValue());
304 else if (prop.isNameMatch(
"CCD_RAPID_GUIDE_DATA"))
306 if (nvp->getState() == IPS_ALERT)
308 emit newGuideStarData(primaryChip.get(), -1, -1, -1);
312 double dx = -1, dy = -1, fit = -1;
314 auto np = nvp->findWidgetByName(
"GUIDESTAR_X");
317 np = nvp->findWidgetByName(
"GUIDESTAR_Y");
320 np = nvp->findWidgetByName(
"GUIDESTAR_FIT");
322 fit = np->getValue();
324 if (dx >= 0 && dy >= 0 && fit >= 0)
325 emit newGuideStarData(primaryChip.get(), dx, dy, fit);
328 else if (prop.isNameMatch(
"GUIDER_RAPID_GUIDE_DATA"))
330 if (nvp->getState() == IPS_ALERT)
332 emit newGuideStarData(guideChip.get(), -1, -1, -1);
336 double dx = -1, dy = -1, fit = -1;
337 auto np = nvp->findWidgetByName(
"GUIDESTAR_X");
340 np = nvp->findWidgetByName(
"GUIDESTAR_Y");
343 np = nvp->findWidgetByName(
"GUIDESTAR_FIT");
345 fit = np->getValue();
347 if (dx >= 0 && dy >= 0 && fit >= 0)
348 emit newGuideStarData(guideChip.get(), dx, dy, fit);
353void Camera::processSwitch(INDI::Property prop)
355 auto svp = prop.getSwitch();
357 if (svp->isNameMatch(
"CCD_COOLER"))
360 HasCoolerControl =
true;
361 emit coolerToggled(svp->sp[0].s == ISS_ON);
366 if (isBLOBEnabled() ==
false || m_StreamingEnabled ==
false)
369 HasVideoStream =
true;
371 if (!streamWindow && svp->sp[0].s == ISS_ON)
373 streamWindow.reset(
new StreamWG(
this));
375 INumberVectorProperty *streamFrame = getNumber(
"CCD_STREAM_FRAME");
376 INumber *w =
nullptr, *h =
nullptr;
380 w = IUFindNumber(streamFrame,
"WIDTH");
381 h = IUFindNumber(streamFrame,
"HEIGHT");
392 auto rawBP = getBLOB(
"CCD1");
395 int x = 0, y = 0, w = 0, h = 0;
396 int binx = 0, biny = 0;
398 primaryChip->getFrame(&x, &y, &w, &h);
399 primaryChip->getBinning(&binx, &biny);
405 streamWindow->setSize(streamW, streamH);
413 streamWindow->enableStream(svp->sp[0].s == ISS_ON);
414 emit videoStreamToggled(svp->sp[0].s == ISS_ON);
417 else if (svp->isNameMatch(
"CCD_CAPTURE_FORMAT"))
419 m_CaptureFormats.clear();
420 for (
int i = 0; i < svp->nsp; i++)
422 m_CaptureFormats << svp->sp[i].label;
423 if (svp->sp[i].s == ISS_ON)
424 m_CaptureFormatIndex = i;
427 else if (svp->isNameMatch(
"CCD_TRANSFER_FORMAT"))
429 ISwitch *format = IUFindOnSwitch(svp);
431 m_EncodingFormat = format->label;
433 else if (svp->isNameMatch(
"RECORD_STREAM"))
435 ISwitch *recordOFF = IUFindSwitch(svp,
"RECORD_OFF");
437 if (recordOFF && recordOFF->s == ISS_ON)
439 emit videoRecordToggled(
false);
440 KSNotification::event(
QLatin1String(
"IndiServerMessage"),
i18n(
"Video Recording Stopped"), KSNotification::INDI);
444 emit videoRecordToggled(
true);
445 KSNotification::event(
QLatin1String(
"IndiServerMessage"),
i18n(
"Video Recording Started"), KSNotification::INDI);
448 else if (svp->isNameMatch(
"TELESCOPE_TYPE"))
450 ISwitch *format = IUFindSwitch(svp,
"TELESCOPE_PRIMARY");
451 if (format && format->s == ISS_ON)
452 telescopeType = TELESCOPE_PRIMARY;
454 telescopeType = TELESCOPE_GUIDE;
456 else if (!strcmp(svp->name,
"CCD_FAST_TOGGLE"))
458 m_FastExposureEnabled = IUFindOnSwitchIndex(svp) == 0;
460 else if (svp->isNameMatch(
"CONNECTION"))
462 auto dSwitch = svp->findWidgetByName(
"DISCONNECT");
464 if (dSwitch && dSwitch->getState() == ISS_ON)
468 streamWindow->enableStream(
false);
469 emit videoStreamToggled(
false);
470 streamWindow->close();
471 streamWindow.reset();
477 primaryCCDBLOB = INDI::Property();
482void Camera::processText(INDI::Property prop)
484 auto tvp = prop.getText();
485 if (tvp->isNameMatch(
"CCD_FILE_PATH"))
487 auto filepath = tvp->findWidgetByName(
"FILE_PATH");
489 emit newRemoteFile(
QString(filepath->getText()));
498 auto bvp = primaryCCDBLOB.getBLOB();
499 auto bp = bvp->at(0);
501 bp->setBlob(
const_cast<char *
>(message.
data()));
502 bp->setSize(message.
size());
504 processBLOB(primaryCCDBLOB);
507 bp->setBlob(
nullptr);
510void Camera::processStream(INDI::Property prop)
512 if (!streamWindow || streamWindow->isStreamEnabled() ==
false)
515 INumberVectorProperty *streamFrame = getNumber(
"CCD_STREAM_FRAME");
516 INumber *w =
nullptr, *h =
nullptr;
520 w = IUFindNumber(streamFrame,
"WIDTH");
521 h = IUFindNumber(streamFrame,
"HEIGHT");
531 int x = 0, y = 0, w = 0, h = 0;
532 int binx = 1, biny = 1;
534 primaryChip->getFrame(&x, &y, &w, &h);
535 primaryChip->getBinning(&binx, &biny);
540 streamWindow->setSize(streamW, streamH);
542 streamWindow->show();
543 streamWindow->newFrame(prop);
546void ISD::Camera::updateFileBuffer(INDI::Property prop,
bool is_fits)
561 auto bp = prop.getBLOB()->at(0);
563 if (fileWriteBufferSize != bp->getBlobLen())
565 if (fileWriteBuffer !=
nullptr)
566 delete [] fileWriteBuffer;
567 fileWriteBufferSize = bp->getBlobLen();
568 fileWriteBuffer =
new char[fileWriteBufferSize];
573 memcpy(fileWriteBuffer, bp->getBlob(), bp->getBlobLen());
580 if (BType == BLOB_FITS)
590#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
591 fileWriteThread =
QtConcurrent::run(&ISD::Camera::WriteImageFileInternal,
this, filename, fileWriteBuffer,
592 fileWriteBufferSize);
594 fileWriteThread =
QtConcurrent::run(
this, &ISD::Camera::WriteImageFileInternal, filename, fileWriteBuffer,
595 fileWriteBufferSize);
598 else if (!WriteImageFileInternal(filename,
static_cast<char*
>(fileWriteBuffer), fileWriteBufferSize))
604bool Camera::processBLOB(INDI::Property prop)
606 auto bvp = prop.getBLOB();
608 if (bvp->getPermission() == IP_WO || bvp->at(0)->getSize() == 0)
613 auto bp = bvp->at(0);
618 if (format.contains(
"stream"))
620 if (m_StreamingEnabled ==
false)
622 else if (streamWindow)
633 else if (format.contains(
"fits"))
635 else if (format.contains(
"xisf"))
637 else if (RAWFormats.
contains(shortFormat))
640 if (BType == BLOB_OTHER)
643 CameraChip *targetChip =
nullptr;
645 if (bvp->isNameMatch(
"CCD2"))
646 targetChip = guideChip.get();
649 targetChip = primaryChip.get();
650 qCDebug(KSTARS_INDI) <<
"Image received. Mode:" << getFITSModeStringString(targetChip->getCaptureMode()) <<
"Size:" <<
658 updateFileBuffer(prop, BType == BLOB_FITS);
670 imageData->setExtension(shortFormat);
671 if (!imageData->loadFromBuffer(buffer))
678 imageData->setProperty(
"device", getDeviceName());
679 imageData->setProperty(
"blobVector", prop.getName());
680 imageData->setProperty(
"blobElement", bp->getName());
681 imageData->setProperty(
"chip", targetChip->getType());
684 targetChip->setImageData(imageData);
685 emit propertyUpdated(prop);
691void Camera::StreamWindowHidden()
696 auto streamSP =
getSwitch(
"CCD_VIDEO_STREAM");
700 streamSP->at(0)->setState(ISS_OFF);
701 streamSP->at(1)->setState(ISS_ON);
702 streamSP->setState(IPS_IDLE);
710 streamSP->at(0)->setState(ISS_OFF);
711 streamSP->at(1)->setState(ISS_ON);
712 streamSP->setState(IPS_IDLE);
716 streamSP =
getSwitch(
"AUX_VIDEO_STREAM");
720 streamSP->at(0)->setState(ISS_OFF);
721 streamSP->at(1)->setState(ISS_ON);
722 streamSP->setState(IPS_IDLE);
728 streamWindow->disconnect();
731bool Camera::hasGuideHead()
736bool Camera::hasCooler()
741bool Camera::hasCoolerControl()
743 return HasCoolerControl;
746bool Camera::setCoolerControl(
bool enable)
748 if (HasCoolerControl ==
false)
757 auto coolerON = coolerSP->findWidgetByName(
"COOLER_ON");
758 auto coolerOFF = coolerSP->findWidgetByName(
"COOLER_OFF");
759 if (!coolerON || !coolerOFF)
762 coolerON->setState(enable ? ISS_ON : ISS_OFF);
763 coolerOFF->setState(enable ? ISS_OFF : ISS_ON);
769CameraChip *Camera::getChip(CameraChip::ChipType cType)
773 case CameraChip::PRIMARY_CCD:
774 return primaryChip.get();
776 case CameraChip::GUIDE_CCD:
777 return guideChip.get();
783bool Camera::setRapidGuide(CameraChip *targetChip,
bool enable)
785 ISwitchVectorProperty *rapidSP =
nullptr;
786 ISwitch *enableS =
nullptr;
788 if (targetChip == primaryChip.get())
791 rapidSP =
getSwitch(
"GUIDER_RAPID_GUIDE");
793 if (rapidSP ==
nullptr)
796 enableS = IUFindSwitch(rapidSP,
"ENABLE");
798 if (enableS ==
nullptr)
802 if ((enable && enableS->s == ISS_ON) || (!enable && enableS->s == ISS_OFF))
805 IUResetSwitch(rapidSP);
806 rapidSP->sp[0].s = enable ? ISS_ON : ISS_OFF;
807 rapidSP->sp[1].s = enable ? ISS_OFF : ISS_ON;
814bool Camera::configureRapidGuide(CameraChip *targetChip,
bool autoLoop,
bool sendImage,
bool showMarker)
816 ISwitchVectorProperty *rapidSP =
nullptr;
817 ISwitch *autoLoopS =
nullptr, *sendImageS =
nullptr, *showMarkerS =
nullptr;
819 if (targetChip == primaryChip.get())
820 rapidSP =
getSwitch(
"CCD_RAPID_GUIDE_SETUP");
822 rapidSP =
getSwitch(
"GUIDER_RAPID_GUIDE_SETUP");
824 if (rapidSP ==
nullptr)
827 autoLoopS = IUFindSwitch(rapidSP,
"AUTO_LOOP");
828 sendImageS = IUFindSwitch(rapidSP,
"SEND_IMAGE");
829 showMarkerS = IUFindSwitch(rapidSP,
"SHOW_MARKER");
831 if (!autoLoopS || !sendImageS || !showMarkerS)
835 if (((autoLoop && autoLoopS->s == ISS_ON) || (!autoLoop && autoLoopS->s == ISS_OFF)) &&
836 ((sendImage && sendImageS->s == ISS_ON) || (!sendImage && sendImageS->s == ISS_OFF)) &&
837 ((showMarker && showMarkerS->s == ISS_ON) || (!showMarker && showMarkerS->s == ISS_OFF)))
840 autoLoopS->s = autoLoop ? ISS_ON : ISS_OFF;
841 sendImageS->s = sendImage ? ISS_ON : ISS_OFF;
842 showMarkerS->s = showMarker ? ISS_ON : ISS_OFF;
849void Camera::updateUploadSettings(
const QString &uploadDirectory,
const QString &uploadFile)
851 ITextVectorProperty *uploadSettingsTP =
nullptr;
852 IText *uploadT =
nullptr;
854 uploadSettingsTP =
getText(
"UPLOAD_SETTINGS");
855 if (uploadSettingsTP)
857 uploadT = IUFindText(uploadSettingsTP,
"UPLOAD_DIR");
858 if (uploadT && uploadDirectory.
isEmpty() ==
false)
860 auto posixDirectory = uploadDirectory;
863 IUSaveText(uploadT, posixDirectory.toLatin1().constData());
866 uploadT = IUFindText(uploadSettingsTP,
"UPLOAD_PREFIX");
874Camera::UploadMode Camera::getUploadMode()
876 ISwitchVectorProperty *uploadModeSP =
nullptr;
880 if (uploadModeSP ==
nullptr)
882 qWarning() <<
"No UPLOAD_MODE in CCD driver. Please update driver to INDI compliant CCD driver.";
883 return UPLOAD_CLIENT;
888 ISwitch *modeS =
nullptr;
890 modeS = IUFindSwitch(uploadModeSP,
"UPLOAD_CLIENT");
891 if (modeS && modeS->s == ISS_ON)
892 return UPLOAD_CLIENT;
893 modeS = IUFindSwitch(uploadModeSP,
"UPLOAD_LOCAL");
894 if (modeS && modeS->s == ISS_ON)
896 modeS = IUFindSwitch(uploadModeSP,
"UPLOAD_BOTH");
897 if (modeS && modeS->s == ISS_ON)
902 return UPLOAD_CLIENT;
905bool Camera::setUploadMode(UploadMode mode)
907 ISwitch *modeS =
nullptr;
909 auto uploadModeSP =
getSwitch(
"UPLOAD_MODE");
913 qWarning() <<
"No UPLOAD_MODE in CCD driver. Please update driver to INDI compliant CCD driver.";
920 modeS = uploadModeSP->findWidgetByName(
"UPLOAD_CLIENT");
923 if (modeS->s == ISS_ON)
928 modeS = uploadModeSP->findWidgetByName(
"UPLOAD_BOTH");
931 if (modeS->s == ISS_ON)
936 modeS = uploadModeSP->findWidgetByName(
"UPLOAD_LOCAL");
939 if (modeS->s == ISS_ON)
944 uploadModeSP->reset();
952bool Camera::getTemperature(
double *value)
954 if (HasCooler ==
false)
957 auto temperatureNP = getNumber(
"CCD_TEMPERATURE");
962 *value = temperatureNP->at(0)->getValue();
967bool Camera::setTemperature(
double value)
969 auto nvp = getNumber(
"CCD_TEMPERATURE");
974 auto np = nvp->findWidgetByName(
"CCD_TEMPERATURE_VALUE");
986bool Camera::setEncodingFormat(
const QString &value)
988 if (value.
isEmpty() || value == m_EncodingFormat)
991 auto svp =
getSwitch(
"CCD_TRANSFER_FORMAT");
997 for (
int i = 0; i < svp->nsp; i++)
999 if (svp->at(i)->getLabel() == value)
1001 svp->at(i)->setState(ISS_ON);
1006 m_EncodingFormat = value;
1011bool Camera::setTelescopeType(TelescopeType type)
1013 if (type == telescopeType)
1021 auto typePrimary = svp->findWidgetByName(
"TELESCOPE_PRIMARY");
1022 auto typeGuide = svp->findWidgetByName(
"TELESCOPE_GUIDE");
1024 if (!typePrimary || !typeGuide)
1027 telescopeType =
type;
1029 if ( (telescopeType == TELESCOPE_PRIMARY && typePrimary->getState() == ISS_OFF) ||
1030 (telescopeType == TELESCOPE_GUIDE && typeGuide->getState() == ISS_OFF))
1032 typePrimary->setState(telescopeType == TELESCOPE_PRIMARY ? ISS_ON : ISS_OFF);
1033 typeGuide->setState(telescopeType == TELESCOPE_PRIMARY ? ISS_OFF : ISS_ON);
1035 setConfig(SAVE_CONFIG);
1041bool Camera::setVideoStreamEnabled(
bool enable)
1043 if (HasVideoStream ==
false)
1046 auto svp =
getSwitch(
"CCD_VIDEO_STREAM");
1052 if ((enable && svp->at(0)->getState() == ISS_ON) || (!enable && svp->at(1)->getState() == ISS_ON))
1055 svp->at(0)->setState(enable ? ISS_ON : ISS_OFF);
1056 svp->at(1)->setState(enable ? ISS_OFF : ISS_ON);
1063bool Camera::resetStreamingFrame()
1065 auto frameProp = getNumber(
"CCD_STREAM_FRAME");
1070 auto xarg = frameProp->findWidgetByName(
"X");
1071 auto yarg = frameProp->findWidgetByName(
"Y");
1072 auto warg = frameProp->findWidgetByName(
"WIDTH");
1073 auto harg = frameProp->findWidgetByName(
"HEIGHT");
1075 if (xarg && yarg && warg && harg)
1077 if (!std::fabs(xarg->getValue() - xarg->getMin()) &&
1078 !std::fabs(yarg->getValue() - yarg->getMin()) &&
1079 !std::fabs(warg->getValue() - warg->getMax()) &&
1080 !std::fabs(harg->getValue() - harg->getMax()))
1083 xarg->setValue(xarg->getMin());
1084 yarg->setValue(yarg->getMin());
1085 warg->setValue(warg->getMax());
1086 harg->setValue(harg->getMax());
1095bool Camera::setStreamLimits(uint16_t maxBufferSize, uint16_t maxPreviewFPS)
1097 auto limitsProp = getNumber(
"LIMITS");
1102 auto bufferMax = limitsProp->findWidgetByName(
"LIMITS_BUFFER_MAX");
1103 auto previewFPS = limitsProp->findWidgetByName(
"LIMITS_PREVIEW_FPS");
1105 if (bufferMax && previewFPS)
1107 if(std::fabs(bufferMax->getValue() - maxBufferSize) > 0 || std::fabs(previewFPS->getValue() - maxPreviewFPS) > 0)
1109 bufferMax->setValue(maxBufferSize);
1110 previewFPS->setValue(maxPreviewFPS);
1120bool Camera::setStreamingFrame(
int x,
int y,
int w,
int h)
1122 auto frameProp = getNumber(
"CCD_STREAM_FRAME");
1127 auto xarg = frameProp->findWidgetByName(
"X");
1128 auto yarg = frameProp->findWidgetByName(
"Y");
1129 auto warg = frameProp->findWidgetByName(
"WIDTH");
1130 auto harg = frameProp->findWidgetByName(
"HEIGHT");
1132 if (xarg && yarg && warg && harg)
1134 if (!std::fabs(xarg->getValue() - x) &&
1135 !std::fabs(yarg->getValue() - y) &&
1136 !std::fabs(warg->getValue() - w) &&
1137 !std::fabs(harg->getValue() - h))
1141 xarg->value = qBound(xarg->getMin(),
static_cast<double>(x) + xarg->getValue(), xarg->getMax());
1142 yarg->value = qBound(yarg->getMin(),
static_cast<double>(y) + yarg->getValue(), yarg->getMax());
1143 warg->value = qBound(warg->getMin(),
static_cast<double>(w), warg->getMax());
1144 harg->value = qBound(harg->getMin(),
static_cast<double>(h), harg->getMax());
1153bool Camera::isStreamingEnabled()
1155 if (HasVideoStream ==
false || !streamWindow)
1158 return streamWindow->isStreamEnabled();
1161bool Camera::setSERNameDirectory(
const QString &filename,
const QString &directory)
1163 auto tvp =
getText(
"RECORD_FILE");
1168 auto filenameT = tvp->findWidgetByName(
"RECORD_FILE_NAME");
1169 auto dirT = tvp->findWidgetByName(
"RECORD_FILE_DIR");
1171 if (!filenameT || !dirT)
1182bool Camera::getSERNameDirectory(
QString &filename,
QString &directory)
1184 auto tvp =
getText(
"RECORD_FILE");
1189 auto filenameT = tvp->findWidgetByName(
"RECORD_FILE_NAME");
1190 auto dirT = tvp->findWidgetByName(
"RECORD_FILE_DIR");
1192 if (!filenameT || !dirT)
1195 filename =
QString(filenameT->getText());
1196 directory =
QString(dirT->getText());
1201bool Camera::startRecording()
1208 auto recordON = svp->findWidgetByName(
"RECORD_ON");
1213 if (recordON->getState() == ISS_ON)
1217 recordON->setState(ISS_ON);
1224bool Camera::startDurationRecording(
double duration)
1226 auto nvp = getNumber(
"RECORD_OPTIONS");
1231 auto durationN = nvp->findWidgetByName(
"RECORD_DURATION");
1241 auto recordON = svp->findWidgetByName(
"RECORD_DURATION_ON");
1246 if (recordON->getState() == ISS_ON)
1249 durationN->setValue(duration);
1253 recordON->setState(ISS_ON);
1260bool Camera::startFramesRecording(uint32_t frames)
1262 auto nvp = getNumber(
"RECORD_OPTIONS");
1267 auto frameN = nvp->findWidgetByName(
"RECORD_FRAME_TOTAL");
1270 if (!frameN || !svp)
1273 auto recordON = svp->findWidgetByName(
"RECORD_FRAME_ON");
1278 if (recordON->getState() == ISS_ON)
1281 frameN->setValue(frames);
1285 recordON->setState(ISS_ON);
1292bool Camera::stopRecording()
1299 auto recordOFF = svp->findWidgetByName(
"RECORD_OFF");
1305 if (recordOFF->getState() == ISS_ON)
1309 recordOFF->setState(ISS_ON);
1318 auto tvp =
getText(
"FITS_HEADER");
1321 if (!tvp || tvp->count() < 3)
1324 for (
auto &record : values)
1326 tvp->at(0)->setText(record.key.toLatin1().constData());
1327 tvp->at(1)->setText(record.value.toString().toLatin1().constData());
1328 tvp->at(2)->setText(record.comment.toLatin1().constData());
1336bool Camera::setGain(
double value)
1341 gainN->value = value;
1346bool Camera::getGain(
double *value)
1351 *value = gainN->value;
1356bool Camera::getGainMinMaxStep(
double *min,
double *max,
double *step)
1363 *step = gainN->step;
1368bool Camera::setOffset(
double value)
1373 offsetN->value = value;
1378bool Camera::getOffset(
double *value)
1383 *value = offsetN->value;
1388bool Camera::getOffsetMinMaxStep(
double *min,
double *max,
double *step)
1393 *min = offsetN->min;
1394 *max = offsetN->max;
1395 *step = offsetN->step;
1400bool Camera::isBLOBEnabled()
1402 return (m_Parent->getClientManager()->isBLOBEnabled(getDeviceName(),
"CCD1"));
1405bool Camera::setBLOBEnabled(
bool enable,
const QString &prop)
1407 m_Parent->getClientManager()->setBLOBEnabled(enable, getDeviceName(), prop);
1412bool Camera::setFastExposureEnabled(
bool enable)
1415 m_FastExposureEnabled = enable;
1417 auto svp =
getSwitch(
"CCD_FAST_TOGGLE");
1422 svp->at(0)->setState(enable ? ISS_ON : ISS_OFF);
1423 svp->at(1)->setState(enable ? ISS_OFF : ISS_ON);
1429bool Camera::setCaptureFormat(
const QString &format)
1431 auto svp =
getSwitch(
"CCD_CAPTURE_FORMAT");
1435 for (
auto &oneSwitch : *svp)
1436 oneSwitch.setState(oneSwitch.label == format ? ISS_ON : ISS_OFF);
1442bool Camera::setFastCount(uint32_t count)
1444 auto nvp = getNumber(
"CCD_FAST_COUNT");
1449 nvp->at(0)->setValue(count);
1456bool Camera::setStreamExposure(
double duration)
1458 auto nvp = getNumber(
"STREAMING_EXPOSURE");
1463 nvp->at(0)->setValue(duration);
1470bool Camera::getStreamExposure(
double *duration)
1472 auto nvp = getNumber(
"STREAMING_EXPOSURE");
1477 *duration = nvp->at(0)->getValue();
1482bool Camera::isCoolerOn()
1489 return (svp->at(0)->getState() == ISS_ON);
1492bool Camera::getTemperatureRegulation(
double &ramp,
double &threshold)
1494 auto regulation = getProperty(
"CCD_TEMP_RAMP");
1495 if (!regulation.isValid())
1498 ramp = regulation.getNumber()->at(0)->getValue();
1499 threshold = regulation.getNumber()->at(1)->getValue();
1503bool Camera::setTemperatureRegulation(
double ramp,
double threshold)
1505 auto regulation = getProperty(
"CCD_TEMP_RAMP");
1506 if (!regulation.isValid())
1509 regulation.getNumber()->at(0)->setValue(ramp);
1510 regulation.getNumber()->at(1)->setValue(threshold);
1515bool Camera::setScopeInfo(
double focalLength,
double aperture)
1517 auto scopeInfo = getProperty(
"SCOPE_INFO");
1518 if (!scopeInfo.isValid())
1521 auto nvp = scopeInfo.getNumber();
1522 nvp->at(0)->setValue(focalLength);
1523 nvp->at(1)->setValue(aperture);
1529bool Camera::WriteImageFileInternal(
const QString &filename,
char *buffer,
const size_t size)
1531 QFile file(filename);
1534 qCCritical(KSTARS_INDI) <<
"ISD:CCD Error: Unable to open write file: " <<
1541 for (
size_t nr = 0; nr < size; nr += n)
1543 n = out.writeRawData(buffer + nr, size - nr);
1550 ok = file.flush() &&
ok;
1559QString Camera::getCaptureFormat()
const
1561 if (m_CaptureFormatIndex < 0 || m_CaptureFormats.
isEmpty() || m_CaptureFormatIndex >= m_CaptureFormats.
size())
1564 return m_CaptureFormats[m_CaptureFormatIndex];
@ ERROR_LOAD
Saving to disk error.
bool saveCurrentImage(QString &filename)
saveCurrentImage save the image that is currently in the image data buffer
void sendNewProperty(INDI::Property prop)
Send new property command to server.
INDI::PropertyView< IText > * getText(const QString &name) const
INDI::PropertyView< ISwitch > * getSwitch(const QString &name) const
static KNotification * event(const QString &eventId, const QString &text=QString(), const QPixmap &pixmap=QPixmap(), const NotificationFlags &flags=CloseOnTimeout, const QString &componentName=QString())
QString i18n(const char *text, const TYPE &arg...)
ISD is a collection of INDI Standard Devices.
QString name(GameStandardAction id)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
QString label(StandardShortcut id)
const char * constData() const const
QByteArray fromRawData(const char *data, qsizetype size)
qsizetype size() const const
QDateTime currentDateTime()
bool isRunning() const const
qsizetype count() const const
bool isEmpty() const const
qsizetype size() const const
QString arg(Args &&... args) const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString mid(qsizetype position, qsizetype n) const const
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
double toDouble(bool *ok) const const
QByteArray toLatin1() const const
QString toLower() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QFuture< T > run(Function function,...)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)