8#include "capturemodulestate.h"
11#include "ekos_capture_debug.h"
16CaptureModuleState::CaptureModuleState(
QObject *parent):
QObject{parent} {}
20 mutableCameras().append(newCamera);
21 connect(newCamera.
get(), &Camera::newStatus,
this, &CaptureModuleState::captureStateChanged);
22 connect(newCamera.
get(), &Camera::requestAction,
this, &CaptureModuleState::handleActionRequest);
25 m_DitheringTimer.setSingleShot(
true);
31void CaptureModuleState::removeCamera(
int pos)
33 if (pos > m_Cameras.count() - 1)
36 auto cam = m_Cameras.at(pos);
38 cam->disconnect(
this);
41 m_Cameras.removeAt(pos);
46void CaptureModuleState::captureStateChanged(CaptureState newstate,
const QString &trainname,
int cameraID)
58 if (activeAction(cameraID) == CAPTURE_ACTION_PAUSE)
60 setActiveAction(cameraID, CAPTURE_ACTION_NONE);
63 clearAllActions(cameraID);
67 if (checkMeridianFlipActive())
68 pauseCapturingImmediately(cameraID);
78void CaptureModuleState::setGuideStatus(GuideState newstate)
82 case GUIDE_DITHERING_SUCCESS:
83 case GUIDE_DITHERING_ERROR:
84 foreach (
auto cam, cameras())
87 if (activeAction(cam->cameraId()) == CAPTURE_ACTION_DITHER)
88 setActiveAction(cam->cameraId(), CAPTURE_ACTION_NONE);
90 if (cam->state()->isCaptureStopped() || cam->state()->isCapturePausing())
91 enqueueAction(cam->cameraId(), CAPTURE_ACTION_START);
95 foreach (
auto cam, cameras())
98 if (activeAction(cam->cameraId()) == CAPTURE_ACTION_CHECK_GUIDING)
99 setActiveAction(cam->cameraId(), CAPTURE_ACTION_NONE);
108 foreach (
auto cam, cameras())
109 cam->state()->setGuideState(newstate);
112 checkActiveActions();
115void CaptureModuleState::setGuideDeviation(
double delta_ra,
double delta_dec)
117 const double deviation_rms = std::hypot(delta_ra, delta_dec);
119 foreach (
auto cam, cameras())
120 cam->state()->setGuideDeviation(deviation_rms);
123void Ekos::CaptureModuleState::pauseCapturingImmediately(
int cameraID,
bool followersOnly)
128 foreach (
auto cam, cameras())
130 pauseCapturingImmediately(cam->cameraId(), followersOnly);
136 if (cameraID >= cameras().count())
138 qCWarning(KSTARS_EKOS_CAPTURE) <<
"pauseCapturingImmediately(): unknown camera ID =" << cameraID;
143 if ((!followersOnly || cameraID > 0) && cameras()[cameraID]->state()->isCaptureRunning())
146 enqueueAction(cameraID, CAPTURE_ACTION_PAUSE);
148 enqueueAction(cameraID, CAPTURE_ACTION_SUSPEND);
152bool CaptureModuleState::checkMeridianFlipActive()
154 if (leadState().isNull())
157 return leadState()->getMeridianFlipState()->checkMeridianFlipActive();
162 if (cameras().size() <= 0)
165 return cameras()[0]->state();
168void CaptureModuleState::updateMFMountState(MeridianFlipState::MeridianFlipMountState status)
171 if (status == m_MFMountState)
176 case MeridianFlipState::MOUNT_FLIP_ACCEPTED:
177 case MeridianFlipState::MOUNT_FLIP_RUNNING:
179 pauseCapturingImmediately();
181 case MeridianFlipState::MOUNT_FLIP_COMPLETED:
182 setupRestartPostMF();
191 checkActiveActions();
194CaptureWorkflowActionType CaptureModuleState::activeAction(
int cameraID)
196 if (m_activeActions.
contains(cameraID))
197 return m_activeActions[cameraID];
199 return CAPTURE_ACTION_NONE;
202void CaptureModuleState::setActiveAction(
int cameraID, CaptureWorkflowActionType action)
204 if (action == CAPTURE_ACTION_NONE)
205 m_activeActions.
remove(cameraID);
207 m_activeActions[cameraID] = action;
210void CaptureModuleState::handleActionRequest(
int cameraID, CaptureWorkflowActionType action)
212 qCDebug(KSTARS_EKOS_CAPTURE) <<
"Handling" << action <<
"request for camera" << cameraID;
215 case CAPTURE_ACTION_DITHER_REQUEST:
216 setActiveAction(cameraID, action);
217 prepareDitheringAction(cameraID);
224 checkActiveActions();
227void CaptureModuleState::enqueueAction(
int cameraID, CaptureWorkflowActionType action)
229 getActionQueue(cameraID).enqueue(action);
232void CaptureModuleState::checkActiveActions()
234 foreach (
auto cam, cameras())
236 const int cameraID = cam->cameraId();
237 switch (activeAction(cameraID))
239 case CAPTURE_ACTION_NONE:
240 checkNextActionExecution(cameraID);
242 case CAPTURE_ACTION_DITHER_REQUEST:
243 checkReadyForDithering(cameraID);
254 if (!m_actionQueues.
contains(cameraId))
257 return m_actionQueues[cameraId];
260void CaptureModuleState::checkNextActionExecution(
int cameraID)
264 foreach (
auto cam, cameras())
265 checkNextActionExecution(cam->cameraId());
272 if (m_activeActions[cameraID] != CAPTURE_ACTION_NONE || actionQueue.
isEmpty())
275 auto action = actionQueue.
dequeue();
279 case CAPTURE_ACTION_START:
280 if (cam->state()->isCaptureStopped())
282 else if (cam->state()->isCapturePausing())
283 cam->toggleSequence();
285 case CAPTURE_ACTION_PAUSE:
286 setActiveAction(cameraID, CAPTURE_ACTION_PAUSE);
289 if (!getActionQueue(cameraID).isEmpty() && actionQueue.
head() == CAPTURE_ACTION_SUSPEND)
295 case CAPTURE_ACTION_SUSPEND:
296 setActiveAction(cameraID, CAPTURE_ACTION_SUSPEND);
299 case CAPTURE_ACTION_CHECK_GUIDING:
300 setActiveAction(cameraID, CAPTURE_ACTION_CHECK_GUIDING);
303 qCWarning(KSTARS_EKOS_CAPTURE) <<
"No activity defined for action" << action;
307 checkActiveActions();
310void CaptureModuleState::clearAllActions(
int cameraID)
312 setActiveAction(cameraID, CAPTURE_ACTION_NONE);
313 getActionQueue(cameraID).clear();
316void CaptureModuleState::prepareDitheringAction(
int cameraId)
318 const double maxRemainingExposureTime = 0.5 * mutableCameras()[cameraId]->activeJob()->getCoreProperty(
319 SequenceJob::SJ_Exposure).toDouble();
320 foreach (
auto cam, cameras())
322 if (cam->state()->isCaptureRunning() && cam->cameraId() != cameraId)
324 if (cameraId > 0 || cam->activeJob()->getExposeLeft() < maxRemainingExposureTime)
327 if (cam->cameraId() > 0)
328 enqueueAction(cam->cameraId(), CAPTURE_ACTION_PAUSE);
333 enqueueAction(cam->cameraId(), CAPTURE_ACTION_PAUSE);
335 enqueueAction(cam->cameraId(), CAPTURE_ACTION_SUSPEND);
340 checkActiveActions();
343 m_DitheringTimer.
start(maxRemainingExposureTime * 1000);
346void CaptureModuleState::checkReadyForDithering(
int cameraId)
350 foreach (
auto cam, cameras())
351 if (cam->state()->isCaptureRunning() && cam->cameraId() != cameraId)
354 qCDebug(KSTARS_EKOS_CAPTURE) <<
"Dithering requested by camera" << cameraId <<
"blocked by camera" << cam->cameraId();
360 qCInfo(KSTARS_EKOS_CAPTURE) <<
"Execute dithering requested by camera" << cameraId;
361 setActiveAction(cameraId, CAPTURE_ACTION_DITHER);
362 foreach(
auto cam, cameras())
364 const int id = cam->cameraId();
366 if (
id != cameraId && activeAction(
id) == CAPTURE_ACTION_DITHER_REQUEST)
367 setActiveAction(
id, CAPTURE_ACTION_DITHER);
371 m_DitheringTimer.
stop();
377void CaptureModuleState::startDithering()
381 foreach (
auto id, m_activeActions.
keys())
382 if (activeAction(
id) == CAPTURE_ACTION_DITHER_REQUEST)
384 setActiveAction(
id, CAPTURE_ACTION_DITHER);
387 else if (activeAction(
id) == CAPTURE_ACTION_DITHER)
395 foreach (
auto cam, cameras())
396 if (cam->state()->isCaptureRunning() && activeAction(cam->cameraId()) != CAPTURE_ACTION_DITHER)
398 qCInfo(KSTARS_EKOS_CAPTURE) <<
"Aborting capture of camera" << cam->cameraId() <<
"before dithering starts";
403 emit newLog(
i18n(
"Dithering..."));
407void CaptureModuleState::setupRestartPostMF()
410 if (cameras().size() == 0)
413 const bool waitForGuiding = leadState()->getMeridianFlipState()->resumeGuidingAfterFlip()
414 && leadState()->getGuideState() != GUIDE_GUIDING;
416 foreach (
auto cam, cameras())
418 if (cam->cameraId() > 0 && (cam->state()->isCaptureStopped() || cam->state()->isCapturePausing()))
422 enqueueAction(cam->cameraId(), CAPTURE_ACTION_CHECK_GUIDING);
425 enqueueAction(cam->cameraId(), CAPTURE_ACTION_START);
QString i18n(const char *text, const TYPE &arg...)
Ekos is an advanced Astrophotography tool for Linux.
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
bool isEmpty() const const
bool contains(const Key &key) const const
QList< Key > keys() const const
size_type remove(const Key &key)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool isActive() const const