PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
PlusIgtlClientInfo.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2 Program: Plus
3 Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4 See License.txt for details.
5 =========================================================Plus=header=end*/
6 
7 // Local includes
8 #include "PlusIgtlClientInfo.h"
9 
10 // IGTL includes
11 #include <igtl_header.h>
12 
13 //----------------------------------------------------------------------------
15  : ClientHeaderVersion(IGTL_HEADER_VERSION_1)
16  , TDATAResolution(0)
17  , TDATARequested(false)
18  , LastTDATASentTimeStamp(-1)
19 {
20 
21 }
22 
23 //----------------------------------------------------------------------------
25 {
26  if (strXmlData == NULL)
27  {
28  LOG_ERROR("Failed to set ClientInfo - input xml data string is invalid");
29  return PLUS_FAIL;
30  }
31 
32  vtkSmartPointer<vtkXMLDataElement> xmldata = vtkSmartPointer<vtkXMLDataElement>::Take(vtkXMLUtilities::ReadElementFromString(strXmlData));
33  if (xmldata == NULL)
34  {
35  LOG_ERROR("Failed to set ClientInfo - invalid xml data string: " << strXmlData);
36  return PLUS_FAIL;
37  }
38 
39  return SetClientInfoFromXmlData(xmldata);
40 }
41 
42 
43 //----------------------------------------------------------------------------
45 {
46  if (xmldata == NULL)
47  {
48  LOG_ERROR("Failed to set ClientInfo - invalid xml data string!");
49  return PLUS_FAIL;
50  }
51 
52  PlusIgtlClientInfo clientInfo;
53 
54  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, ClientHeaderVersion, clientInfo.ClientHeaderVersion, xmldata);
55  XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(TDATARequested, clientInfo.TDATARequested, xmldata);
56  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, TDATAResolution, clientInfo.TDATAResolution, xmldata);
57  if (xmldata->GetAttribute("Resolution") != NULL)
58  {
59  int resolution;
60  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, Resolution, resolution, xmldata);
61  clientInfo.SetTDATAResolution(resolution);
62 
63  LOG_WARNING("Old parameter name \"Resolution\" detected. Please replace with \"TDATAResolution\".");
64  xmldata->RemoveAttribute("Resolution");
65  xmldata->SetIntAttribute("TDATAResolution", resolution);
66  }
67 
68  // Get message types
69  vtkXMLDataElement* messageTypes = xmldata->FindNestedElementWithName("MessageTypes");
70  if (messageTypes != NULL)
71  {
72  for (int i = 0; i < messageTypes->GetNumberOfNestedElements(); ++i)
73  {
74  const char* name = messageTypes->GetNestedElement(i)->GetName();
75  if (name == NULL || STRCASECMP(name, "Message") != 0)
76  {
77  continue;
78  }
79  vtkXMLDataElement* typeElem = messageTypes->GetNestedElement(i);
80  std::string type;
81  XML_READ_STRING_ATTRIBUTE_NONMEMBER_REQUIRED(Type, type, typeElem);
82  clientInfo.IgtlMessageTypes.push_back(type);
83  }
84  }
85 
86  // Get transform names
87  vtkXMLDataElement* transformNames = xmldata->FindNestedElementWithName("TransformNames");
88  if (transformNames != NULL)
89  {
90  for (int i = 0; i < transformNames->GetNumberOfNestedElements(); ++i)
91  {
92  const char* transform = transformNames->GetNestedElement(i)->GetName();
93  if (transform == NULL || STRCASECMP(transform, "Transform") != 0)
94  {
95  continue;
96  }
97  vtkXMLDataElement* transformElem = transformNames->GetNestedElement(i);
98  std::string name;
99  XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(Name, name, transformElem);
100  if (name.empty())
101  {
102  LOG_WARNING("In TransformNames child transform #" << i << " definition is incomplete: required Name attribute is missing.");
103  continue;
104  }
105 
106  igsioTransformName tName;
107  if (tName.SetTransformName(name) != PLUS_SUCCESS)
108  {
109  LOG_WARNING("Invalid transform name: " << name);
110  continue;
111  }
112  clientInfo.TransformNames.push_back(tName);
113  }
114  }
115 
116  // Get image streams
117  vtkXMLDataElement* imageNames = xmldata->FindNestedElementWithName("ImageNames");
118  if (imageNames != NULL)
119  {
120  for (int i = 0; i < imageNames->GetNumberOfNestedElements(); ++i)
121  {
122  const char* image = imageNames->GetNestedElement(i)->GetName();
123  if (image == NULL || STRCASECMP(image, "Image") != 0)
124  {
125  continue;
126  }
127  vtkXMLDataElement* imageElem = imageNames->GetNestedElement(i);
128  std::string embeddedTransformToFrame;
129  XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(EmbeddedTransformToFrame, embeddedTransformToFrame, imageElem);
130  if (embeddedTransformToFrame.empty())
131  {
132  LOG_WARNING("EmbeddedTransformToFrame attribute of ImageNames/Image element #" << i << " is missing. This element will be ignored.");
133  continue;
134  }
135 
136  std::string name;
137  XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(Name, name, imageElem);
138  if (name.empty())
139  {
140  LOG_WARNING("Name attribute of ImageNames/Image element # " << i << " is missing. This element will be ignored.");
141  continue;
142  }
143 
144  ImageStream stream;
145  stream.EmbeddedTransformToFrame = embeddedTransformToFrame;
146  stream.Name = name;
147  stream.FrameConverter = vtkSmartPointer<vtkIGSIOFrameConverter>::New();
148  stream.FrameConverter->EnableCacheOn();
149 
150  clientInfo.ImageStreams.push_back(stream);
151  }
152  }
153 
154  // Get video streams
155  vtkXMLDataElement* videoNames = xmldata->FindNestedElementWithName("VideoNames");
156  if (videoNames != NULL)
157  {
158  for (int i = 0; i < videoNames->GetNumberOfNestedElements(); ++i)
159  {
160  const char* video = videoNames->GetNestedElement(i)->GetName();
161  if (video == NULL || STRCASECMP(video, "Video") != 0)
162  {
163  continue;
164  }
165  vtkXMLDataElement* videoElem = videoNames->GetNestedElement(i);
166  std::string embeddedTransformToFrame;
167  XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(EmbeddedTransformToFrame, embeddedTransformToFrame, videoElem);
168  if (embeddedTransformToFrame.empty())
169  {
170  LOG_WARNING("EmbeddedTransformToFrame attribute of VideoNames/Video element #" << i << " is missing. This element will be ignored.");
171  continue;
172  }
173 
174  std::string name;
175  XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(Name, name, videoElem);
176  if (name.empty())
177  {
178  LOG_WARNING("Name attribute of videoNames/Video element # " << i << " is missing. This element will be ignored.");
179  continue;
180  }
181 
182  VideoStream stream;
183  stream.EmbeddedTransformToFrame = embeddedTransformToFrame;
184  stream.Name = name;
185  stream.FrameConverter = vtkSmartPointer<vtkIGSIOFrameConverter>::New();
186  stream.FrameConverter->EnableCacheOn();
187 
188  XML_FIND_NESTED_ELEMENT_OPTIONAL(encodingElem, videoElem, "Encoding");
189  if (encodingElem)
190  {
191  XML_READ_STRING_ATTRIBUTE_NONMEMBER_REQUIRED(FourCC, stream.EncodeVideoParameters.FourCC, encodingElem);
192  XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(RateControl, stream.EncodeVideoParameters.RateControl, encodingElem);
193  XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(DeadlineMode, stream.EncodeVideoParameters.DeadlineMode, encodingElem);
194  XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(Lossless, stream.EncodeVideoParameters.Lossless, encodingElem);
195  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, MinKeyframeDistance, stream.EncodeVideoParameters.MinKeyframeDistance, encodingElem);
196  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, MaxKeyframeDistance, stream.EncodeVideoParameters.MaxKeyframeDistance, encodingElem);
197  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, Speed, stream.EncodeVideoParameters.Speed, encodingElem);
198  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, TargetBitrate, stream.EncodeVideoParameters.TargetBitrate, encodingElem);
199  }
200 
201  clientInfo.VideoStreams.push_back(stream);
202  }
203  }
204 
205  // Get string names
206  vtkXMLDataElement* stringNames = xmldata->FindNestedElementWithName("StringNames");
207  if (stringNames != NULL)
208  {
209  for (int i = 0; i < stringNames->GetNumberOfNestedElements(); ++i)
210  {
211  const char* string = stringNames->GetNestedElement(i)->GetName();
212  if (string == NULL || STRCASECMP(string, "String") != 0)
213  {
214  continue;
215  }
216  vtkXMLDataElement* stringElem = stringNames->GetNestedElement(i);
217  std::string name;
218  XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(Name, name, stringElem);
219  if (name.empty())
220  {
221  LOG_WARNING("In StringNames child element #" << i << " definition is incomplete: required Name attribute is missing");
222  continue;
223  }
224 
225  clientInfo.StringNames.push_back(name);
226  }
227  }
228 
229  // Copy over the new client info
230  (*this) = clientInfo;
231 
232  return PLUS_SUCCESS;
233 }
234 
235 //----------------------------------------------------------------------------
236 void PlusIgtlClientInfo::GetClientInfoInXmlData(std::string& strXmlData)
237 {
238  vtkSmartPointer<vtkXMLDataElement> xmldata = vtkSmartPointer<vtkXMLDataElement>::New();
239  xmldata->SetName("ClientInfo");
240  xmldata->SetAttribute("TDATARequested", (this->GetTDATARequested() ? "TRUE" : "FALSE"));
241  xmldata->SetIntAttribute("TDATAResolution", this->GetTDATAResolution());
242 
243  vtkSmartPointer<vtkXMLDataElement> messageTypes = vtkSmartPointer<vtkXMLDataElement>::New();
244  messageTypes->SetName("MessageTypes");
245  for (unsigned int i = 0; i < IgtlMessageTypes.size(); ++i)
246  {
247  vtkSmartPointer<vtkXMLDataElement> message = vtkSmartPointer<vtkXMLDataElement>::New();
248  message->SetName("Message");
249  message->SetAttribute("Type", IgtlMessageTypes[i].c_str());
250  messageTypes->AddNestedElement(message);
251  }
252  xmldata->AddNestedElement(messageTypes);
253 
254  vtkSmartPointer<vtkXMLDataElement> transformNames = vtkSmartPointer<vtkXMLDataElement>::New();
255  transformNames->SetName("TransformNames");
256  for (unsigned int i = 0; i < TransformNames.size(); ++i)
257  {
258  if (!TransformNames[i].IsValid())
259  {
260  std::string transformName;
261  TransformNames[i].GetTransformName(transformName);
262  LOG_ERROR("Failed to add transform name to client info - transform name is invalid (" << transformName << ").");
263  continue;
264  }
265  vtkSmartPointer<vtkXMLDataElement> transform = vtkSmartPointer<vtkXMLDataElement>::New();
266  transform->SetName("Transform");
267  std::string tname;
268  TransformNames[i].GetTransformName(tname);
269  transform->SetAttribute("Name", tname.c_str());
270  transformNames->AddNestedElement(transform);
271  }
272  xmldata->AddNestedElement(transformNames);
273 
274  vtkSmartPointer<vtkXMLDataElement> stringNames = vtkSmartPointer<vtkXMLDataElement>::New();
275  stringNames->SetName("StringNames");
276  for (unsigned int i = 0; i < StringNames.size(); ++i)
277  {
278  if (StringNames[i].empty())
279  {
280  LOG_ERROR("Failed to add string name to client info - string name is empty");
281  continue;
282  }
283  vtkSmartPointer<vtkXMLDataElement> stringElem = vtkSmartPointer<vtkXMLDataElement>::New();
284  stringElem->SetName("String");
285  stringElem->SetAttribute("Name", StringNames[i].c_str());
286  stringNames->AddNestedElement(stringElem);
287  }
288  xmldata->AddNestedElement(stringNames);
289 
290  vtkSmartPointer<vtkXMLDataElement> imageNames = vtkSmartPointer<vtkXMLDataElement>::New();
291  imageNames->SetName("ImageNames");
292  for (unsigned int i = 0; i < ImageStreams.size(); ++i)
293  {
294  vtkSmartPointer<vtkXMLDataElement> image = vtkSmartPointer<vtkXMLDataElement>::New();
295  image->SetName("Image");
296  image->SetAttribute("Name", ImageStreams[i].Name.c_str());
297  image->SetAttribute("EmbeddedTransformToFrame", ImageStreams[i].EmbeddedTransformToFrame.c_str());
298  imageNames->AddNestedElement(image);
299  }
300  xmldata->AddNestedElement(imageNames);
301 
302  std::ostringstream os;
303  igsioCommon::XML::PrintXML(os, vtkIndent(0), xmldata);
304  strXmlData = os.str();
305 }
306 
307 //----------------------------------------------------------------------------
308 void PlusIgtlClientInfo::PrintSelf(ostream& os, vtkIndent indent)
309 {
310  os << indent << "IGTL version: " << this->ClientHeaderVersion;
311  os << indent << "Message types: ";
312  if (!this->IgtlMessageTypes.empty())
313  {
314  for (unsigned int i = 0; i < this->IgtlMessageTypes.size(); ++i)
315  {
316  if (i > 0)
317  {
318  os << ", ";
319  }
320  os << this->IgtlMessageTypes[i];
321  }
322  }
323  else
324  {
325  os << "(none)";
326  }
327  os << indent << ". ";
328 
329  os << indent << "TDATARequested: " << (this->GetTDATARequested() ? "TRUE" : "FALSE") << ". ";
330  os << indent << "LastTDATASentTimeStamp: " << this->GetLastTDATASentTimeStamp() << ". ";
331  os << indent << "TDATAResolution: " << this->GetTDATAResolution() << ". ";
332 
333  os << ". Transforms: ";
334  if (!this->TransformNames.empty())
335  {
336  for (unsigned int i = 0; i < this->TransformNames.size(); ++i)
337  {
338  if (i > 0)
339  {
340  os << ", ";
341  }
342  std::string tn;
343  this->TransformNames[i].GetTransformName(tn);
344  os << tn;
345  }
346  }
347  else
348  {
349  os << "(none)";
350  }
351 
352  os << ". Strings: ";
353  if (!this->StringNames.empty())
354  {
355  std::ostringstream stringNames;
356  for (unsigned int i = 0; i < this->StringNames.size(); ++i)
357  {
358  if (i > 0)
359  {
360  os << ", ";
361  }
362  os << this->StringNames[i];
363  }
364  }
365  else
366  {
367  os << "(none)";
368  }
369 
370  os << ". Images: ";
371  if (!this->ImageStreams.empty())
372  {
373  std::ostringstream imageNames;
374  for (unsigned int i = 0; i < this->ImageStreams.size(); ++i)
375  {
376  if (i > 0)
377  {
378  os << ", ";
379  }
380  os << this->ImageStreams[i].Name << " (EmbeddedTransformToFrame: " << this->ImageStreams[i].EmbeddedTransformToFrame << ")";
381  }
382  }
383  else
384  {
385  os << "(none)";
386  }
387 }
388 
389 //----------------------------------------------------------------------------
391 {
392  return this->ClientHeaderVersion;
393 }
394 
395 //----------------------------------------------------------------------------
397 {
398  this->ClientHeaderVersion = version;
399 }
400 
401 //----------------------------------------------------------------------------
403 {
404  return this->TDATAResolution;
405 }
406 
407 //----------------------------------------------------------------------------
409 {
410  this->TDATAResolution = val;
411 }
412 
413 //----------------------------------------------------------------------------
415 {
416  return this->TDATARequested;
417 }
418 
419 //----------------------------------------------------------------------------
421 {
422  this->TDATARequested = val;
423 }
424 
425 //----------------------------------------------------------------------------
427 {
428  return this->LastTDATASentTimeStamp;
429 }
430 
431 //----------------------------------------------------------------------------
433 {
434  this->LastTDATASentTimeStamp = val;
435 }
void SetLastTDATASentTimeStamp(double val)
double GetLastTDATASentTimeStamp() const
std::vector< ImageStream > ImageStreams
std::vector< std::string > IgtlMessageTypes
igsioStatus PlusStatus
Definition: PlusCommon.h:40
void SetClientHeaderVersion(int version)
PlusStatus SetClientInfoFromXmlData(const char *strXmlData)
std::vector< std::string > StringNames
vtkSmartPointer< vtkIGSIOFrameConverter > FrameConverter
for i
std::vector< igsioTransformName > TransformNames
#define PLUS_FAIL
Definition: PlusCommon.h:43
bool GetTDATARequested() const
EncodingParameters EncodeVideoParameters
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
std::vector< VideoStream > VideoStreams
int GetClientHeaderVersion() const
void SetTDATARequested(bool val)
const char * message
Definition: phidget22.h:2457
This class provides client information for vtkPlusOpenIGTLinkServer.
void SetTDATAResolution(int val)
vtkSmartPointer< vtkIGSIOFrameConverter > FrameConverter
void GetClientInfoInXmlData(std::string &strXmlData)
virtual void PrintSelf(ostream &os, vtkIndent indent)