00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "stream.h"
00037
00038 #include "gentl_wrapper.h"
00039 #include "exception.h"
00040 #include "cport.h"
00041
00042 #include <iostream>
00043
00044 namespace rcg
00045 {
00046
00047 Stream::Stream(const std::shared_ptr<Device> &_parent,
00048 const std::shared_ptr<const GenTLWrapper> &_gentl, const char *_id) :
00049 buffer(_gentl, this)
00050 {
00051 parent=_parent;
00052 gentl=_gentl;
00053 id=_id;
00054
00055 n_open=0;
00056 stream=0;
00057 event=0;
00058 bn=0;
00059 }
00060
00061 Stream::~Stream()
00062 {
00063 try
00064 {
00065 stopStreaming();
00066
00067 if (stream != 0)
00068 {
00069 gentl->DSClose(stream);
00070 }
00071 }
00072 catch (...)
00073 { }
00074 }
00075
00076 std::shared_ptr<Device> Stream::getParent() const
00077 {
00078 return parent;
00079 }
00080
00081 const std::string &Stream::getID() const
00082 {
00083 return id;
00084 }
00085
00086 void Stream::open()
00087 {
00088 if (n_open == 0)
00089 {
00090 if (parent->getHandle() != 0)
00091 {
00092 if (gentl->DevOpenDataStream(parent->getHandle(), id.c_str(), &stream) !=
00093 GenTL::GC_ERR_SUCCESS)
00094 {
00095 throw GenTLException("Stream::open()", gentl);
00096 }
00097 }
00098 else
00099 {
00100 throw GenTLException("Stream::open(): Device must be opened before open before opening a stream");
00101 }
00102 }
00103
00104 n_open++;
00105 }
00106
00107 void Stream::close()
00108 {
00109 if (n_open > 0)
00110 {
00111 n_open--;
00112 }
00113
00114 if (n_open == 0)
00115 {
00116 stopStreaming();
00117 gentl->DSClose(stream);
00118 stream=0;
00119
00120 nodemap=0;
00121 cport=0;
00122 }
00123 }
00124
00125 void Stream::startStreaming(int na)
00126 {
00127 buffer.setHandle(0);
00128
00129 if (stream == 0)
00130 {
00131 throw GenTLException("Stream::startStreaming(): Stream is not open");
00132 }
00133
00134
00135
00136 if (bn > 0)
00137 {
00138 stopStreaming();
00139 }
00140
00141
00142
00143 size_t size=0;
00144 if (getDefinesPayloadsize())
00145 {
00146 size=getPayloadSize();
00147 }
00148 else
00149 {
00150 std::shared_ptr<GenApi::CNodeMapRef> nodemap=parent->getRemoteNodeMap();
00151 GenApi::IInteger *p=dynamic_cast<GenApi::IInteger *>(nodemap->_GetNode("PayloadSize"));
00152
00153 if (GenApi::IsReadable(p))
00154 {
00155 size=p->GetValue();
00156 }
00157 }
00158
00159
00160
00161 bool err=false;
00162
00163 bn=std::max(static_cast<size_t>(8), getBufAnnounceMin());
00164 for (size_t i=0; i<bn; i++)
00165 {
00166 GenTL::BUFFER_HANDLE p=0;
00167
00168 if (gentl->DSAllocAndAnnounceBuffer(stream, size, 0, &p) != GenTL::GC_ERR_SUCCESS)
00169 {
00170 err=true;
00171 break;
00172 }
00173
00174 if (!err && gentl->DSQueueBuffer(stream, p) != GenTL::GC_ERR_SUCCESS)
00175 {
00176 err=true;
00177 break;
00178 }
00179 }
00180
00181
00182
00183 if (!err && gentl->GCRegisterEvent(stream, GenTL::EVENT_NEW_BUFFER, &event) !=
00184 GenTL::GC_ERR_SUCCESS)
00185 {
00186 err=true;
00187 }
00188
00189
00190
00191 uint64_t n=GENTL_INFINITE;
00192
00193 if (na > 0)
00194 {
00195 n=static_cast<uint64_t>(na);
00196 }
00197
00198 if (!err && gentl->DSStartAcquisition(stream, GenTL::ACQ_START_FLAGS_DEFAULT, n) !=
00199 GenTL::GC_ERR_SUCCESS)
00200 {
00201 gentl->GCUnregisterEvent(stream, GenTL::EVENT_NEW_BUFFER);
00202 err=true;
00203 }
00204
00205 if (!err)
00206 {
00207 GenApi::CCommandPtr start=parent->getRemoteNodeMap()->_GetNode("AcquisitionStart");
00208 start->Execute();
00209 }
00210
00211
00212
00213 if (err)
00214 {
00215 gentl->DSFlushQueue(stream, GenTL::ACQ_QUEUE_ALL_DISCARD);
00216
00217 GenTL::BUFFER_HANDLE p=0;
00218 while (gentl->DSGetBufferID(stream, 0, &p) == GenTL::GC_ERR_SUCCESS)
00219 {
00220 gentl->DSRevokeBuffer(stream, p, 0, 0);
00221 }
00222
00223 throw GenTLException("Stream::startStreaming()", gentl);
00224 }
00225 }
00226
00227 void Stream::stopStreaming()
00228 {
00229 if (bn > 0)
00230 {
00231 buffer.setHandle(0);
00232
00233
00234
00235 GenApi::CCommandPtr stop=parent->getRemoteNodeMap()->_GetNode("AcquisitionStop");
00236 stop->Execute();
00237
00238 gentl->DSStopAcquisition(stream, GenTL::ACQ_STOP_FLAGS_DEFAULT);
00239 gentl->GCUnregisterEvent(stream, GenTL::EVENT_NEW_BUFFER);
00240 gentl->DSFlushQueue(stream, GenTL::ACQ_QUEUE_ALL_DISCARD);
00241
00242
00243
00244 GenTL::BUFFER_HANDLE p=0;
00245 while (gentl->DSGetBufferID(stream, 0, &p) == GenTL::GC_ERR_SUCCESS)
00246 {
00247 gentl->DSRevokeBuffer(stream, p, 0, 0);
00248 }
00249
00250 event=0;
00251 bn=0;
00252 }
00253 }
00254
00255 const Buffer *Stream::grab(int64_t _timeout)
00256 {
00257 uint64_t timeout=GENTL_INFINITE;
00258 if (_timeout >= 0)
00259 {
00260 timeout=_timeout;
00261 }
00262
00263
00264
00265 if (bn == 0 && event == 0)
00266 {
00267 throw GenTLException("Streaming::grab(): Streaming not started");
00268 }
00269
00270
00271
00272 if (buffer.getHandle() != 0)
00273 {
00274 if (gentl->DSQueueBuffer(stream, buffer.getHandle()) != GenTL::GC_ERR_SUCCESS)
00275 {
00276 buffer.setHandle(0);
00277 throw GenTLException("Stream::grab()", gentl);
00278 }
00279
00280 buffer.setHandle(0);
00281 }
00282
00283
00284
00285 GenTL::EVENT_NEW_BUFFER_DATA data;
00286 size_t size=sizeof(GenTL::EVENT_NEW_BUFFER_DATA);
00287 memset(&data, 0, size);
00288
00289 GenTL::GC_ERROR err=gentl->EventGetData(event, &data, &size, timeout);
00290
00291
00292
00293
00294 if (err == GenTL::GC_ERR_ABORT || err == GenTL::GC_ERR_TIMEOUT)
00295 {
00296 return 0;
00297 }
00298 else if (err != GenTL::GC_ERR_SUCCESS)
00299 {
00300 throw GenTLException("Stream::grab()", gentl);
00301 }
00302
00303
00304
00305 buffer.setHandle(data.BufferHandle);
00306
00307 return &buffer;
00308 }
00309
00310 namespace
00311 {
00312
00313 template<class T> inline T getStreamValue(const std::shared_ptr<const GenTLWrapper> &gentl,
00314 void *stream, GenTL::STREAM_INFO_CMD cmd)
00315 {
00316 T ret=0;
00317
00318 GenTL::INFO_DATATYPE type;
00319 size_t size=sizeof(T);
00320
00321 if (stream != 0)
00322 {
00323 gentl->DSGetInfo(stream, cmd, &type, &ret, &size);
00324 }
00325
00326 return ret;
00327 }
00328
00329 inline bool getStreamBool(const std::shared_ptr<const GenTLWrapper> &gentl,
00330 void *stream, GenTL::STREAM_INFO_CMD cmd)
00331 {
00332 bool8_t ret=0;
00333
00334 GenTL::INFO_DATATYPE type;
00335 size_t size=sizeof(ret);
00336
00337 if (stream != 0)
00338 {
00339 gentl->DSGetInfo(stream, cmd, &type, &ret, &size);
00340 }
00341
00342 return ret != 0;
00343 }
00344
00345 }
00346
00347 uint64_t Stream::getNumDelivered() const
00348 {
00349 return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_DELIVERED);
00350 }
00351
00352 uint64_t Stream::getNumUnderrun() const
00353 {
00354 return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_UNDERRUN);
00355 }
00356
00357 size_t Stream::getNumAnnounced() const
00358 {
00359 return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_ANNOUNCED);
00360 }
00361
00362 size_t Stream::getNumQueued() const
00363 {
00364 return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_QUEUED);
00365 }
00366
00367 size_t Stream::getNumAwaitDelivery() const
00368 {
00369 return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_AWAIT_DELIVERY);
00370 }
00371
00372 uint64_t Stream::getNumStarted() const
00373 {
00374 return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_STARTED);
00375 }
00376
00377 size_t Stream::getPayloadSize() const
00378 {
00379 return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_PAYLOAD_SIZE);
00380 }
00381
00382 bool Stream::getIsGrabbing() const
00383 {
00384 return getStreamBool(gentl, stream, GenTL::STREAM_INFO_IS_GRABBING);
00385 }
00386
00387 bool Stream::getDefinesPayloadsize() const
00388 {
00389 return getStreamBool(gentl, stream, GenTL::STREAM_INFO_DEFINES_PAYLOADSIZE);
00390 }
00391
00392 std::string Stream::getTLType() const
00393 {
00394 std::string ret;
00395
00396 GenTL::INFO_DATATYPE type;
00397 char tmp[1024]="";
00398 size_t size=sizeof(tmp);
00399
00400 if (stream != 0)
00401 {
00402 if (gentl->DSGetInfo(stream, GenTL::STREAM_INFO_TLTYPE, &type, &ret, &size) ==
00403 GenTL::GC_ERR_SUCCESS)
00404 {
00405 if (type == GenTL::INFO_DATATYPE_STRING)
00406 {
00407 ret=tmp;
00408 }
00409 }
00410 }
00411
00412 return ret;
00413 }
00414
00415 size_t Stream::getNumChunksMax() const
00416 {
00417 return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_CHUNKS_MAX);
00418 }
00419
00420 size_t Stream::getBufAnnounceMin() const
00421 {
00422 return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_BUF_ANNOUNCE_MIN);
00423 }
00424
00425 size_t Stream::getBufAlignment() const
00426 {
00427 return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_BUF_ALIGNMENT);
00428 }
00429
00430 std::shared_ptr<GenApi::CNodeMapRef> Stream::getNodeMap()
00431 {
00432 if (stream != 0 && !nodemap)
00433 {
00434 cport=std::shared_ptr<CPort>(new CPort(gentl, &stream));
00435 nodemap=allocNodeMap(gentl, stream, cport.get());
00436 }
00437
00438 return nodemap;
00439 }
00440
00441 void *Stream::getHandle() const
00442 {
00443 return stream;
00444 }
00445
00446 }