Kstars

sequencequeue.cpp
1/*
2 SPDX-FileCopyrightText: 2012 Jasem Mutlaq <mutlaqja@ikarustech.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "sequencequeue.h"
8
9#include <knotification.h>
10#include <ekos_capture_debug.h>
11
12#include "camerastate.h"
13#include "capturedeviceadaptor.h"
14#include "ksnotification.h"
15#include "sequencejob.h"
16
17// Current Sequence File Format:
18constexpr double SQ_FORMAT_VERSION = 2.6;
19// We accept file formats with version back to:
20constexpr double SQ_COMPAT_VERSION = 2.0;
21
22namespace Ekos
23{
24
25bool SequenceQueue::load(const QString &fileURL, const QString &targetName,
28{
29 QFile sFile(fileURL);
30 if (!sFile.open(QIODevice::ReadOnly))
31 {
32 QString message = i18n("Unable to open file %1", fileURL);
33 KSNotification::sorry(message, i18n("Could Not Open File"));
34 return false;
35 }
36
37 LilXML * xmlParser = newLilXML();
38
39 char errmsg[MAXRBUF];
40 XMLEle * root = nullptr;
41 XMLEle * ep = nullptr;
42 char c;
43
44 // We expect all data read from the XML to be in the C locale - QLocale::c().
45 QLocale cLocale = QLocale::c();
46
47 while (sFile.getChar(&c))
48 {
49 root = readXMLEle(xmlParser, c, errmsg);
50
51 if (root)
52 {
53 double sqVersion = cLocale.toDouble(findXMLAttValu(root, "version"));
54 if (sqVersion < SQ_COMPAT_VERSION)
55 {
56 emit newLog(i18n("Deprecated sequence file format version %1. Please construct a new sequence file.",
57 sqVersion));
58 return false;
59 }
60
61 for (ep = nextXMLEle(root, 1); ep != nullptr; ep = nextXMLEle(root, 0))
62 {
63 if (!strcmp(tagXMLEle(ep), "Observer"))
64 {
65 state->setObserverName(QString(pcdataXMLEle(ep)));
66 }
67 else if (!strcmp(tagXMLEle(ep), "GuideDeviation"))
68 {
69 m_GuideDeviationSet = true;
70 m_EnforceGuideDeviation = !strcmp(findXMLAttValu(ep, "enabled"), "true");
71 m_GuideDeviation = cLocale.toDouble(pcdataXMLEle(ep));
72 }
73 else if (!strcmp(tagXMLEle(ep), "CCD"))
74 {
75 // Old field in some files. Without this empty test, it would fall through to the else condition and create a job.
76 }
77 else if (!strcmp(tagXMLEle(ep), "FilterWheel"))
78 {
79 // Old field in some files. Without this empty test, it would fall through to the else condition and create a job.
80 }
81 else if (!strcmp(tagXMLEle(ep), "GuideStartDeviation"))
82 {
83 m_GuideStartDeviationSet = true;
84 m_EnforceStartGuiderDrift = !strcmp(findXMLAttValu(ep, "enabled"), "true");
85 m_StartGuideDeviation = cLocale.toDouble(pcdataXMLEle(ep));
86 }
87 else if (!strcmp(tagXMLEle(ep), "Autofocus"))
88 {
89 // Old field in some files. Without this empty test, it would fall through to the else condition and create a job.
90 }
91 else if (!strcmp(tagXMLEle(ep), "HFRCheck"))
92 {
93 m_AutofocusSet = true;
94 m_EnforceAutofocusHFR = !strcmp(findXMLAttValu(ep, "enabled"), "true");
95
96 XMLEle *epHFR;
97 //Set default values in case of malformed XML
98 m_HFRDeviation = 0.0;
99 m_HFRCheckAlgorithm = HFR_CHECK_LAST_AUTOFOCUS;
100 m_HFRCheckThresholdPercentage = HFR_CHECK_DEFAULT_THRESHOLD;
101 m_HFRCheckFrames = 1;
102
103 for (epHFR = nextXMLEle(ep, 1); epHFR != nullptr; epHFR = nextXMLEle(ep, 0))
104 {
105 if (!strcmp(tagXMLEle(epHFR), "HFRDeviation"))
106 {
107 double const HFRValue = cLocale.toDouble(pcdataXMLEle(epHFR));
108 // Set the HFR value from XML, or reset it to zero, don't let another unrelated older HFR be used
109 if (HFRValue >= 0.0)
110 m_HFRDeviation = HFRValue;
111 }
112
113 if (!strcmp(tagXMLEle(epHFR), "HFRCheckAlgorithm"))
114 {
115 int HFRCheckAlgo = cLocale.toInt(pcdataXMLEle(epHFR));
116 // Set the HFR Check Algo from XML, or reset it to Last Autofocus
117 if (HFRCheckAlgo >= 0 && HFRCheckAlgo < HFR_CHECK_MAX_ALGO)
118 m_HFRCheckAlgorithm = static_cast<HFRCheckAlgorithm>(HFRCheckAlgo);
119 }
120 else if (!strcmp(tagXMLEle(epHFR), "HFRCheckThreshold"))
121 {
122 double const hFRCheckThreshold = cLocale.toDouble(pcdataXMLEle(epHFR));
123 // Set the HFR Threshold Percentage from XML, or reset it to 10%, don't let another unrelated older value be used
124 if (hFRCheckThreshold >= 0.0)
125 m_HFRCheckThresholdPercentage = hFRCheckThreshold;
126 }
127 else if (!strcmp(tagXMLEle(epHFR), "HFRCheckFrames"))
128 {
129 int const hFRCheckFrames = cLocale.toInt(pcdataXMLEle(epHFR));
130 // Set the HFR Frames from XML, or reset it to 1, don't let another unrelated older value be used
131 if (hFRCheckFrames > 1)
132 m_HFRCheckFrames = hFRCheckFrames;
133 }
134 }
135 }
136 else if (!strcmp(tagXMLEle(ep), "RefocusOnTemperatureDelta"))
137 {
138 m_RefocusOnTemperatureDeltaSet = true;
139 m_EnforceAutofocusOnTemperature = !strcmp(findXMLAttValu(ep, "enabled"), "true");
140 double const deltaValue = cLocale.toDouble(pcdataXMLEle(ep));
141 m_MaxFocusTemperatureDelta = deltaValue;
142 }
143 else if (!strcmp(tagXMLEle(ep), "RefocusEveryN"))
144 {
145 m_RefocusEveryNSet = true;
146 m_EnforceRefocusEveryN = !strcmp(findXMLAttValu(ep, "enabled"), "true");
147 int const minutesValue = cLocale.toInt(pcdataXMLEle(ep));
148 // Set the refocus period from XML, or reset it to zero, don't let another unrelated older refocus period be used.
149 m_RefocusEveryN = minutesValue > 0 ? minutesValue : 0;
150 }
151 else if (!strcmp(tagXMLEle(ep), "RefocusOnMeridianFlip"))
152 {
153 m_RefocusOnMeridianFlipSet = true;
154 m_RefocusAfterMeridianFlip = !strcmp(findXMLAttValu(ep, "enabled"), "true");
155 }
156 else if (!strcmp(tagXMLEle(ep), "MeridianFlip"))
157 {
158 // meridian flip is managed by the mount only
159 // older files might nevertheless contain MF settings
160 if (! strcmp(findXMLAttValu(ep, "enabled"), "true"))
161 emit newLog(
162 i18n("Meridian flip configuration has been shifted to the mount module. Please configure the meridian flip there."));
163 }
164 else
165 {
166 auto job = new SequenceJob(devices, state, SequenceJob::JOBTYPE_BATCH, ep, targetName);
167 m_allJobs.append(job);
168 }
169 }
170 delXMLEle(root);
171 }
172 else if (errmsg[0])
173 {
174 emit newLog(QString(errmsg));
175 delLilXML(xmlParser);
176 return false;
177 }
178 }
179
180 state->setSequenceURL(QUrl::fromLocalFile(fileURL));
181 state->setDirty(false);
182 delLilXML(xmlParser);
183 return true;
184}
185
186void SequenceQueue::setOptions()
187{
188 if (m_GuideDeviationSet)
189 {
190 Options::setEnforceGuideDeviation(m_EnforceGuideDeviation);
191 Options::setGuideDeviation(m_GuideDeviation);
192 }
193 if (m_GuideStartDeviationSet)
194 {
195 Options::setEnforceStartGuiderDrift(m_EnforceStartGuiderDrift);
196 Options::setStartGuideDeviation(m_StartGuideDeviation);
197 }
198 if (m_AutofocusSet)
199 {
200 Options::setEnforceAutofocusHFR(m_EnforceAutofocusHFR);
201 Options::setHFRCheckAlgorithm(m_HFRCheckAlgorithm);
202 Options::setHFRThresholdPercentage(m_HFRCheckThresholdPercentage);
203 Options::setInSequenceCheckFrames(m_HFRCheckFrames);
204 Options::setHFRDeviation(m_HFRDeviation);
205 }
206 if (m_RefocusOnTemperatureDeltaSet)
207 {
208 Options::setEnforceAutofocusOnTemperature(m_EnforceAutofocusOnTemperature);
209 Options::setMaxFocusTemperatureDelta(m_MaxFocusTemperatureDelta);
210 }
211 if (m_RefocusEveryNSet)
212 {
213 Options::setEnforceRefocusEveryN(m_EnforceRefocusEveryN);
214 Options::setRefocusEveryN(m_RefocusEveryN);
215 }
216 if (m_RefocusOnMeridianFlipSet)
217 {
218 Options::setRefocusAfterMeridianFlip(m_RefocusAfterMeridianFlip);
219 }
220}
221
222void SequenceQueue::loadOptions()
223{
224 m_GuideDeviationSet = true;
225
226 m_EnforceGuideDeviation = Options::enforceGuideDeviation();
227 m_GuideDeviation = Options::guideDeviation();
228
229 m_GuideStartDeviationSet = true;
230 m_EnforceStartGuiderDrift = Options::enforceStartGuiderDrift();
231 m_StartGuideDeviation = Options::startGuideDeviation();
232
233 m_AutofocusSet = true;
234 m_EnforceAutofocusHFR = Options::enforceAutofocusHFR();
235 m_HFRCheckAlgorithm = static_cast<HFRCheckAlgorithm>(Options::hFRCheckAlgorithm());
236 m_HFRCheckThresholdPercentage = Options::hFRThresholdPercentage();
237 m_HFRCheckFrames = Options::inSequenceCheckFrames();
238 m_HFRDeviation = Options::hFRDeviation();
239
240 m_RefocusOnTemperatureDeltaSet = true;
241 m_EnforceAutofocusOnTemperature = Options::enforceAutofocusOnTemperature();
242 m_MaxFocusTemperatureDelta = Options::maxFocusTemperatureDelta();
243
244 m_RefocusEveryNSet = true;
245 m_EnforceRefocusEveryN = Options::enforceRefocusEveryN();
246 m_RefocusEveryN = Options::refocusEveryN();
247
248 m_RefocusOnMeridianFlipSet = true;
249 m_RefocusAfterMeridianFlip = Options::refocusAfterMeridianFlip();
250}
251
252bool SequenceQueue::save(const QString &path, const QString &observerName)
253{
254 QFile file;
255 file.setFileName(path);
256
257 if (!file.open(QIODevice::WriteOnly))
258 {
259 QString message = i18n("Unable to write to file %1", path);
260 KSNotification::sorry(message, i18n("Could not open file"));
261 return false;
262 }
263
264 QTextStream outstream(&file);
265
266 // We serialize sequence data to XML using the C locale
267 QLocale cLocale = QLocale::c();
268
269 outstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << Qt::endl;
270 outstream << "<SequenceQueue version='" << SQ_FORMAT_VERSION << "'>" << Qt::endl;
271 if (observerName.isEmpty() == false)
272 outstream << "<Observer>" << observerName << "</Observer>" << Qt::endl;
273 outstream << "<GuideDeviation enabled='" << (m_EnforceGuideDeviation ? "true" : "false") << "'>"
274 << cLocale.toString(m_GuideDeviation) << "</GuideDeviation>" << Qt::endl;
275 outstream << "<GuideStartDeviation enabled='" << (m_EnforceStartGuiderDrift ? "true" : "false") << "'>"
276 << cLocale.toString(m_StartGuideDeviation) << "</GuideStartDeviation>" << Qt::endl;
277 outstream << "<HFRCheck enabled='" << (m_EnforceAutofocusHFR ? "true" : "false") << "'>" << Qt::endl;
278 outstream << "<HFRDeviation>" << cLocale.toString(m_HFRDeviation) << "</HFRDeviation>" << Qt::endl;
279 outstream << "<HFRCheckAlgorithm>" << m_HFRCheckAlgorithm << "</HFRCheckAlgorithm>" << Qt::endl;
280 outstream << "<HFRCheckThreshold>" << cLocale.toString(m_HFRCheckThresholdPercentage) << "</HFRCheckThreshold>" << Qt::endl;
281 outstream << "<HFRCheckFrames>" << cLocale.toString(m_HFRCheckFrames) << "</HFRCheckFrames>" << Qt::endl;
282 outstream << "</HFRCheck>" << Qt::endl;
283 outstream << "<RefocusOnTemperatureDelta enabled='" << (m_EnforceAutofocusOnTemperature ? "true" : "false") <<
284 "'>"
285 << cLocale.toString(m_MaxFocusTemperatureDelta) << "</RefocusOnTemperatureDelta>" << Qt::endl;
286 outstream << "<RefocusEveryN enabled='" << (m_EnforceRefocusEveryN ? "true" : "false") << "'>"
287 << cLocale.toString(m_RefocusEveryN) << "</RefocusEveryN>" << Qt::endl;
288 outstream << "<RefocusOnMeridianFlip enabled='" << (m_RefocusAfterMeridianFlip ? "true" : "false") << "'/>"
289 << Qt::endl;
290
291 for (auto &job : m_allJobs)
292 {
293 job->saveTo(outstream, cLocale);
294 }
295
296 outstream << "</SequenceQueue>" << Qt::endl;
297
298 emit newLog(i18n("Sequence queue saved to %1", path));
299 file.flush();
300 file.close();
301
302 return true;
303}
304
305}
306
Sequence Job is a container for the details required to capture a series of images.
QString i18n(const char *text, const TYPE &arg...)
Ekos is an advanced Astrophotography tool for Linux.
Definition align.cpp:83
bool open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
void setFileName(const QString &name)
virtual void close() override
bool flush()
void append(QList< T > &&value)
QLocale c()
double toDouble(QStringView s, bool *ok) const const
int toInt(QStringView s, bool *ok) const const
QString toString(QDate date, FormatType format) const const
bool isEmpty() const const
QTextStream & endl(QTextStream &stream)
QUrl fromLocalFile(const QString &localFile)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:38:42 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.