CtControl.cpp 24.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//###########################################################################
// This file is part of LImA, a Library for Image Acquisition
//
// Copyright (C) : 2009-2011
// European Synchrotron Radiation Facility
// BP 220, Grenoble 38043
// FRANCE
//
// This is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
//###########################################################################
papillon's avatar
   
papillon committed
22
23
24
#include <string>
#include <sstream>

25
26
#include "CtControl.h"
#include "CtSaving.h"
27
#ifdef WITH_SPS_IMAGE
ahoms's avatar
ahoms committed
28
#include "CtSpsImage.h"
29
#endif
papillon's avatar
   
papillon committed
30
#include "CtAcquisition.h"
papillon's avatar
   
papillon committed
31
#include "CtImage.h"
papillon's avatar
   
papillon committed
32
#include "CtBuffer.h"
33
#include "CtShutter.h"
34
#include "CtAccumulation.h"
Florent Langlois's avatar
Florent Langlois committed
35
#include "CtVideo.h"
36
#include "CtEvent.h"
37

38
39
#include "SoftOpInternalMgr.h"
#include "SoftOpExternalMgr.h"
papillon's avatar
   
papillon committed
40

41
#include "PoolThreadMgr.h"
papillon's avatar
   
papillon committed
42

43
44
using namespace lima;

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
class CtControl::_LastBaseImageReadyCallback : public TaskEventCallback
{
public:
  _LastBaseImageReadyCallback(CtControl &ctrl) : 
    TaskEventCallback(),_ctrl(ctrl) {}
						 
  virtual void finished(Data &aData)
  {
    _ctrl.newBaseImageReady(aData);
  }
private:
  CtControl &_ctrl;
};

class CtControl::_LastImageReadyCallback : public TaskEventCallback
{
public:
  _LastImageReadyCallback(CtControl &ctrl) :
    TaskEventCallback(),_ctrl(ctrl) {}
  
  virtual void finished(Data &aData)
  {
    _ctrl.newImageReady(aData);
  }
private:
  CtControl &_ctrl;
};

class CtControl::_LastImageSavedCallback : public TaskEventCallback
{
public:
  _LastImageSavedCallback(CtControl &ctrl) :
    TaskEventCallback(),_ctrl(ctrl) {}
  
  virtual void finished(Data &aData)
  {
    _ctrl.newImageSaved(aData);
  }
private:
  CtControl &_ctrl;
};

class CtControl::_LastCounterReadyCallback : public TaskEventCallback
{
public:
  _LastCounterReadyCallback(CtControl &ctrl) :
    TaskEventCallback(),_ctrl(ctrl) {}
  
  virtual void finished(Data &aData)
  {
    _ctrl.newCounterReady(aData);
  }
private:
  CtControl &_ctrl;
};

101
102
103
104
105
106
107
108
109
110
111
112
113
114
class CtControl::_AbortAcqCallback : public TaskEventCallback
{
public:
  _AbortAcqCallback(CtControl &ctrl) :
    TaskEventCallback(),_ctrl(ctrl) {}
  
  virtual void finished(Data &aData)
  {
    _ctrl.stopAcq();
  }
private:
  CtControl &_ctrl;
};

115
116
117
118
class CtControl::SoftOpErrorHandler : public TaskMgr::EventCallback
{
public:
  SoftOpErrorHandler(CtControl &ctr) : m_ct(ctr) {}
119

120
121
122
123
124
125
126
127
128
129
  virtual void error(Data&,const char *errmsg)
  {
    Event *anEvent = new Event(Control,Event::Error,Event::Processing,
			       Event::Default,errmsg);
    CtEvent *eventMgr = m_ct.event();
    eventMgr->reportEvent(anEvent);
  }
private:
  CtControl&	m_ct;
};
130

131
CtControl::CtControl(HwInterface *hw) :
132
133
134
135
136
137
  m_hw(hw),
  m_op_int_active(false),
  m_op_ext_link_task_active(false),
  m_op_ext_sink_task_active(false),
  m_base_images_ready(CtControl::ltData()),
  m_images_ready(CtControl::ltData()),
138
  m_images_buffer_size(16),
139
  m_policy(All), m_ready(false),
140
  m_autosave(false), m_running(false),
141
  m_img_status_cb(NULL)
142
{
seb's avatar
seb committed
143
144
  DEB_CONSTRUCTOR();

papillon's avatar
   
papillon committed
145
  m_ct_acq= new CtAcquisition(hw);
146
  m_ct_image= new CtImage(hw,*this);
papillon's avatar
   
papillon committed
147
  m_ct_buffer= new CtBuffer(hw);
148
  m_ct_shutter = new CtShutter(hw);
149
  m_ct_accumulation = new CtAccumulation(*this);
Florent Langlois's avatar
Florent Langlois committed
150
  m_ct_video = new CtVideo(*this);
151
  m_ct_event = new CtEvent(*this);
152
153

  //Saving
papillon's avatar
   
papillon committed
154
  m_ct_saving= new CtSaving(*this);
155
156
157
158
  _LastImageSavedCallback *aSaveCbkPt = new _LastImageSavedCallback(*this);
  m_ct_saving->setEndCallback(aSaveCbkPt);
  aSaveCbkPt->unref();

159
#ifdef WITH_SPS_IMAGE
ahoms's avatar
ahoms committed
160
161
  //Sps image
  m_ct_sps_image = new CtSpsImage();
162
#endif
163
164
  m_op_int = new SoftOpInternalMgr();
  m_op_ext = new SoftOpExternalMgr();
165
166

  m_soft_op_error_handler = new SoftOpErrorHandler(*this);
167
}
papillon's avatar
   
papillon committed
168

169
170
CtControl::~CtControl()
{
seb's avatar
seb committed
171
172
  DEB_DESTRUCTOR();

173
174
175
176
  DEB_TRACE() << "Waiting for all threads to finish their tasks";
  PoolThreadMgr& pool_thread_mgr = PoolThreadMgr::get();
  pool_thread_mgr.wait();

177
178
179
  if (m_img_status_cb)
    unregisterImageStatusCallback(*m_img_status_cb);

180
  delete m_ct_saving;
181
#ifdef WITH_SPS_IMAGE
ahoms's avatar
ahoms committed
182
  delete m_ct_sps_image;
183
#endif
papillon's avatar
   
papillon committed
184
  delete m_ct_acq;
papillon's avatar
   
papillon committed
185
  delete m_ct_image;
papillon's avatar
   
papillon committed
186
  delete m_ct_buffer;
Laurent Claustre's avatar
Laurent Claustre committed
187
  delete m_ct_shutter;
188
  delete m_ct_accumulation;
Florent Langlois's avatar
Florent Langlois committed
189
190
  delete m_ct_video;

papillon's avatar
   
papillon committed
191
  delete m_op_int;
192
  delete m_op_ext;
193
194

  delete m_soft_op_error_handler;
195
196
}

papillon's avatar
   
papillon committed
197
198
void CtControl::setApplyPolicy(ApplyPolicy policy)
{
seb's avatar
seb committed
199
200
201
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR1(policy);

papillon's avatar
   
papillon committed
202
203
204
  m_policy= policy;
}

seb's avatar
seb committed
205
void CtControl::getApplyPolicy(ApplyPolicy &policy) const
papillon's avatar
   
papillon committed
206
{
seb's avatar
seb committed
207
208
  DEB_MEMBER_FUNCT();

papillon's avatar
   
papillon committed
209
  policy= m_policy;
seb's avatar
seb committed
210
211

  DEB_RETURN() << DEB_VAR1(policy);
papillon's avatar
   
papillon committed
212
}
213
214
215

void CtControl::prepareAcq()
{
seb's avatar
seb committed
216
  DEB_MEMBER_FUNCT();
217

218
219
220
  Status aStatus;
  getStatus(aStatus);

221
  if(aStatus.AcquisitionStatus == AcqRunning)
222
223
224
225
    throw LIMA_CTL_EXC(Error,"Acquisition not finished");

  if(aStatus.AcquisitionStatus == AcqConfig)
    throw LIMA_CTL_EXC(Error,"Configuration not finished");
226

227
  resetStatus(false);
228
229
230
  
  //Clear common header
  m_ct_saving->resetInternalCommonHeader();
231

seb's avatar
seb committed
232
  DEB_TRACE() << "Apply hardware bin/roi";
papillon's avatar
papillon committed
233
  m_ct_image->applyHard();
seb's avatar
seb committed
234
235

  DEB_TRACE() << "Setup Acquisition Buffers";
papillon's avatar
   
papillon committed
236
  m_ct_buffer->setup(this);
seb's avatar
seb committed
237

238
239
240
  DEB_TRACE() << "Apply Acquisition Parameters";
  m_ct_acq->apply(m_policy);

241
242
243
  DEB_TRACE() << "Apply Shutter Parameters";
  m_ct_shutter->apply();

244
245
246
  DEB_TRACE() << "Prepare Accumulation if needed";
  m_ct_accumulation->prepare();

247
248
249
250
251
  DEB_TRACE() << "Prepare Saving if needed";
  m_ct_saving->_prepare();
  m_autosave= m_ct_saving->hasAutoSaveMode();
  m_ready= true;

seb's avatar
seb committed
252
  DEB_TRACE() << "Prepare Hardware for Acquisition";
papillon's avatar
   
papillon committed
253
  m_hw->prepareAcq();
papillon's avatar
   
papillon committed
254

seb's avatar
seb committed
255
  DEB_TRACE() << "Apply software bin/roi";
256
257
  m_op_int_active= (m_ct_image->applySoft(m_op_int) ||
		    m_op_int->hasReconstructionTask());
258
259
  if(m_op_int_active)
    {
260
261
262
263
264
      TaskEventCallback *aCbkPt;
      if(m_ct_buffer->isAccumulationActive())
	aCbkPt = new CtAccumulation::_ImageReady4AccCallback(*this->m_ct_accumulation);
      else
	aCbkPt = new _LastBaseImageReadyCallback(*this);
265
266
267
268
269
      m_op_int->setEndCallback(aCbkPt);
      aCbkPt->unref();
    }
  else
    m_op_int->setEndCallback(NULL);
papillon's avatar
   
papillon committed
270
  // set ext op
271
272
  m_op_ext->prepare();
  m_op_ext->isTaskActive(m_op_ext_link_task_active,m_op_ext_sink_task_active);
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
  if(m_op_ext_link_task_active)
    {
      _LastImageReadyCallback *aCbkPt = new _LastImageReadyCallback(*this);
      m_op_ext->setEndLinkTaskCallback(aCbkPt);
      aCbkPt->unref();
    }
  else
    m_op_ext->setEndLinkTaskCallback(NULL);

  if(m_op_ext_sink_task_active)
    {
      _LastCounterReadyCallback *aCbkPt = new _LastCounterReadyCallback(*this);
      m_op_ext->setEndSinkTaskCallback(aCbkPt);
      aCbkPt->unref();
    }
  else
    m_op_ext->setEndSinkTaskCallback(NULL);
papillon's avatar
   
papillon committed
290

291
#ifdef WITH_SPS_IMAGE
ahoms's avatar
ahoms committed
292
293
294
295
296
297
298
299
  m_display_active_flag = m_ct_sps_image->isActive();
  if(m_display_active_flag)
  {
    FrameDim dim;
    m_ct_image->getImageDim(dim);
    
    m_ct_sps_image->prepare(dim);
  }
300
#endif
301
302
  m_images_ready.clear();
  m_base_images_ready.clear();
303
  m_images_buffer.clear();
Florent Langlois's avatar
Florent Langlois committed
304
  m_ct_video->_prepareAcq();
305
  m_ct_event->_prepareAcq();
306
307
308
309
310
311
312
313
314
315
316
317
318

  //Check that no software operation is done if Hardware saving is activated
  CtSaving::ManagedMode savingManagedMode;
  m_ct_saving->getManagedMode(savingManagedMode);
  if(savingManagedMode == CtSaving::Hardware &&
     (m_op_int_active || 
      m_op_ext_link_task_active ||
      m_op_ext_sink_task_active ||
#ifdef WITH_SPS_IMAGE
      m_display_active_flag ||
#endif
      m_ct_video->isActive()))
    THROW_CTL_ERROR(Error) << "Can't have any software operation if Hardware saving is active";
319
320
321
322
}

void CtControl::startAcq()
{
seb's avatar
seb committed
323
324
  DEB_MEMBER_FUNCT();

papillon's avatar
   
papillon committed
325
326
  if (!m_ready)
	throw LIMA_CTL_EXC(Error, "Run prepareAcq before starting acquisition");
327
  m_running = true;
328
329
330
331
332
333
334
335
336
337
  TrigMode trigMode;
  m_ct_acq->getTriggerMode(trigMode);

  if(trigMode != IntTrigMult)
    m_ready = false;
  else
    {
      //First check the detector is in Idle Stat
      HwInterface::Status hwStatus;
      m_hw->getStatus(hwStatus);
338
      if(hwStatus.det != DetIdle)
339
340
341
342
343
344
345
346
	throw LIMA_CTL_EXC(Error, "Try to restart before detector is ready");

      //m_ready = false after the last image is triggerred
      int nbFrames4Acq;
      m_ct_acq->getAcqNbFrames(nbFrames4Acq);
      nbFrames4Acq -= 2;
      m_ready = m_status.ImageCounters.LastImageAcquired != nbFrames4Acq;
    }
seb's avatar
seb committed
347

348
349
  AutoMutex aLock(m_cond.mutex());

papillon's avatar
   
papillon committed
350
  m_hw->startAcq();
351
  m_status.AcquisitionStatus = AcqRunning;
seb's avatar
seb committed
352
  DEB_TRACE() << "Hardware Acquisition started";
353
354
355
356
}
 
void CtControl::stopAcq()
{
seb's avatar
seb committed
357
358
  DEB_MEMBER_FUNCT();

papillon's avatar
   
papillon committed
359
  m_hw->stopAcq();
360
  m_ready = false;
361
  m_running = false;
seb's avatar
seb committed
362
  DEB_TRACE() << "Hardware Acquisition Stopped";
363
  _calcAcqStatus();
364
}
seb's avatar
seb committed
365
void CtControl::getStatus(Status& status) const
366
{
seb's avatar
seb committed
367
  DEB_MEMBER_FUNCT();
papillon's avatar
   
papillon committed
368

seb's avatar
seb committed
369
  AutoMutex aLock(m_cond.mutex());
370
  status = m_status;
371
372
373
374
375
376
  HwInterface::Status aHwStatus;
  m_hw->getStatus(aHwStatus);
  DEB_TRACE() << DEB_VAR1(aHwStatus);
  if(aHwStatus.acq == AcqFault)
    status.AcquisitionStatus = AcqFault;
  else if(status.AcquisitionStatus == AcqReady)
seb's avatar
seb committed
377
    {
378
379
380
      HwInterface::Status aHwStatus;
      m_hw->getStatus(aHwStatus);
      DEB_TRACE() << DEB_VAR1(aHwStatus);
381
382
383
      status.AcquisitionStatus = aHwStatus.acq;
    }
}
seb's avatar
seb committed
384

385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
/** @brief aborts an acquisiton from a callback thread: it's safe to call 
 *  from a HW thread. Creates a dummy task that calls stopAcq()
 */

void CtControl::abortAcq(AcqStatus acq_status, ErrorCode error_code, 
			 Data& data, bool ctrl_mutex_locked)
{
  DEB_MEMBER_FUNCT();

  if (!ctrl_mutex_locked)
    m_cond.mutex().lock();

  bool status_change = (m_status.AcquisitionStatus != acq_status);
  if (status_change) {
    m_status.AcquisitionStatus = acq_status;
    m_status.Error = error_code;
  }

  if (!ctrl_mutex_locked)
    m_cond.mutex().unlock();

  typedef SinkTaskBase AbortAcqTask;
  AbortAcqTask *abort_task = new AbortAcqTask();
  _AbortAcqCallback *abort_cb = new _AbortAcqCallback(*this);
  abort_task->setEventCallback(abort_cb);
  abort_cb->unref();

  TaskMgr *mgr = new TaskMgr();
  mgr->setInputData(data);
  mgr->addSinkTask(0, abort_task);
  abort_task->unref();
  
  PoolThreadMgr::get().addProcess(mgr);
}


421
422
423
424
425
/** @brief an event arrived, calc the new status
 */
void CtControl::_calcAcqStatus()
{
  DEB_MEMBER_FUNCT();
seb's avatar
seb committed
426

427
428
429
430
431
432
433
434
  AutoMutex aLock(m_cond.mutex());
  if(m_status.AcquisitionStatus == AcqRunning)
    {
      const ImageStatus &anImageCnt = m_status.ImageCounters;
      int acq_nb_frames;
      m_ct_acq->getAcqNbFrames(acq_nb_frames);
      if((!m_running ||
	  anImageCnt.LastImageAcquired == (acq_nb_frames - 1)) && // we reach the nb frames asked
435
	 anImageCnt.LastImageAcquired == anImageCnt.LastImageReady) // processing has finished
seb's avatar
seb committed
436
	{
437
	  if(m_autosave)
438
	    {
439
	      // Saving is finished
440
441
	      if(anImageCnt.LastImageAcquired == anImageCnt.LastImageSaved)
		m_status.AcquisitionStatus = AcqReady;
442
	    }
443
	  else
444
445
	    m_status.AcquisitionStatus = AcqReady;
	  DEB_TRACE() << DEB_VAR1(m_status);
seb's avatar
seb committed
446
447
	}
    }
448
449
450
451
}

void CtControl::getImageStatus(ImageStatus& status) const
{
seb's avatar
seb committed
452
453
  DEB_MEMBER_FUNCT();
  
454
  AutoMutex aLock(m_cond.mutex());
seb's avatar
seb committed
455
  status= m_status.ImageCounters;
seb's avatar
seb committed
456
457
  
  DEB_RETURN() << DEB_VAR1(status);
458
459
}

460
461
void CtControl::ReadImage(Data &aReturnData,long frameNumber, 
			  long readBlockLen)
462
{
seb's avatar
seb committed
463
  DEB_MEMBER_FUNCT();
464
465
  DEB_PARAM() << DEB_VAR2(frameNumber, readBlockLen);

466
467
468
  AutoMutex aLock(m_cond.mutex());
  if(m_op_ext_link_task_active)
    {
469
470
471
      if (readBlockLen != 1)
	throw LIMA_CTL_EXC(NotSupported, "Cannot read more than one frame "
			   "at a time with External Operations");
472
473
      if(frameNumber < 0)
	frameNumber = m_status.ImageCounters.LastImageReady;
474

475
476
477
478
479
480
481
482
483
484
485
486
487
488
      std::map<int,Data>::iterator i = m_images_buffer.find(frameNumber);
      if(i != m_images_buffer.end())
	aReturnData = i->second;
      else
	{
	  if(frameNumber < m_status.ImageCounters.LastImageReady - m_images_buffer_size)
	    throw LIMA_CTL_EXC(Error,"Frame no more available");
	  else
	    throw LIMA_CTL_EXC(Error,"Frame not available yet");
	}
    }
  else
    {
      aLock.unlock();
489
490
491
492
493
494
495
496
497
498
499
500
      CtSaving::ManagedMode savingManagedMode;
      m_ct_saving->getManagedMode(savingManagedMode);
      if(savingManagedMode == CtSaving::Hardware)
	{
	  if (readBlockLen != 1)
	    THROW_CTL_ERROR(NotSupported) << "Cannot read more than one frame " 
					  << "at a time with Hardware Saving";

	  m_ct_saving->_ReadImage(aReturnData,frameNumber);
	}
      else
	ReadBaseImage(aReturnData,frameNumber,readBlockLen);
501
    }
seb's avatar
seb committed
502
503

  DEB_RETURN() << DEB_VAR1(aReturnData);
504
505
}

506
507
void CtControl::ReadBaseImage(Data &aReturnData,long frameNumber, 
			      long readBlockLen)
508
{
seb's avatar
seb committed
509
  DEB_MEMBER_FUNCT();
510
  DEB_PARAM() << DEB_VAR2(frameNumber, readBlockLen);
seb's avatar
seb committed
511

512
513
514
515
516
  AcqMode acqMode;
  m_ct_acq->getAcqMode(acqMode);
  int acq_nb_frames;
  m_ct_acq->getAcqNbFrames(acq_nb_frames);

517
  AutoMutex aLock(m_cond.mutex());
seb's avatar
seb committed
518
  ImageStatus &imgStatus = m_status.ImageCounters;
519
  long lastFrame = imgStatus.LastBaseImageReady;
520
521
522
523
524

  //Authorize to read the current frame in Accumulation Mode
  if(acqMode == Accumulation && lastFrame < acq_nb_frames - 1)
    ++lastFrame;

525
526
527
528
529
530
  if (frameNumber < 0) {
    frameNumber = lastFrame - (readBlockLen - 1);
    if (frameNumber < 0)
      throw LIMA_CTL_EXC(Error, "Frame(s) not available yet");
  } else if (frameNumber + readBlockLen - 1 > lastFrame)
    throw LIMA_CTL_EXC(Error, "Frame(s) not available yet");
531
  aLock.unlock();
532
  m_ct_buffer->getFrame(aReturnData,frameNumber,readBlockLen);
seb's avatar
seb committed
533
  
534
535
  FrameDim img_dim;
  m_ct_image->getImageDim(img_dim);
536
  int roiWidth = img_dim.getSize().getWidth();
537
  int roiHeight = img_dim.getSize().getHeight() * readBlockLen;
538
  if((roiWidth * roiHeight) >
Florent Langlois's avatar
Florent Langlois committed
539
     (aReturnData.dimensions[0] * aReturnData.dimensions[1]))
540
541
    throw LIMA_CTL_EXC(Error, "Roi dim > HwBuffer dim");

Florent Langlois's avatar
Florent Langlois committed
542
543
  aReturnData.dimensions[0] = roiWidth;
  aReturnData.dimensions[1] = roiHeight;
544

seb's avatar
seb committed
545
  DEB_RETURN() << DEB_VAR1(aReturnData);
546
547
}

papillon's avatar
   
papillon committed
548
549
550
551
552
void CtControl::setReconstructionTask(LinkTask *task)
{
  m_op_int->setReconstructionTask(task);
}

553
554
void CtControl::reset()
{
seb's avatar
seb committed
555
  DEB_MEMBER_FUNCT();
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571

  DEB_TRACE() << "Stopping acquisition";
  stopAcq();

  DEB_TRACE() << "Throwing waiting save tasks";
  m_ct_saving->clear();

  DEB_TRACE() << "Suspending task threads";
  PoolThreadMgr& pool_thread_mgr = PoolThreadMgr::get();
  pool_thread_mgr.abort();
 
  DEB_TRACE() << "Reseting hardware";
  m_hw->reset(HwInterface::SoftReset);

  DEB_TRACE() << "Reseting image";
  m_ct_image->reset();
572
573
574
575
576
577

  DEB_TRACE() << "Reseting buffer";
  m_ct_buffer->reset();

  DEB_TRACE() << "Reseting acquisition";
  m_ct_acq->reset();
578
579
580
  
  DEB_TRACE() << "Reseting shutter parameters";
  m_ct_shutter->reset();
ahoms's avatar
ahoms committed
581

582
#ifdef WITH_SPS_IMAGE
ahoms's avatar
ahoms committed
583
584
  DEB_TRACE() << "Reseting display";
  m_ct_sps_image->reset();
585
#endif
586
  resetStatus(false);
587
  m_status.AcquisitionStatus = AcqReady;
588
589
590
591
592
593
594
595
596
597
}

void CtControl::resetStatus(bool only_acq_status)
{
  DEB_MEMBER_FUNCT();
  DEB_TRACE() << "Reseting the status";
  if (only_acq_status)
    m_status.AcquisitionStatus = AcqReady;
  else
    m_status.reset();
598
599
}

600
bool CtControl::newFrameReady(Data& fdata)
papillon's avatar
   
papillon committed
601
{
seb's avatar
seb committed
602
603
604
605
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR1(fdata);

  DEB_TRACE() << "Frame acq.nb " << fdata.frameNumber << " received";
606

607
  bool aContinueFlag = true;
608
  AutoMutex aLock(m_cond.mutex());
seb's avatar
seb committed
609
  if(_checkOverrun(fdata))
610
611
    aContinueFlag = false;// Stop Acquisition on overun
  else
seb's avatar
seb committed
612
    {
613
      m_status.ImageCounters.LastImageAcquired= fdata.frameNumber;
seb's avatar
seb committed
614
      aLock.unlock();
615
  
616
      TaskMgr *mgr = new TaskMgr();
617
      mgr->setEventCallback(m_soft_op_error_handler);
618
      mgr->setInputData(fdata);
papillon's avatar
   
papillon committed
619

620
      int internal_stage = 0;
621
      if (!m_ct_buffer->isAccumulationActive())
622
	m_op_int->addTo(*mgr, internal_stage);
623
  
624
625
      int last_link,last_sink;
      m_op_ext->addTo(*mgr, internal_stage, last_link, last_sink);
papillon's avatar
   
papillon committed
626

627
      if (internal_stage || (last_link >= 0) || (last_sink >= 0))
628
629
630
	PoolThreadMgr::get().addProcess(mgr);
      else
	delete mgr;
631
      if (!internal_stage)
632
	newBaseImageReady(fdata);
633

634
635
      if (m_img_status_cb)
	m_img_status_cb->imageStatusChanged(m_status.ImageCounters);
636
      _calcAcqStatus();
637
    }
638

639
  return aContinueFlag;
640
}
papillon's avatar
   
papillon committed
641

642
643
void CtControl::newBaseImageReady(Data &aData)
{
seb's avatar
seb committed
644
645
646
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR1(aData);

647
  AutoMutex aLock(m_cond.mutex());
seb's avatar
seb committed
648
  long expectedImageReady = m_status.ImageCounters.LastBaseImageReady + 1;
649
  bool img_status_changed = false;
650
651
652
653
654
655
656
657
658
659
660
661
662
663
  if(aData.frameNumber == expectedImageReady)
    {
      while(!m_base_images_ready.empty())
	{
	  std::set<Data,ltData>::iterator i = m_base_images_ready.begin();
	  long nextExpectedImageReady = expectedImageReady + 1;
	  if(nextExpectedImageReady == i->frameNumber)
	    {
	      expectedImageReady = nextExpectedImageReady;
	      m_base_images_ready.erase(i);
	    }
	  else
	    break;
	}
seb's avatar
seb committed
664
665
      ImageStatus &imgStatus = m_status.ImageCounters;
      imgStatus.LastBaseImageReady = expectedImageReady;
666
      if(!m_op_ext_link_task_active)
seb's avatar
seb committed
667
	imgStatus.LastImageReady = expectedImageReady;
668
669
      
      img_status_changed = true;
670
671
672
    }
  else
    m_base_images_ready.insert(aData);
673

674
675
  aLock.unlock();

676
  if(m_autosave && !m_op_ext_link_task_active)
677
    newFrameToSave(aData);
678

679
#ifdef WITH_SPS_IMAGE
ahoms's avatar
ahoms committed
680
  if(m_display_active_flag)
681
    m_ct_sps_image->frameReady(aData);
682
#endif
seb's avatar
seb committed
683

Florent Langlois's avatar
Florent Langlois committed
684
685
  m_ct_video->frameReady(aData);

686
  if(m_img_status_cb && img_status_changed)
seb's avatar
seb committed
687
    m_img_status_cb->imageStatusChanged(m_status.ImageCounters);
688

689
  _calcAcqStatus();
690
}
papillon's avatar
   
papillon committed
691

692
693
void CtControl::newImageReady(Data &aData)
{
seb's avatar
seb committed
694
695
696
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR1(aData);

697
  AutoMutex aLock(m_cond.mutex());
seb's avatar
seb committed
698
  long expectedImageReady = m_status.ImageCounters.LastImageReady + 1;
699
  bool img_status_changed = false;
700
701
702
703
704
705
706
707
708
709
710
711
712
713
  if(aData.frameNumber == expectedImageReady)
    {
      while(!m_images_ready.empty())
	{
	  std::set<Data,ltData>::iterator i = m_images_ready.begin();
	  long nextExpectedImageReady = expectedImageReady + 1;
	  if(nextExpectedImageReady == i->frameNumber)
	    {
	      expectedImageReady = nextExpectedImageReady;
	      m_images_ready.erase(i);
	    }
	  else
	    break;
	}
seb's avatar
seb committed
714
      m_status.ImageCounters.LastImageReady = expectedImageReady;
715
716

      img_status_changed = true;
717
718
719
720
    }
  else
    m_images_ready.insert(aData);

721
722
723
724
725
  m_images_buffer.insert(std::pair<int,Data>(aData.frameNumber,aData));
  //pop out the oldest Data
  if(int(m_images_buffer.size()) > m_images_buffer_size)
    m_images_buffer.erase(m_images_buffer.begin());

726
727
  aLock.unlock();

728
  if(m_autosave)
729
    newFrameToSave(aData);
730
731

  if (m_img_status_cb && img_status_changed)
seb's avatar
seb committed
732
    m_img_status_cb->imageStatusChanged(m_status.ImageCounters);
733
  _calcAcqStatus();
734
735
736
737
}

void CtControl::newCounterReady(Data&)
{
seb's avatar
seb committed
738
  DEB_MEMBER_FUNCT();
739
740
741
742
743
744
745
746
747
  //@todo
}

/** @brief inc the save counter.
 *  @warning due to sequential saving, no check with image number!!!
 *  @see newImageReady
*/
void CtControl::newImageSaved(Data&)
{
seb's avatar
seb committed
748
  DEB_MEMBER_FUNCT();
749
750
  CtSaving::ManagedMode savingManagedMode;
  m_ct_saving->getManagedMode(savingManagedMode);
751
  AutoMutex aLock(m_cond.mutex());
seb's avatar
seb committed
752
  ++m_status.ImageCounters.LastImageSaved;
753
754
755
756
757
758
  if(savingManagedMode == CtSaving::Hardware)
    {
      m_status.ImageCounters.LastImageAcquired = m_status.ImageCounters.LastImageSaved;
      m_status.ImageCounters.LastBaseImageReady = m_status.ImageCounters.LastImageSaved;
      m_status.ImageCounters.LastImageReady = m_status.ImageCounters.LastImageSaved;
    }
759
760
761
  aLock.unlock();

  if (m_img_status_cb)
seb's avatar
seb committed
762
    m_img_status_cb->imageStatusChanged(m_status.ImageCounters);
763
  _calcAcqStatus();
papillon's avatar
   
papillon committed
764
765
766
767
}

void CtControl::newFrameToSave(Data& fdata)
{
seb's avatar
seb committed
768
769
770
771
772
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR1(fdata);

  DEB_TRACE() << "Add frame acq.nr " << fdata.frameNumber 
	      << " to saving";
papillon's avatar
   
papillon committed
773
774
775
  m_ct_saving->frameReady(fdata);
}

776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
void CtControl::registerImageStatusCallback(ImageStatusCallback& cb)
{
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR2(&cb, m_img_status_cb);

  if (m_img_status_cb) {
    DEB_ERROR() << "ImageStatusCallback already registered";
    throw LIMA_CTL_EXC(InvalidValue, "ImageStatusCallback already registered");
  }

  cb.setImageStatusCallbackGen(this);
  m_img_status_cb = &cb;
}

void CtControl::unregisterImageStatusCallback(ImageStatusCallback& cb)
{
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR2(&cb, m_img_status_cb);

  if (m_img_status_cb != &cb) {
    DEB_ERROR() << "ImageStatusCallback not registered";
    throw LIMA_CTL_EXC(InvalidValue, "ImageStatusCallback not registered");
  }
  
  m_img_status_cb = NULL;
  cb.setImageStatusCallbackGen(NULL);
}

seb's avatar
seb committed
804
805
806
/** @brief this methode check if an overrun 
 *  @warning this methode is call under lock
 */
807
bool CtControl::_checkOverrun(Data &aData)
seb's avatar
seb committed
808
809
810
811
812
813
814
815
816
817
818
{
  DEB_MEMBER_FUNCT();
  if(m_status.AcquisitionStatus == AcqFault) return true;

  const ImageStatus &imageStatus = m_status.ImageCounters;

  long imageToProcess = imageStatus.LastImageAcquired - 
    imageStatus.LastBaseImageReady;

  long imageToSave =	imageStatus.LastImageAcquired -
    imageStatus.LastImageSaved;
819

seb's avatar
seb committed
820
821
822
  long nb_buffers;
  m_ct_buffer->getNumber(nb_buffers);
  
seb's avatar
seb committed
823
  CtSaving::SavingMode mode;
824
  m_ct_saving->getSavingMode(mode);
seb's avatar
seb committed
825

seb's avatar
seb committed
826
  bool overrunFlag = false;
827
  ErrorCode error_code = NoError;
seb's avatar
seb committed
828
829
830
  if(imageToProcess >= nb_buffers) // Process overrun
    {
      overrunFlag = true;
831
      error_code = ProcessingOverun;
seb's avatar
seb committed
832
    }
seb's avatar
seb committed
833
  else if(mode != CtSaving::Manual && imageToSave >= nb_buffers) // Save overrun
seb's avatar
seb committed
834
835
    {
      overrunFlag = true;
836
837
838
839
840
841
842
843
      int first_to_save, last_to_save;
      m_ct_saving->getSaveCounters(first_to_save, last_to_save);
      DEB_ERROR() << DEB_VAR2(first_to_save, last_to_save);
      int frames_to_save = last_to_save - first_to_save + 1;
      int frames_to_compress = imageStatus.LastBaseImageReady - last_to_save;
      bool slow_processing = frames_to_compress > frames_to_save;
      DEB_ERROR() << DEB_VAR2(frames_to_compress, frames_to_save);
      error_code = slow_processing ? ProcessingOverun : SaveOverun;
seb's avatar
seb committed
844
    }
845

Florent Langlois's avatar
Florent Langlois committed
846
  DEB_PARAM() << DEB_VAR1(overrunFlag);
847
848
849
850
851
  if (overrunFlag) {
    DEB_ERROR() << DEB_VAR2(m_status, error_code);
    abortAcq(AcqFault, error_code, aData, true);
  }

seb's avatar
seb committed
852
853
  return overrunFlag;
}
papillon's avatar
   
papillon committed
854
855
856
// ----------------------------------------------------------------------------
// Struct ImageStatus
// ----------------------------------------------------------------------------
857
858
CtControl::ImageStatus::ImageStatus()
{
seb's avatar
seb committed
859
  DEB_CONSTRUCTOR();
860
861
862
863
864
  reset();
}

void CtControl::ImageStatus::reset()
{
seb's avatar
seb committed
865
866
  DEB_MEMBER_FUNCT();

867
868
869
870
871
  LastImageAcquired	= -1;
  LastBaseImageReady	= -1;
  LastImageReady	= -1;
  LastImageSaved	= -1;
  LastCounterReady	= -1;
seb's avatar
seb committed
872
873
  
  DEB_TRACE() << *this;
874
}
seb's avatar
seb committed
875
876
877
878
879
880
881
882
883
884
885
886
// ----------------------------------------------------------------------------
// Struct Status
// ----------------------------------------------------------------------------

CtControl::Status::Status() :
  AcquisitionStatus(AcqReady),
  Error(NoError),
  CameraStatus(NoCameraError),
  ImageCounters()
{
  DEB_CONSTRUCTOR();
}
887

seb's avatar
seb committed
888
889
890
891
892
893
894
895
896
void CtControl::Status::reset()
{
  DEB_MEMBER_FUNCT();

  AcquisitionStatus = AcqReady;
  Error = NoError;
  CameraStatus = NoCameraError;
  ImageCounters.reset();
}
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919

// ----------------------------------------------------------------------------
// class ImageStatus
// ----------------------------------------------------------------------------
CtControl::ImageStatusCallback::ImageStatusCallback()
  : m_cb_gen(NULL)
{
  DEB_CONSTRUCTOR();
}

CtControl::ImageStatusCallback::~ImageStatusCallback()
{
  DEB_DESTRUCTOR();
  if (m_cb_gen)
    m_cb_gen->unregisterImageStatusCallback(*this);
}

void 
CtControl::ImageStatusCallback::setImageStatusCallbackGen(CtControl *cb_gen)
{
  DEB_MEMBER_FUNCT();
  m_cb_gen = cb_gen;
}
920
921

#ifdef WIN32
Sebastien Petitdemange's avatar
Sebastien Petitdemange committed
922
CtAcquisition* CtControl::acquisition() 		{ return m_ct_acq; }
923
924
CtSaving* 		CtControl::saving() 		{ return m_ct_saving; }
#ifdef WITH_SPS_IMAGE
Sebastien Petitdemange's avatar
Sebastien Petitdemange committed
925
CtSpsImage* 	CtControl::display() 			{ return m_ct_sps_image; }
926
#endif
Sebastien Petitdemange's avatar
Sebastien Petitdemange committed
927
928
929
930
931
CtImage* 		CtControl::image() 		{ return m_ct_image; }
CtBuffer* 		CtControl::buffer() 		{ return m_ct_buffer; }
CtAccumulation* 	CtControl::accumulation() 	{ return m_ct_accumulation; }
CtVideo*		CtControl::video()		{ return m_ct_video;}
CtShutter* 		CtControl::shutter() 		{ return m_ct_shutter; }
932
CtEvent* 		CtControl::event()		{ return m_ct_event; }
933

Sebastien Petitdemange's avatar
Sebastien Petitdemange committed
934
SoftOpExternalMgr* 	CtControl::externalOperation() 	{return m_op_ext;}
935

Sebastien Petitdemange's avatar
Sebastien Petitdemange committed
936
HwInterface* 	CtControl::hwInterface() 		{return m_hw;}
937
#endif