MNE-CPP  beta 1.0
fiffstreamthread.cpp
Go to the documentation of this file.
1 //=============================================================================================================
37 //*************************************************************************************************************
38 //=============================================================================================================
39 // INCLUDES
40 //=============================================================================================================
41 
42 #include "fiffstreamthread.h"
43 #include "fiffstreamserver.h"
44 #include "mne_rt_commands.h"
45 
46 
47 //*************************************************************************************************************
48 //=============================================================================================================
49 // Fiff INCLUDES
50 //=============================================================================================================
51 
52 #include <utils/ioutils.h>
53 #include <fiff/fiff_constants.h>
54 #include <fiff/fiff_tag.h>
55 
56 
57 //*************************************************************************************************************
58 //=============================================================================================================
59 // QT INCLUDES
60 //=============================================================================================================
61 
62 #include <QtNetwork>
63 
64 
65 //*************************************************************************************************************
66 //=============================================================================================================
67 // USED NAMESPACES
68 //=============================================================================================================
69 
70 using namespace UTILSLIB;
71 using namespace RTSERVER;
72 using namespace FIFFLIB;
73 
74 
75 //*************************************************************************************************************
76 //=============================================================================================================
77 // DEFINE MEMBER METHODS
78 //=============================================================================================================
79 
80 FiffStreamThread::FiffStreamThread(qint32 id, int socketDescriptor, QObject *parent)
81 : QThread(parent)
82 , m_iDataClientId(id)
83 , m_sDataClientAlias(QString(""))
84 , m_iSocketDescriptor(socketDescriptor)
85 , m_bIsSendingRawBuffer(false)
86 , m_bIsRunning(false)
87 {
88 }
89 
90 
91 //*************************************************************************************************************
92 
93 FiffStreamThread::~FiffStreamThread()
94 {
95  //Remove from client list
96  FiffStreamServer* t_pFiffStreamServer = qobject_cast<FiffStreamServer*>(this->parent());
97  if(t_pFiffStreamServer)
98  t_pFiffStreamServer->m_qClientList.remove(m_iDataClientId);
99 
100  m_bIsRunning = false;
101  QThread::wait();
102 }
103 
104 
105 //*************************************************************************************************************
106 
107 void FiffStreamThread::startMeas(qint32 ID)
108 {
109  if(ID == m_iDataClientId)
110  {
111  qDebug() << "Activate raw buffer sending.";
112 
113  m_qMutex.lock();
114  // ToDo send start meas
115  FiffStream t_FiffStreamOut(&m_qSendBlock, QIODevice::WriteOnly);
116  t_FiffStreamOut.start_block(FIFFB_RAW_DATA);
117  m_bIsSendingRawBuffer = true;
118  m_qMutex.unlock();
119  }
120 }
121 
122 
123 //*************************************************************************************************************
124 
125 void FiffStreamThread::stopMeas(qint32 ID)
126 {
127  qDebug() << "void FiffStreamThread::stopMeas(qint32 ID)";
128  if(ID == m_iDataClientId || ID == -1)
129  {
130  qDebug() << "stop raw buffer sending.";
131 
132  m_qMutex.lock();
133  FiffStream t_FiffStreamOut(&m_qSendBlock, QIODevice::WriteOnly);
134  t_FiffStreamOut.end_block(FIFFB_RAW_DATA);
135  m_bIsSendingRawBuffer = false;
136  m_qMutex.unlock();
137  }
138 }
139 
140 
141 //*************************************************************************************************************
142 
143 void FiffStreamThread::parseCommand(FiffTag::SPtr p_pTag)
144 {
145  if(p_pTag->size() >= 4)
146  {
147  qint32* t_pInt = (qint32*)p_pTag->data();
148  IOUtils::swap_intp(t_pInt);
149  qint32 t_iCmd = t_pInt[0];
150 
151  if(t_iCmd == MNE_RT_SET_CLIENT_ALIAS)
152  {
153  //
154  // Set Client Alias
155  //
156  m_sDataClientAlias = QString(p_pTag->mid(4, p_pTag->size()-4));
157  printf("FiffStreamClient (ID %d): new alias = '%s'\r\n\n", m_iDataClientId, m_sDataClientAlias.toUtf8().constData());
158  }
159  else if(t_iCmd == MNE_RT_GET_CLIENT_ID)
160  {
161  //
162  // Send Client ID
163  //
164  printf("FiffStreamClient (ID %d): send client ID %d\r\n\n", m_iDataClientId, m_iDataClientId);
165  writeClientId();
166  }
167  else
168  {
169  printf("FiffStreamClient (ID %d): unknown command\r\n\n", m_iDataClientId);
170  }
171  }
172  else
173  {
174  printf("FiffStreamClient (ID %d): unknown command\r\n\n", m_iDataClientId);
175  }
176 }
177 
178 
179 //*************************************************************************************************************
180 
181 void FiffStreamThread::sendRawBuffer(QSharedPointer<Eigen::MatrixXf> m_pMatRawData)
182 {
183  if(m_bIsSendingRawBuffer)
184  {
185 // qDebug() << "Send RawBuffer to client";
186 
187  m_qMutex.lock();
188 
189  FiffStream t_FiffStreamOut(&m_qSendBlock, QIODevice::WriteOnly);
190  t_FiffStreamOut.write_float(FIFF_DATA_BUFFER,m_pMatRawData->data(),m_pMatRawData->rows()*m_pMatRawData->cols());
191 
192  m_qMutex.unlock();
193 
194  }
195 // else
196 // {
197 // qDebug() << "Send RawBuffer is not activated";
198 // }
199 }
200 
201 
202 //*************************************************************************************************************
203 
204 //void FiffStreamThread::sendData(QTcpSocket& p_qTcpSocket)
205 //{
206 // if(p_qTcpSocket.state() != QAbstractSocket::UnconnectedState && m_bIsRunning)
207 // {
208 // m_qMutex.lock();
209 // qint32 t_iBlockSize = m_qSendBlock.size();
210 // if(t_iBlockSize > 0)
211 // {
213 // qint32 t_iBytesWritten = p_qTcpSocket.write(m_qSendBlock);
214 // qDebug()<<"[Block to write]"<<t_iBlockSize<<"[bytes has been Written]"<<t_iBytesWritten;
215 // p_qTcpSocket.waitForBytesWritten();
216 // }
217 // m_qMutex.unlock();
218 // }
219 //}
220 
221 
222 //*************************************************************************************************************
223 
224 void FiffStreamThread::sendMeasurementInfo(qint32 ID, FiffInfo p_fiffInfo)
225 {
226  if(ID == m_iDataClientId)
227  {
228  m_qMutex.lock();
229 
230  FiffStream t_FiffStreamOut(&m_qSendBlock, QIODevice::WriteOnly);
231 
232 // qint32 init_info[2];
233 // init_info[0] = FIFF_MNE_RT_CLIENT_ID;
234 // init_info[1] = m_iDataClientId;
235 
236 // t_FiffStreamOut.start_block(FIFFB_MNE_RT_MEAS_INFO);
237 
238 //FiffStream::start_writing_raw
239 
240  p_fiffInfo.writeToStream(&t_FiffStreamOut);
241  m_qMutex.unlock();
242 
243 // qDebug() << "MeasInfo Blocksize: " << m_qSendBlock.size();
244  }
245 }
246 
247 
248 //*************************************************************************************************************
249 
250 void FiffStreamThread::writeClientId()
251 {
252  FiffStream t_FiffStreamOut(&m_qSendBlock, QIODevice::WriteOnly);
253 
254  t_FiffStreamOut.write_int(FIFF_MNE_RT_CLIENT_ID, &m_iDataClientId);
255 }
256 
257 
258 //*************************************************************************************************************
259 
260 //void FiffStreamThread::readProc(QTcpSocket& p_qTcpSocket)
261 //{
262 // FiffStream t_FiffStreamIn(&p_qTcpSocket);
263 
264 // //
265 // // Read: Wait 10ms for incomming tag header, read and continue
266 // //
267 // p_qTcpSocket.waitForReadyRead(10);
268 
269 // if (p_qTcpSocket.bytesAvailable() >= (int)sizeof(qint32)*4)
270 // {
271 // qDebug() << "goes to read bytes " ;
272 // FiffTag::SPtr t_pTag;
273 // FiffTag::read_tag_info(&t_FiffStreamIn, t_pTag, false);
274 
275 // //
276 // // wait until tag size data are available and read the data
277 // //
278 // while (p_qTcpSocket.bytesAvailable() < t_pTag->size())
279 // {
280 // p_qTcpSocket.waitForReadyRead(10);
281 // }
282 // FiffTag::read_tag_data(&t_FiffStreamIn, t_pTag);
283 
284 // //
285 // // Parse the tag
286 // //
287 // if(t_pTag->kind == FIFF_MNE_RT_COMMAND)
288 // {
289 // parseCommand(t_pTag);
290 // }
291 // }
292 //}
293 
294 
295 //*************************************************************************************************************
296 
297 void FiffStreamThread::run()
298 {
299  m_bIsRunning = true;
300 
301  FiffStreamServer* t_pParentServer = qobject_cast<FiffStreamServer*>(this->parent());
302 
303  connect(t_pParentServer, &FiffStreamServer::remitMeasInfo,
304  this, &FiffStreamThread::sendMeasurementInfo);
305  connect(t_pParentServer, &FiffStreamServer::remitRawBuffer,
306  this, &FiffStreamThread::sendRawBuffer);
307  connect(t_pParentServer, &FiffStreamServer::startMeasFiffStreamClient,
308  this, &FiffStreamThread::startMeas);
309  connect(t_pParentServer, &FiffStreamServer::stopMeasFiffStreamClient,
310  this, &FiffStreamThread::stopMeas);
311 
312  QTcpSocket t_qTcpSocket;
313  if (!t_qTcpSocket.setSocketDescriptor(m_iSocketDescriptor)) {
314  emit error(t_qTcpSocket.error());
315  return;
316  }
317  else
318  {
319  printf("FiffStreamClient (assigned ID %d) accepted from\n\tIP:\t%s\n\tPort:\t%d\n\n",
320  m_iDataClientId,
321  QHostAddress(t_qTcpSocket.peerAddress()).toString().toUtf8().constData(),
322  t_qTcpSocket.peerPort());
323  }
324 
325  FiffStream t_FiffStreamIn(&t_qTcpSocket);
326 
327 // int i = 0;
328  while(t_qTcpSocket.state() != QAbstractSocket::UnconnectedState && m_bIsRunning)
329  {
330  //
331  // Write available data
332  //
333  m_qMutex.lock();
334  qint32 t_iBlockSize = m_qSendBlock.size();
335 // qDebug() << "data available" << t_iBlockSize;
336  if(t_iBlockSize > 0)
337  {
338  qint32 t_iBytesWritten = t_qTcpSocket.write(m_qSendBlock);
339 // qDebug() << ++i<< "[wrote bytes] " << t_iBytesWritten;
340  t_qTcpSocket.waitForBytesWritten();
341  if(t_iBytesWritten == t_iBlockSize)
342  {
343  m_qSendBlock.clear();
344  }
345  else
346  {
347  //we have to store bytes which were not written to the socket, due to writing limit
348  //m_qSendBlock = m_qSendBlock.mid(t_iBytesWritten, t_iBlockSize-t_iBytesWritten);
349  m_qSendBlock.remove(0,t_iBytesWritten); //higher performance then mid
350  }
351  }
352  m_qMutex.unlock();
353 
354  //
355  // Read: Wait 10ms for incomming tag header, read and continue
356  //
357  t_qTcpSocket.waitForReadyRead(10);
358 
359  if (t_qTcpSocket.bytesAvailable() >= (int)sizeof(qint32)*4)
360  {
361 // qDebug() << "goes to read bytes " ;
362  FiffTag::SPtr t_pTag;
363  FiffTag::read_tag_info(&t_FiffStreamIn, t_pTag, false);
364 
365  //
366  // wait until tag size data are available and read the data
367  //
368  while (t_qTcpSocket.bytesAvailable() < t_pTag->size())
369  {
370  t_qTcpSocket.waitForReadyRead(10);
371  }
372  FiffTag::read_tag_data(&t_FiffStreamIn, t_pTag);
373 
374  //
375  // Parse the tag
376  //
377  if(t_pTag->kind == FIFF_MNE_RT_COMMAND)
378  {
379  parseCommand(t_pTag);
380  }
381  }
382  }
383 
384  t_qTcpSocket.disconnectFromHost();
385  if(t_qTcpSocket.state() != QAbstractSocket::UnconnectedState)
386  t_qTcpSocket.waitForDisconnected();
387 }
#define FIFF_MNE_RT_CLIENT_ID
FIFF measurement file information.
Definition: fiff_info.h:96
static bool read_tag_data(FiffStream *p_pStream, FiffTag::SPtr &p_pTag, qint64 pos=-1)
Definition: fiff_tag.cpp:109
static bool read_tag_info(FiffStream *p_pStream, FiffTag::SPtr &p_pTag, bool p_bDoSkip=true)
Definition: fiff_tag.cpp:137
The FiffStreamServer class provides.
QSharedPointer< FiffTag > SPtr
Definition: fiff_tag.h:166
Fiff constants.
void writeToStream(FiffStream *p_pStream)
Definition: fiff_info.cpp:349
Contains mne rt constants.
implementation of the FiffStreamServer Class.
#define MNE_RT_GET_CLIENT_ID
implementation of the FiffStreamThread Class.
#define FIFF_MNE_RT_COMMAND
Definition: fiff.h:98
#define FIFF_DATA_BUFFER
FiffTag class declaration, which provides fiff tag I/O and processing methods.
FIFF File I/O routines.
Definition: fiff_stream.h:129
#define MNE_RT_SET_CLIENT_ALIAS
IOUtils class declaration.