Fraxinus  17.12-rc2
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) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
33 #include "cxVideoImplService.h"
34 
35 #include <ctkPluginContext.h>
36 #include "boost/bind.hpp"
37 #include "cxData.h"
38 
40 
42 #include "cxVideoConnection.h"
43 #include "cxBasicVideoSource.h"
44 #include "cxTypeConversions.h"
45 #include "cxTrackingService.h"
46 #include "cxVideoServiceBackend.h"
47 
48 #include "cxLogger.h"
49 #include "cxTrackingServiceProxy.h"
51 #include "cxFileHelpers.h"
52 #include "cxSpaceProviderImpl.h"
53 #include "cxVideoServiceBackend.h"
54 #include "cxStreamerService.h"
55 #include "cxStreamerServiceProxy.h"
56 #include "cxStreamerServiceNull.h"
57 #include "cxNullDeleter.h"
58 
59 namespace cx
60 {
61 
62 VideoImplService::VideoImplService(ctkPluginContext *context) :
63  mContext(context )
64 {
65  VideoServiceBackendPtr videoBackend;
66 
69  SpaceProviderPtr spaceProvider;
70  spaceProvider.reset(new cx::SpaceProviderImpl(tracking, pasm));
71  mBackend = VideoServiceBackend::create(pasm,tracking, spaceProvider, context);
72 
73  mEmptyVideoSource.reset(new BasicVideoSource());
74  mVideoConnection.reset(new VideoConnection(mBackend));
75  mActiveVideoSource = mEmptyVideoSource;
76 
77  connect(mVideoConnection.get(), &VideoConnection::connected, this, &VideoImplService::autoSelectActiveVideoSource);
78  connect(mVideoConnection.get(), &VideoConnection::videoSourcesChanged, this, &VideoImplService::autoSelectActiveVideoSource);
79  connect(mVideoConnection.get(), &VideoConnection::fps, this, &VideoImplService::fpsSlot);
80  connect(mBackend->tracking().get(), &TrackingService::activeToolChanged, this, &VideoImplService::autoSelectActiveVideoSource);
81  connect(mVideoConnection.get(), &VideoConnection::connected, this, &VideoImplService::connected);
82 
83  this->initServiceListener();
84 }
85 
87 {
88  // Disconnect before deleting videoconnection:
89  // The VideoConnection might emit events AND call processevents, causing
90  // recursive calls back to this during deletion.
91  disconnect(mVideoConnection.get(), &VideoConnection::connected, this, &VideoImplService::autoSelectActiveVideoSource);
92  disconnect(mVideoConnection.get(), &VideoConnection::videoSourcesChanged, this, &VideoImplService::autoSelectActiveVideoSource);
93  disconnect(mVideoConnection.get(), &VideoConnection::fps, this, &VideoImplService::fpsSlot);
94  disconnect(mBackend->tracking().get(), &TrackingService::activeToolChanged, this, &VideoImplService::autoSelectActiveVideoSource);
95  disconnect(mVideoConnection.get(), &VideoConnection::connected, this, &VideoImplService::connected);
96 
97  mVideoConnection.reset();
98 }
99 
101 {
102  QList<StreamerServicePtr> services = this->getStreamerServices();
103  foreach(StreamerServicePtr service, services)
104  {
105  if (service->getType()==uid)
106  {
107  return service;
108  }
109  }
111 }
112 
113 QList<StreamerServicePtr> VideoImplService::getStreamerServices()
114 {
115  QList<StreamerServicePtr> retval;
116  QList<StreamerService *> services = mStreamerServiceListener->getServices();
117  foreach(StreamerService* service, services)
118  {
119  if(service)
120  {
121  StreamerServicePtr temp(new StreamerServiceProxy(mBackend->mContext, service->getName()), null_deleter());
122  retval.append(temp);
123  }
124  }
125  return retval;
126 }
127 
129 {
130  return false;
131 }
132 
133 void VideoImplService::autoSelectActiveVideoSource()
134 {
135  VideoSourcePtr suggestion = this->getGuessForActiveVideoSource(mActiveVideoSource);
136  this->setActiveVideoSource(suggestion->getUid());
137 }
138 
140 {
141  mActiveVideoSource = mEmptyVideoSource;
142 
143  std::vector<VideoSourcePtr> sources = this->getVideoSources();
144  for (unsigned i=0; i<sources.size(); ++i)
145  if (sources[i]->getUid()==uid)
146  mActiveVideoSource = sources[i];
147 
148  // set active stream in all probes if stream is present:
149  TrackingService::ToolMap tools = mBackend->tracking()->getTools();
150  for (TrackingService::ToolMap::iterator iter=tools.begin(); iter!=tools.end(); ++iter)
151  {
152  ProbePtr probe = iter->second->getProbe();
153  if (!probe)
154  continue;
155  if (!probe->getAvailableVideoSources().count(uid)){
156  report("No active streams");
157  continue;
158  }
159  probe->setActiveStream(uid);
160  }
161 
163 }
164 
165 VideoSourcePtr VideoImplService::getGuessForActiveVideoSource(VideoSourcePtr old)
166 {
167 
168  if(old && old->getUid().contains("playback"))
169  return old;
170 
171  QStringList nameFilters;
172  nameFilters << "TissueAngio.fts" << "TissueFlow.fts" << "ScanConverted.fts";
173  // ask for playback stream:
174  foreach(USAcquisitionVideoPlaybackPtr uSAcquisitionVideoPlayback,mUSAcquisitionVideoPlaybacks)
175  {
176  if (uSAcquisitionVideoPlayback->isActive() && nameFilters.contains(uSAcquisitionVideoPlayback->getType()) )
177  return uSAcquisitionVideoPlayback->getVideoSource();
178  }
179 
180  // ask for playback stream:
181  foreach(USAcquisitionVideoPlaybackPtr uSAcquisitionVideoPlayback,mUSAcquisitionVideoPlaybacks)
182  {
183  if (uSAcquisitionVideoPlayback->isActive())
184  return uSAcquisitionVideoPlayback->getVideoSource();
185  }
186 
187  // ask for active stream in first probe:
188  ToolPtr tool = mBackend->tracking()->getFirstProbe();
189  if (tool && tool->getProbe() && tool->getProbe()->getRTSource())
190  {
191  // keep existing if present
192  if (old)
193  {
194  if (tool->getProbe()->getAvailableVideoSources().count(old->getUid()))
195  return old;
196  }
197 
198  return tool->getProbe()->getRTSource();
199  }
200 
201  std::vector<VideoSourcePtr> allSources = this->getVideoSources();
202  // keep existing if present
203  if (old)
204  {
205  if (std::count(allSources.begin(), allSources.end(), old))
206  return old;
207  }
208  // ask for anything
209  if (!allSources.empty())
210  return allSources.front();
211 
212  // give up: return empty
213  return mEmptyVideoSource;
214 }
215 
217 {
218  return mActiveVideoSource;
219 }
220 
222 {
223 
224  QStringList res = getAbsolutePathToFiles( mBackend->getDataManager()->getActivePatientFolder() + "/US_Acq/",QStringList("*.fts"), true);
225  QSet<QString> types;
226  foreach (const QString &acq, res)
227  {
228  types.insert(acq.split("_").back());
229  }
230  USAcquisitionVideoPlaybackPtr tempUSAcquisitionVideoPlayback;
231  foreach(const QString type, types.toList() ){
232 
233  tempUSAcquisitionVideoPlayback.reset(new USAcquisitionVideoPlayback(mBackend,type));
234  mUSAcquisitionVideoPlaybacks.push_back(tempUSAcquisitionVideoPlayback );
235 
236 
237  mUSAcquisitionVideoPlaybacks.back()->setTime(controller);
238 
239  VideoSourcePtr playbackSource = mUSAcquisitionVideoPlaybacks.back()->getVideoSource();
240  TrackingService::ToolMap tools = mBackend->tracking()->getTools();
241  for (TrackingService::ToolMap::iterator iter=tools.begin(); iter!=tools.end(); ++iter)
242  {
243  ProbePtr probe = iter->second->getProbe();
244  if (!probe)
245  continue;
246  if (mUSAcquisitionVideoPlaybacks.back()->isActive())
247  probe->setRTSource(playbackSource);
248  else
249  probe->removeRTSource(playbackSource);
250  }
251  mUSAcquisitionVideoPlaybacks.back()->setRoot(mBackend->getDataManager()->getActivePatientFolder() + "/US_Acq/");
252  }
253  this->autoSelectActiveVideoSource();
254 }
255 
256 std::vector<VideoSourcePtr> VideoImplService::getVideoSources()
257 {
258  std::vector<VideoSourcePtr> retval = mVideoConnection->getVideoSources();
259  foreach(USAcquisitionVideoPlaybackPtr uSAcquisitionVideoPlayback,mUSAcquisitionVideoPlaybacks)
260  {
261  if (uSAcquisitionVideoPlayback->isActive())
262  retval.push_back(uSAcquisitionVideoPlayback->getVideoSource());
263  }
264  return retval;
265 }
266 
267 void VideoImplService::fpsSlot(QString source, int val)
268 {
269  if (source==mActiveVideoSource->getUid())
270  emit fps(val);
271 }
272 
274 {
275  if (mVideoConnection->isConnected())
276  return;
277 
278  //StreamerService* service = this->getStreamerService(mConnectionMethod);
279  StreamerServicePtr service = this->getStreamerService(mConnectionMethod);
280  if (!service)
281  {
282  reportError(QString("Found no streamer for method [%1]").arg(mConnectionMethod));
283  return;
284  }
285 
286  mVideoConnection->runDirectLinkClient(service);
287 }
288 
290 {
291  mVideoConnection->disconnectServer();
292 }
293 
295 {
296  return mVideoConnection->isConnected();
297 }
298 
300 {
301  return mConnectionMethod;
302 }
303 
304 void VideoImplService::setConnectionMethod(QString connectionMethod)
305 {
306  if (mConnectionMethod == connectionMethod)
307  return;
308 
309  if(connectionMethod.isEmpty())
310  {
311  reportWarning("Trying to set connection method to empty string");
312  return;
313  }
314 
315  mConnectionMethod = connectionMethod;
316 // emit connectionMethodChanged();
317 }
318 
319 std::vector<TimelineEvent> VideoImplService::getPlaybackEvents()
320 {
321  std::vector<TimelineEvent> retval;
322  foreach(USAcquisitionVideoPlaybackPtr uSAcquisitionVideoPlayback,mUSAcquisitionVideoPlaybacks)
323  {
324  std::vector<TimelineEvent> events = uSAcquisitionVideoPlayback->getEvents();
325  retval.reserve(retval.size() + events.size());
326  retval.insert( retval.end(), events.begin(), events.end() );
327  }
328 
329  return retval;
330 }
331 
332 void VideoImplService::initServiceListener()
333 {
334  mStreamerServiceListener.reset(new ServiceTrackerListener<StreamerService>(
335  mBackend->mContext,
336  boost::bind(&VideoImplService::onStreamerServiceAdded, this, _1),
337  boost::function<void (StreamerService*)>(),
338  boost::bind(&VideoImplService::onStreamerServiceRemoved, this, _1)
339  ));
340  mStreamerServiceListener->open();
341 
342 }
343 
344 void VideoImplService::onStreamerServiceAdded(StreamerService* service)
345 {
346  if (mConnectionMethod.isEmpty())
347  mConnectionMethod = service->getType();
348 
349  emit StreamerServiceAdded(service);
350 }
351 
352 void VideoImplService::onStreamerServiceRemoved(StreamerService *service)
353 {
354  emit StreamerServiceRemoved(service);
355 }
356 
357 
358 } /* namespace cx */
bool connected(bool)
boost::shared_ptr< class SpaceProvider > SpaceProviderPtr
virtual QString getConnectionMethod()
void reportError(QString msg)
Definition: cxLogger.cpp:92
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)
boost::shared_ptr< class PlaybackTime > PlaybackTimePtr
boost::shared_ptr< Probe > ProbePtr
Definition: cxProbe.h:93
static PatientModelServicePtr create(ctkPluginContext *pluginContext)
void activeToolChanged(const QString &uId)
void reportWarning(QString msg)
Definition: cxLogger.cpp:91
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:90
static VideoServiceBackendPtr create(PatientModelServicePtr dataManager, TrackingServicePtr trackingService, SpaceProviderPtr spaceProvider, ctkPluginContext *context)
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