CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxVideoImplService.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 #include "cxVideoImplService.h"
13 
14 #include <ctkPluginContext.h>
15 #include "boost/bind.hpp"
16 #include "cxData.h"
17 
19 
21 #include "cxVideoConnection.h"
22 #include "cxBasicVideoSource.h"
23 #include "cxTypeConversions.h"
24 #include "cxTrackingService.h"
25 #include "cxVideoServiceBackend.h"
26 
27 #include "cxLogger.h"
28 #include "cxTrackingServiceProxy.h"
30 #include "cxFileHelpers.h"
31 #include "cxSpaceProviderImpl.h"
32 #include "cxVideoServiceBackend.h"
33 #include "cxStreamerService.h"
34 #include "cxStreamerServiceProxy.h"
35 #include "cxStreamerServiceNull.h"
36 #include "cxNullDeleter.h"
38 
39 namespace cx
40 {
41 
42 VideoImplService::VideoImplService(ctkPluginContext *context) :
43  mContext(context )
44 {
45  VideoServiceBackendPtr videoBackend;
46 
49  SpaceProviderPtr spaceProvider;
50  spaceProvider.reset(new cx::SpaceProviderImpl(tracking, pasm));
52  mBackend = VideoServiceBackend::create(pasm,tracking, spaceProvider, filemanager, context);
53 
54  mEmptyVideoSource.reset(new BasicVideoSource());
55  mVideoConnection.reset(new VideoConnection(mBackend));
56  mActiveVideoSource = mEmptyVideoSource;
57 
58  connect(mVideoConnection.get(), &VideoConnection::connected, this, &VideoImplService::autoSelectActiveVideoSource);
59  connect(mVideoConnection.get(), &VideoConnection::videoSourcesChanged, this, &VideoImplService::autoSelectActiveVideoSource);
60  connect(mVideoConnection.get(), &VideoConnection::fps, this, &VideoImplService::fpsSlot);
61  connect(mBackend->tracking().get(), &TrackingService::activeToolChanged, this, &VideoImplService::autoSelectActiveVideoSource);
62  connect(mVideoConnection.get(), &VideoConnection::connected, this, &VideoImplService::connected);
63 
64  this->initServiceListener();
65 }
66 
68 {
69  // Disconnect before deleting videoconnection:
70  // The VideoConnection might emit events AND call processevents, causing
71  // recursive calls back to this during deletion.
72  disconnect(mVideoConnection.get(), &VideoConnection::connected, this, &VideoImplService::autoSelectActiveVideoSource);
73  disconnect(mVideoConnection.get(), &VideoConnection::videoSourcesChanged, this, &VideoImplService::autoSelectActiveVideoSource);
74  disconnect(mVideoConnection.get(), &VideoConnection::fps, this, &VideoImplService::fpsSlot);
75  disconnect(mBackend->tracking().get(), &TrackingService::activeToolChanged, this, &VideoImplService::autoSelectActiveVideoSource);
76  disconnect(mVideoConnection.get(), &VideoConnection::connected, this, &VideoImplService::connected);
77 
78  mVideoConnection.reset();
79 }
80 
82 {
83  QList<StreamerServicePtr> services = this->getStreamerServices();
84  foreach(StreamerServicePtr service, services)
85  {
86  if (service->getType()==uid)
87  {
88  return service;
89  }
90  }
92 }
93 
94 QList<StreamerServicePtr> VideoImplService::getStreamerServices()
95 {
96  QList<StreamerServicePtr> retval;
97  QList<StreamerService *> services = mStreamerServiceListener->getServices();
98  foreach(StreamerService* service, services)
99  {
100  if(service)
101  {
102  StreamerServicePtr temp(new StreamerServiceProxy(mBackend->mContext, service->getName()), null_deleter());
103  retval.append(temp);
104  }
105  }
106  return retval;
107 }
108 
110 {
111  return false;
112 }
113 
114 void VideoImplService::autoSelectActiveVideoSource()
115 {
116  VideoSourcePtr suggestion = this->getGuessForActiveVideoSource(mActiveVideoSource);
117  this->setActiveVideoSource(suggestion->getUid());
118 }
119 
121 {
122  mActiveVideoSource = mEmptyVideoSource;
123 
124  std::vector<VideoSourcePtr> sources = this->getVideoSources();
125  for (unsigned i=0; i<sources.size(); ++i)
126  if (sources[i]->getUid()==uid)
127  mActiveVideoSource = sources[i];
128 
129  // set active stream in all probes if stream is present:
130  TrackingService::ToolMap tools = mBackend->tracking()->getTools();
131  for (TrackingService::ToolMap::iterator iter=tools.begin(); iter!=tools.end(); ++iter)
132  {
133  ProbePtr probe = iter->second->getProbe();
134  if (!probe)
135  continue;
136  if (!probe->getAvailableVideoSources().count(uid)){
137  report("No active streams");
138  continue;
139  }
140  probe->setActiveStream(uid);
141  }
142 
144 }
145 
146 VideoSourcePtr VideoImplService::getGuessForActiveVideoSource(VideoSourcePtr old)
147 {
148 
149  if(old && old->getUid().contains("playback"))
150  return old;
151 
152  QStringList nameFilters;
153  nameFilters << "TissueAngio.fts" << "TissueFlow.fts" << "ScanConverted.fts";
154  // ask for playback stream:
155  foreach(USAcquisitionVideoPlaybackPtr uSAcquisitionVideoPlayback,mUSAcquisitionVideoPlaybacks)
156  {
157  if (uSAcquisitionVideoPlayback->isActive() && nameFilters.contains(uSAcquisitionVideoPlayback->getType()) )
158  return uSAcquisitionVideoPlayback->getVideoSource();
159  }
160 
161  // ask for playback stream:
162  foreach(USAcquisitionVideoPlaybackPtr uSAcquisitionVideoPlayback,mUSAcquisitionVideoPlaybacks)
163  {
164  if (uSAcquisitionVideoPlayback->isActive())
165  return uSAcquisitionVideoPlayback->getVideoSource();
166  }
167 
168  // ask for active stream in first probe:
169  ToolPtr tool = mBackend->tracking()->getFirstProbe();
170  if (tool && tool->getProbe() && tool->getProbe()->getRTSource())
171  {
172  // keep existing if present
173  if (old)
174  {
175  if (tool->getProbe()->getAvailableVideoSources().count(old->getUid()))
176  return old;
177  }
178 
179  return tool->getProbe()->getRTSource();
180  }
181 
182  std::vector<VideoSourcePtr> allSources = this->getVideoSources();
183  // keep existing if present
184  if (old)
185  {
186  if (std::count(allSources.begin(), allSources.end(), old))
187  return old;
188  }
189  // ask for anything
190  if (!allSources.empty())
191  return allSources.front();
192 
193  // give up: return empty
194  return mEmptyVideoSource;
195 }
196 
198 {
199  return mActiveVideoSource;
200 }
201 
203 {
204 
205  QStringList res = getAbsolutePathToFiles( mBackend->getDataManager()->getActivePatientFolder() + "/US_Acq/",QStringList("*.fts"), true);
206  QSet<QString> types;
207  foreach (const QString &acq, res)
208  {
209  types.insert(acq.split("_").back());
210  }
211  USAcquisitionVideoPlaybackPtr tempUSAcquisitionVideoPlayback;
212  foreach(const QString type, types.toList() ){
213 
214  tempUSAcquisitionVideoPlayback.reset(new USAcquisitionVideoPlayback(mBackend,type));
215  mUSAcquisitionVideoPlaybacks.push_back(tempUSAcquisitionVideoPlayback );
216 
217 
218  mUSAcquisitionVideoPlaybacks.back()->setTime(controller);
219 
220  VideoSourcePtr playbackSource = mUSAcquisitionVideoPlaybacks.back()->getVideoSource();
221  TrackingService::ToolMap tools = mBackend->tracking()->getTools();
222  for (TrackingService::ToolMap::iterator iter=tools.begin(); iter!=tools.end(); ++iter)
223  {
224  ProbePtr probe = iter->second->getProbe();
225  if (!probe)
226  continue;
227  if (mUSAcquisitionVideoPlaybacks.back()->isActive())
228  probe->setRTSource(playbackSource);
229  else
230  probe->removeRTSource(playbackSource);
231  }
232  mUSAcquisitionVideoPlaybacks.back()->setRoot(mBackend->getDataManager()->getActivePatientFolder() + "/US_Acq/");
233  }
234  this->autoSelectActiveVideoSource();
235 }
236 
237 std::vector<VideoSourcePtr> VideoImplService::getVideoSources()
238 {
239  std::vector<VideoSourcePtr> retval = mVideoConnection->getVideoSources();
240  foreach(USAcquisitionVideoPlaybackPtr uSAcquisitionVideoPlayback,mUSAcquisitionVideoPlaybacks)
241  {
242  if (uSAcquisitionVideoPlayback->isActive())
243  retval.push_back(uSAcquisitionVideoPlayback->getVideoSource());
244  }
245  return retval;
246 }
247 
248 void VideoImplService::fpsSlot(QString source, int val)
249 {
250  if (source==mActiveVideoSource->getUid())
251  emit fps(val);
252 }
253 
255 {
256  if (mVideoConnection->isConnected())
257  return;
258 
259  //StreamerService* service = this->getStreamerService(mConnectionMethod);
260  StreamerServicePtr service = this->getStreamerService(mConnectionMethod);
261  if (!service)
262  {
263  reportError(QString("Found no streamer for method [%1]").arg(mConnectionMethod));
264  return;
265  }
266 
267  mVideoConnection->runDirectLinkClient(service);
268 }
269 
271 {
272  mVideoConnection->disconnectServer();
273 }
274 
276 {
277  return mVideoConnection->isConnected();
278 }
279 
281 {
282  return mConnectionMethod;
283 }
284 
285 void VideoImplService::setConnectionMethod(QString connectionMethod)
286 {
287  if (mConnectionMethod == connectionMethod)
288  return;
289 
290  if(connectionMethod.isEmpty())
291  {
292  reportWarning("Trying to set connection method to empty string");
293  return;
294  }
295 
296  mConnectionMethod = connectionMethod;
298 }
299 
300 std::vector<TimelineEvent> VideoImplService::getPlaybackEvents()
301 {
302  std::vector<TimelineEvent> retval;
303  foreach(USAcquisitionVideoPlaybackPtr uSAcquisitionVideoPlayback,mUSAcquisitionVideoPlaybacks)
304  {
305  std::vector<TimelineEvent> events = uSAcquisitionVideoPlayback->getEvents();
306  retval.reserve(retval.size() + events.size());
307  retval.insert( retval.end(), events.begin(), events.end() );
308  }
309 
310  return retval;
311 }
312 
313 void VideoImplService::initServiceListener()
314 {
315  mStreamerServiceListener.reset(new ServiceTrackerListener<StreamerService>(
316  mBackend->mContext,
317  boost::bind(&VideoImplService::onStreamerServiceAdded, this, _1),
318  boost::function<void (StreamerService*)>(),
319  boost::bind(&VideoImplService::onStreamerServiceRemoved, this, _1)
320  ));
321  mStreamerServiceListener->open();
322 
323 }
324 
325 void VideoImplService::onStreamerServiceAdded(StreamerService* service)
326 {
327  if (mConnectionMethod.isEmpty())
328  mConnectionMethod = service->getType();
329 
330  emit StreamerServiceAdded(service);
331 }
332 
333 void VideoImplService::onStreamerServiceRemoved(StreamerService *service)
334 {
335  emit StreamerServiceRemoved(service);
336 }
337 
338 
339 } /* namespace cx */
bool connected(bool)
boost::shared_ptr< class SpaceProvider > SpaceProviderPtr
boost::shared_ptr< class FileManagerService > FileManagerServicePtr
virtual QString getConnectionMethod()
void reportError(QString msg)
Definition: cxLogger.cpp:71
virtual void setPlaybackMode(PlaybackTimePtr controller)
void connected(bool on)
virtual VideoSourcePtr getActiveVideoSource()
virtual QString getType() const =0
void StreamerServiceRemoved(StreamerService *service)
boost::shared_ptr< class TrackingService > TrackingServicePtr
Proxy for StreamerServices.
VideoImplService(ctkPluginContext *context)
virtual std::vector< TimelineEvent > getPlaybackEvents()
void StreamerServiceAdded(StreamerService *service)
virtual bool isConnected() const
Handler for playback of US image data from a US recording session.
boost::shared_ptr< class VideoServiceBackend > VideoServiceBackendPtr
static TrackingServicePtr create(ctkPluginContext *pluginContext)
static VideoServiceBackendPtr create(PatientModelServicePtr dataManager, TrackingServicePtr trackingService, SpaceProviderPtr spaceProvider, FileManagerServicePtr filemanager, ctkPluginContext *context)
boost::shared_ptr< class PlaybackTime > PlaybackTimePtr
boost::shared_ptr< Probe > ProbePtr
Definition: cxProbe.h:72
static PatientModelServicePtr create(ctkPluginContext *pluginContext)
void activeToolChanged(const QString &uId)
void connectionMethodChanged()
void reportWarning(QString msg)
Definition: cxLogger.cpp:70
static FileManagerServicePtr create(ctkPluginContext *context)
boost::shared_ptr< USAcquisitionVideoPlayback > USAcquisitionVideoPlaybackPtr
boost::shared_ptr< class PatientModelService > PatientModelServicePtr
boost::shared_ptr< class VideoSource > VideoSourcePtr
virtual QString getName()=0
virtual StreamerServicePtr getStreamerService(QString uid)
virtual void setConnectionMethod(QString connectionMethod)
virtual std::vector< VideoSourcePtr > getVideoSources()
VideoSource controlled by a vtkImageData.
Helper class for listening to services being added, modified and removed.
std::map< QString, ToolPtr > ToolMap
QStringList getAbsolutePathToFiles(QString path, QStringList nameFilters, bool includeSubDirs)
void report(QString msg)
Definition: cxLogger.cpp:69
Represent one video grabber connection.
boost::shared_ptr< class StreamerService > StreamerServicePtr
Abstract class. Interface to Streamers.
virtual void setActiveVideoSource(QString uid)
virtual void closeConnection()
virtual QList< StreamerServicePtr > getStreamerServices()
void activeVideoSourceChanged()
void fps(QString source, int fps)
Null implementation of the StreamerService.
Namespace for all CustusX production code.
boost::shared_ptr< class Tool > ToolPtr