MNE-CPP  beta 1.0
babymeg.cpp
1 //=============================================================================================================
37 //*************************************************************************************************************
38 //=============================================================================================================
39 // INCLUDES
40 //=============================================================================================================
41 
42 #include "babymeg.h"
43 
45 #include "FormFiles/babymegprojectdialog.h"
46 
47 
48 #include <utils/ioutils.h>
49 
50 #include <iostream>
51 
52 
53 //*************************************************************************************************************
54 //=============================================================================================================
55 // QT INCLUDES
56 //=============================================================================================================
57 
58 #include <QtCore/QtPlugin>
59 #include <QtCore/QTextStream>
60 #include <QtCore/QFile>
61 
62 #include <QList>
63 #include <QDebug>
64 #include <QDir>
65 #include <QDateTime>
66 
67 
68 //*************************************************************************************************************
69 //=============================================================================================================
70 // USED NAMESPACES
71 //=============================================================================================================
72 
73 using namespace BabyMEGPlugin;
74 using namespace UTILSLIB;
75 
76 
77 //*************************************************************************************************************
78 //=============================================================================================================
79 // DEFINE MEMBER METHODS
80 //=============================================================================================================
81 
83 : m_iBlinkStatus(0)
84 , m_iBufferSize(-1)
85 , m_bWriteToFile(false)
86 , m_sCurrentParadigm("")
87 , m_bIsRunning(false)
88 , m_pRawMatrixBuffer(0)
89 , m_sFiffHeader(QCoreApplication::applicationDirPath() + "/mne_x_plugins/resources/babymeg/header.fif")
90 , m_sBadChannels(QCoreApplication::applicationDirPath() + "/mne_x_plugins/resources/babymeg/both.bad")
91 {
92  m_pActionSetupProject = new QAction(QIcon(":/images/database.png"), tr("Setup Project"),this);
93 // m_pActionSetupProject->setShortcut(tr("F12"));
94  m_pActionSetupProject->setStatusTip(tr("Setup Project"));
95  connect(m_pActionSetupProject, &QAction::triggered, this, &BabyMEG::showProjectDialog);
96  addPluginAction(m_pActionSetupProject);
97 
98  m_pActionUpdateFiffInfo = new QAction(QIcon(":/images/latestFiffInfo.png"), tr("Update Fiff Info"),this);
99  m_pActionUpdateFiffInfo->setStatusTip(tr("Update Fiff Info"));
100  connect(m_pActionUpdateFiffInfo, &QAction::triggered, this, &BabyMEG::UpdateFiffInfo);
101  addPluginAction(m_pActionUpdateFiffInfo);
102 
103  m_pActionRecordFile = new QAction(QIcon(":/images/record.png"), tr("Start Recording"),this);
104 // m_pActionSetupProject->setShortcut(tr("F12"));
105  m_pActionRecordFile->setStatusTip(tr("Start Recording"));
106  connect(m_pActionRecordFile, &QAction::triggered, this, &BabyMEG::toggleRecordingFile);
107  addPluginAction(m_pActionRecordFile);
108 
109  //m_pActionRecordFile->setEnabled(false);
110 
111  m_pActionSqdCtrl = new QAction(QIcon(":/images/sqdctrl.png"), tr("Squid Control"),this);
112 // m_pActionSetupProject->setShortcut(tr("F12"));
113  m_pActionSqdCtrl->setStatusTip(tr("Squid Control"));
114  connect(m_pActionSqdCtrl, &QAction::triggered, this, &BabyMEG::showSqdCtrlDialog);
115  addPluginAction(m_pActionSqdCtrl);
116 
117 }
118 
119 
120 //*************************************************************************************************************
121 
123 {
124  if(this->isRunning())
125  stop();
126 
127  if(myClient && myClient->isConnected())
128  myClient->DisConnectBabyMEG();
129 
130 }
131 
132 
133 //*************************************************************************************************************
134 
135 QSharedPointer<IPlugin> BabyMEG::clone() const
136 {
137  QSharedPointer<BabyMEG> pBabyMEGClone(new BabyMEG());
138  return pBabyMEGClone;
139 }
140 
141 
142 //*************************************************************************************************************
143 
144 QString BabyMEG::getFilePath(bool currentTime) const
145 {
146  QString sFilePath = m_sBabyMEGDataPath + "/" + m_sCurrentProject + "/" + m_sCurrentSubject;
147 
148  QString sTimeStamp;
149 
150  if(currentTime)
151  sTimeStamp = QDateTime::currentDateTime().toString("yyMMdd_hhmmss");
152  else
153  sTimeStamp = "<YYMMDD_HMS>";
154 
155  if(m_sCurrentParadigm.isEmpty())
156  sFilePath.append("/"+ sTimeStamp + "_" + m_sCurrentSubject + "_raw.fif");
157  else
158  sFilePath.append("/"+ sTimeStamp + "_" + m_sCurrentSubject + "_" + m_sCurrentParadigm + "_raw.fif");
159 
160  return sFilePath;
161 }
162 
163 
164 //*************************************************************************************************************
165 
166 void BabyMEG::init()
167 {
168  //BabyMEGData Path
169  m_sBabyMEGDataPath = QDir::homePath() + "/BabyMEGData";
170  if(!QDir(m_sBabyMEGDataPath).exists())
171  QDir().mkdir(m_sBabyMEGDataPath);
172  //Test Project
173  if(!QDir(m_sBabyMEGDataPath+"/TestProject").exists())
174  QDir().mkdir(m_sBabyMEGDataPath+"/TestProject");
175  QSettings settings;
176  m_sCurrentProject = settings.value(QString("Plugin/%1/currentProject").arg(getName()), "TestProject").toString();
177  //Test Subject
178  if(!QDir(m_sBabyMEGDataPath+"/TestProject/TestSubject").exists())
179  QDir().mkdir(m_sBabyMEGDataPath+"/TestProject/TestSubject");
180  m_sCurrentSubject = settings.value(QString("Plugin/%1/currentSubject").arg(getName()), "TestSubject").toString();
181 
182  //BabyMEG Inits
183  pInfo = QSharedPointer<BabyMEGInfo>(new BabyMEGInfo());
184  connect(pInfo.data(), &BabyMEGInfo::fiffInfoAvailable, this, &BabyMEG::setFiffInfo);
185  connect(pInfo.data(), &BabyMEGInfo::SendDataPackage, this, &BabyMEG::setFiffData);
186  connect(pInfo.data(), &BabyMEGInfo::SendCMDPackage, this, &BabyMEG::setCMDData);
187  connect(pInfo.data(), &BabyMEGInfo::GainInfoUpdate, this, &BabyMEG::setFiffGainInfo);
188 
189  myClient = QSharedPointer<BabyMEGClient>(new BabyMEGClient(6340,this));
190  myClient->SetInfo(pInfo);
191  myClient->start();
192  myClientComm = QSharedPointer<BabyMEGClient>(new BabyMEGClient(6341,this));
193  myClientComm->SetInfo(pInfo);
194  myClientComm->start();
195 
196  myClientComm->SendCommandToBabyMEGShortConnection("INFO");
197 
198  myClient->ConnectToBabyMEG();
199 
200  //init channels when fiff info is available
201  connect(this, &BabyMEG::fiffInfoAvailable, this, &BabyMEG::initConnector);
202 
203 }
204 
205 
206 //*************************************************************************************************************
207 
209 {
210 
211 }
212 
213 
214 //*************************************************************************************************************
215 //=============================================================================================================
216 // Create measurement instances and config them
217 //=============================================================================================================
218 
219 void BabyMEG::initConnector()
220 {
221  if(m_pFiffInfo)
222  {
223  m_pRTMSABabyMEG = PluginOutputData<NewRealTimeMultiSampleArray>::create(this, "BabyMEG Output", "BabyMEG");
224  m_pRTMSABabyMEG->data()->setName(this->getName());//Provide name to auto store widget settings
225 
226  m_pRTMSABabyMEG->data()->initFromFiffInfo(m_pFiffInfo);
227  m_pRTMSABabyMEG->data()->setMultiArraySize(2);
228 
229  m_pRTMSABabyMEG->data()->setSamplingRate(m_pFiffInfo->sfreq);
230 
231  m_pRTMSABabyMEG->data()->setVisibility(true);
232 
233  m_outputConnectors.append(m_pRTMSABabyMEG);
234  }
235 }
236 
237 
238 //*************************************************************************************************************
239 
241 {
242  m_pFiffInfo.reset();
243  m_iBufferSize = -1;
244 }
245 
246 
247 //*************************************************************************************************************
248 
249 void BabyMEG::showProjectDialog()
250 {
251  BabyMEGProjectDialog projectDialog(this);
252  projectDialog.exec();
253 }
254 
255 
256 //*************************************************************************************************************
257 
258 void BabyMEG::showSqdCtrlDialog()
259 {
260  //BabyMEGSQUIDControlDgl SQUIDCtrlDlg(this);
261  //SQUIDCtrlDlg.exec();
262  // added by Limin for nonmodal dialog
263  if (SQUIDCtrlDlg == NULL)
264  SQUIDCtrlDlg = QSharedPointer<BabyMEGSQUIDControlDgl>(new BabyMEGSQUIDControlDgl(this));
265 
266  if (!SQUIDCtrlDlg->isVisible())
267  {
268  SQUIDCtrlDlg->show();
269  SQUIDCtrlDlg->raise();
270  SQUIDCtrlDlg->Init();
271  }
272 }
273 
274 //*************************************************************************************************************
275 
277 {
278 
279  // read gain info and save them to the m_pFiffInfo.range
280  myClientComm->SendCommandToBabyMEGShortConnection("INFG");
281 
282  //sleep(0.5);
283 
284  //m_pActionRecordFile->setEnabled(true);
285 
286 }
287 
288 
289 //*************************************************************************************************************
290 
292 {
293  qDebug() << "Split recording file";
294  ++m_iSplitCount;
295  QString nextFileName = m_sRecordFile.remove("_raw.fif");
296  nextFileName += QString("-%1_raw.fif").arg(m_iSplitCount);
297 
298  /*
299  * Write the link to the next file
300  */
301  qint32 data;
302  m_pOutfid->start_block(FIFFB_REF);
303  data = FIFFV_ROLE_NEXT_FILE;
304  m_pOutfid->write_int(FIFF_REF_ROLE,&data);
305  m_pOutfid->write_string(FIFF_REF_FILE_NAME, nextFileName);
306  m_pOutfid->write_id(FIFF_REF_FILE_ID);//ToDo meas_id
307  data = m_iSplitCount - 1;
308  m_pOutfid->write_int(FIFF_REF_FILE_NUM, &data);
309  m_pOutfid->end_block(FIFFB_REF);
310 
311  //finish file
312  m_pOutfid->finish_writing_raw();
313 
314  //start next file
315  m_qFileOut.setFileName(nextFileName);
316  m_pOutfid = Fiff::start_writing_raw(m_qFileOut, *m_pFiffInfo, m_cals);
317  fiff_int_t first = 0;
318  m_pOutfid->write_int(FIFF_FIRST_SAMPLE, &first);
319 }
320 
321 
322 //*************************************************************************************************************
323 
325 {
326  //Setup writing to file
327  if(m_bWriteToFile)
328  {
329  m_pOutfid->finish_writing_raw();
330  m_bWriteToFile = false;
331  m_pTimerRecordingChange->stop();
332  m_pActionRecordFile->setIcon(QIcon(":/images/record.png"));
333  m_iSplitCount = 0;
334  }
335  else
336  {
337  m_iSplitCount = 0;
338 
339  if(!m_pFiffInfo)
340  {
341  QMessageBox msgBox;
342  msgBox.setText("FiffInfo missing!");
343  msgBox.exec();
344  return;
345  }
346 
347 
348  //Initiate the stream for writing to the fif file
349  m_sRecordFile = getFilePath(true);
350  m_qFileOut.setFileName(m_sRecordFile);
351  if(m_qFileOut.exists())
352  {
353  QMessageBox msgBox;
354  msgBox.setText("The file you want to write already exists.");
355  msgBox.setInformativeText("Do you want to overwrite this file?");
356  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
357  int ret = msgBox.exec();
358  if(ret == QMessageBox::No)
359  return;
360  }
361 
362  m_pOutfid = Fiff::start_writing_raw(m_qFileOut, *m_pFiffInfo, m_cals);
363  fiff_int_t first = 0;
364  m_pOutfid->write_int(FIFF_FIRST_SAMPLE, &first);
365 
366  m_bWriteToFile = true;
367 
368  m_pTimerRecordingChange = QSharedPointer<QTimer>(new QTimer);
369  connect(m_pTimerRecordingChange.data(), &QTimer::timeout, this, &BabyMEG::changeRecordingButton);
370  m_pTimerRecordingChange->start(500);
371  }
372 }
373 
374 
375 //*************************************************************************************************************
376 
377 void BabyMEG::setFiffData(QByteArray DATA)
378 {
379  //get the first byte -- the data format
380  int dformat = DATA.left(1).toInt();
381 
382  DATA.remove(0,1);
383  qint32 rows = m_pFiffInfo->nchan;
384  qint32 cols = (DATA.size()/dformat)/rows;
385 
386  qDebug() << "[BabyMEG] Matrix " << rows << "x" << cols << " [Data bytes:" << dformat << "]";
387 
388  MatrixXf rawData(Map<MatrixXf>( (float*)DATA.data(),rows, cols ));
389 
390  for(qint32 i = 0; i < rows*cols; ++i)
391  IOUtils::swap_floatp(rawData.data()+i);
392 
393 
394  if(m_bIsRunning)
395  {
396  if(!m_pRawMatrixBuffer)
397  m_pRawMatrixBuffer = CircularMatrixBuffer<float>::SPtr(new CircularMatrixBuffer<float>(40, rows, cols));
398 
399  m_pRawMatrixBuffer->push(&rawData);
400  }
401 // else
402 // {
404 
405 // emit DataToSquidCtrlGUI(rawData);
406 // }
407 
408  emit DataToSquidCtrlGUI(rawData);
409 }
410 
411 
412 //*************************************************************************************************************
413 
414 void BabyMEG::setFiffInfo(FiffInfo p_FiffInfo)
415 {
416  m_pFiffInfo = QSharedPointer<FiffInfo>(new FiffInfo(p_FiffInfo));
417 
418  if(!readProjectors())
419  {
420  qDebug() << "Not able to read projectors";
421  return;
422  }
423 
424  if(!readBadChannels())
425  {
426  qDebug() << "Not able to read bad channels";
427  return;
428  }
429 
430  m_iBufferSize = pInfo->dataLength;
431  sfreq = pInfo->sfreq;
432 
433  //
434  // Add the calibration factors
435  //
436  m_cals = RowVectorXd(m_pFiffInfo->nchan);
437  m_cals.setZero();
438  for (qint32 k = 0; k < m_pFiffInfo->nchan; ++k)
439  m_cals[k] = m_pFiffInfo->chs[k].range*m_pFiffInfo->chs[k].cal;
440 
441  //
442  // Initialize the data and calibration vector
443  //
444  typedef Eigen::Triplet<double> T;
445  std::vector<T> tripletList;
446  tripletList.reserve(m_pFiffInfo->nchan);
447  for(qint32 i = 0; i < m_pFiffInfo->nchan; ++i)
448  tripletList.push_back(T(i, i, this->m_cals[i]));
449 
450  m_sparseMatCals = SparseMatrix<double>(m_pFiffInfo->nchan, m_pFiffInfo->nchan);
451  m_sparseMatCals.setFromTriplets(tripletList.begin(), tripletList.end());
452 
453  emit fiffInfoAvailable();
454 }
455 
456 //*************************************************************************************************************
457 
458 void BabyMEG::setFiffGainInfo(QStringList GainInfo)
459 {
460  if(!m_pFiffInfo)
461  {
462  QMessageBox msgBox;
463  msgBox.setText("FiffInfo missing!");
464  msgBox.exec();
465  return;
466  }
467  else
468  {
469  //set up the gain info
470  qDebug()<<"Set Gain Info";
471  for(qint32 i = 0; i < m_pFiffInfo->nchan; i++)
472  {
473  m_pFiffInfo->chs[i].range = 1.0f/GainInfo.at(i).toFloat();//1; // set gain
474  //qDebug()<<i<<"="<<m_pFiffInfo->chs[i].ch_name<<","<<m_pFiffInfo->chs[i].range;
475  }
476  }
477 
478 }
479 //*************************************************************************************************************
480 
481 void BabyMEG::setCMDData(QByteArray DATA)
482 {
483  qDebug()<<"------"<<DATA;
484 // m_commandManager["FLL"].reply(DATA);
485  emit SendCMDDataToSQUIDControl(DATA);
486  qDebug()<<"Data has been received.";
487 }
488 
489 
490 //*************************************************************************************************************
491 void BabyMEG::comFLL(QString t_sFLLControlCommand)
492 {
493  qDebug()<<"FLL commands";
494 
495  qDebug() << "BabyMeg Received" << t_sFLLControlCommand;
496  int strlen = t_sFLLControlCommand.size();
497  QByteArray Scmd = myClientComm->MGH_LM_Int2Byte(strlen);
498  QByteArray SC = QByteArray("COMS")+Scmd;
499  SC.append(t_sFLLControlCommand);
500  myClientComm->SendCommandToBabyMEGShortConnection(SC);
501 }
502 
503 
504 //*************************************************************************************************************
505 
506 bool BabyMEG::start()
507 {
508  //Check if the thread is already or still running. This can happen if the start button is pressed immediately after the stop button was pressed. In this case the stopping process is not finished yet but the start process is initiated.
509  if(this->isRunning())
510  QThread::wait();
511 
512  if(!m_pRTMSABabyMEG)
513  initConnector();
514 
515  // Start threads
516  m_bIsRunning = true;
517 
518  if(!myClient->isConnected())
519  myClient->ConnectToBabyMEG();
520  // Start threads
521  QThread::start();
522 
523  return true;
524 }
525 
526 
527 //*************************************************************************************************************
528 
529 bool BabyMEG::stop()
530 {
531  if(myClient->isConnected())
532  myClient->DisConnectBabyMEG();
533 
534  m_bIsRunning = false;
535 
536  //In case the semaphore blocks the thread -> Release the QSemaphore and let it exit from the pop function (acquire statement)
537  m_pRawMatrixBuffer->releaseFromPop();
538 
539  //Clear Buffers
540  m_pRawMatrixBuffer->clear();
541 
542  return true;
543 }
544 
545 
546 //*************************************************************************************************************
547 
549 {
550  return _ISensor;
551 }
552 
553 
554 //*************************************************************************************************************
555 
556 QString BabyMEG::getName() const
557 {
558  return "BabyMEG";
559 }
560 
561 
562 //*************************************************************************************************************
563 
565 {
566  if(!myClient->isConnected())
567  myClient->ConnectToBabyMEG();
568 
569  BabyMEGSetupWidget* widget = new BabyMEGSetupWidget(this);//widget is later distroyed by CentralWidget - so it has to be created everytime new
570 
571  //init dialog
572 
573  return widget;
574 }
575 
576 
577 //*************************************************************************************************************
578 
579 MatrixXd BabyMEG::calibrate(const MatrixXf& data)
580 {
581  MatrixXd one;
582  if(m_pFiffInfo && m_sparseMatCals.cols() == m_pFiffInfo->nchan)
583  one = m_sparseMatCals*data.cast<double>();
584  else
585  one = data.cast<double>();
586 
587  return one;
588 }
589 
590 
591 //*************************************************************************************************************
592 
593 bool BabyMEG::readProjectors()
594 {
595  QFile t_headerFiffFile(m_sFiffHeader);
596 
597  //
598  // Open the file
599  //
600  FiffStream::SPtr t_pStream(new FiffStream(&t_headerFiffFile));
601  QString t_sFileName = t_pStream->streamName();
602 
603  printf("Opening header data %s...\n",t_sFileName.toUtf8().constData());
604 
605  FiffDirTree t_Tree;
606  QList<FiffDirEntry> t_Dir;
607 
608  if(!t_pStream->open(t_Tree, t_Dir))
609  return false;
610 
611  QList<FiffProj> q_ListProj = t_pStream->read_proj(t_Tree);
612 
613  if (q_ListProj.size() == 0)
614  {
615  printf("Could not find projectors\n");
616  return false;
617  }
618 
619  m_pFiffInfo->projs = q_ListProj;
620 
621  //garbage collecting
622  t_pStream->device()->close();
623 
624  return true;
625 }
626 
627 
628 //*************************************************************************************************************
629 
630 bool BabyMEG::readBadChannels()
631 {
632  //
633  // Bad Channels
634  //
635  QFile t_badChannelsFile(m_sBadChannels);
636 
637  if (!t_badChannelsFile.open(QIODevice::ReadOnly | QIODevice::Text))
638  return false;
639 
640  printf("Reading bad channels from %s...\n", m_sBadChannels.toUtf8().constData());
641 
642  QTextStream in(&t_badChannelsFile);
643  qint32 count = 0;
644  QStringList t_sListbads;
645  while (!in.atEnd()) {
646  QString channel = in.readLine();
647  if(channel.isEmpty())
648  continue;
649  ++count;
650  printf("Channel %i: %s\n",count,channel.toUtf8().constData());
651  t_sListbads << channel;
652  }
653 
654  m_pFiffInfo->bads = t_sListbads;
655 
656  return true;
657 }
658 
659 
660 //*************************************************************************************************************
661 
662 void BabyMEG::run()
663 {
664 
665  MatrixXf matValue;
666 
667  qint32 size = 0;
668 
669  while(m_bIsRunning)
670  {
671  if(m_pRawMatrixBuffer)
672  {
673  //pop matrix
674  matValue = m_pRawMatrixBuffer->pop();
675 
676  //Write raw data to fif file
677  if(m_bWriteToFile)
678  {
679  size += matValue.rows()*matValue.cols() * 4;
680 
681  if(size > MAX_DATA_LEN)
682  {
683  size = 0;
684  this->splitRecordingFile();
685  }
686 
687  m_pOutfid->write_raw_buffer(matValue.cast<double>());
688  }
689  else
690  size = 0;
691 
692  if(m_pRTMSABabyMEG)
693  m_pRTMSABabyMEG->data()->setValue(this->calibrate(matValue));
694  }
695  }
696 
697  //Close the fif output stream
698  if(m_bWriteToFile)
699  this->toggleRecordingFile();
700 }
701 
702 
703 //*************************************************************************************************************
704 
705 void BabyMEG::changeRecordingButton()
706 {
707  if(m_iBlinkStatus == 0)
708  {
709  m_pActionRecordFile->setIcon(QIcon(":/images/record.png"));
710  m_iBlinkStatus = 1;
711  }
712  else
713  {
714  m_pActionRecordFile->setIcon(QIcon(":/images/record_active.png"));
715  m_iBlinkStatus = 0;
716  }
717 }
The BabyMEGSetupWidget class provides the ECG configuration window.
FIFF measurement file information.
Definition: fiff_info.h:96
OutputConnectorList m_outputConnectors
Definition: IPlugin.h:222
The BabyMEGClient class provides a TCP/IP communication between Qt and Labview.
Definition: babymeginfo.h:70
virtual void unload()
Definition: babymeg.cpp:208
void DisConnectBabyMEG()
void SendCommandToBabyMEGShortConnection(QByteArray s)
void SetInfo(BabyMEGInfo *pInfo)
void DataToSquidCtrlGUI(MatrixXf tmp)
QSharedPointer< CircularMatrixBuffer > SPtr
void addPluginAction(QAction *pAction)
Definition: IPlugin.h:249
void SendCMDDataToSQUIDControl(QByteArray DATA)
QSharedPointer< FiffStream > SPtr
Definition: fiff_stream.h:132
void push(const Matrix< _Tp, Dynamic, Dynamic > *pMatrix)
virtual void run()
Definition: babymeg.cpp:394
QString getFilePath(bool currentTime=false) const
Definition: babymeg.cpp:144
Directory tree structure.
Definition: fiff_dir_tree.h:80
Matrix< _Tp, Dynamic, Dynamic > pop()
The BabyMEGClient class provides a TCP/IP communication between Qt and Labview.
Definition: babymegclient.h:70
static void swap_floatp(float *source)
Definition: ioutils.cpp:196
static FiffStream::SPtr start_writing_raw(QIODevice &p_IODevice, const FiffInfo &info, RowVectorXd &cals, MatrixXi sel=defaultMatrixXi)
Definition: fiff.h:719
QByteArray MGH_LM_Int2Byte(int a)
The BabyMEGSQUIDControlDgl class provides the SQUID control dialog.
virtual QWidget * setupWidget()
Definition: babymeg.cpp:564
Contains the declaration of the BabyMEGSetupWidget class.
static QSharedPointer< PluginOutputData< T > > create(IPlugin *parent, const QString &name, const QString &descr)
virtual QSharedPointer< IPlugin > clone() const
Definition: babymeg.cpp:135
virtual IPlugin::PluginType getType() const
Definition: babymeg.cpp:548
FIFF File I/O routines.
Definition: fiff_stream.h:129
IOUtils class declaration.