Vuo  2.0.2
VuoProtocol.cc
Go to the documentation of this file.
1 
10 #include "VuoProtocol.hh"
11 
12 #include "VuoRunner.hh"
13 #include "VuoStringUtilities.hh"
14 
15 
16 static dispatch_once_t VuoProtocolsCreated = 0;
17 
18 vector<VuoProtocol *> VuoProtocol::protocols;
19 string VuoProtocol::imageFilter = "VuoImageFilter";
20 string VuoProtocol::imageGenerator = "VuoImageGenerator";
21 string VuoProtocol::imageTransition = "VuoImageTransition";
22 
26 vector<VuoProtocol *> VuoProtocol::getProtocols(void)
27 {
28  dispatch_once(&VuoProtocolsCreated, ^{
29  VuoProtocol *imageFilterProtocol = new VuoProtocol(imageFilter, "Image Filter");
30  imageFilterProtocol->addInputPort("time", "VuoReal");
31  imageFilterProtocol->addInputPort("image", "VuoImage");
32  imageFilterProtocol->addOutputPort("outputImage", "VuoImage");
33  protocols.push_back(imageFilterProtocol);
34 
35  VuoProtocol *imageGeneratorProtocol = new VuoProtocol(imageGenerator, "Image Generator");
36  imageGeneratorProtocol->addInputPort("time", "VuoReal");
37  imageGeneratorProtocol->addInputPort("width", "VuoInteger");
38  imageGeneratorProtocol->addInputPort("height", "VuoInteger");
39  imageGeneratorProtocol->addOutputPort("outputImage", "VuoImage");
40  protocols.push_back(imageGeneratorProtocol);
41 
42  VuoProtocol *imageTransitionProtocol = new VuoProtocol(imageTransition, "Image Transition");
43  imageTransitionProtocol->addInputPort("time", "VuoReal");
44  imageTransitionProtocol->addInputPort("progress", "VuoReal");
45  imageTransitionProtocol->addInputPort("startImage", "VuoImage");
46  imageTransitionProtocol->addInputPort("endImage", "VuoImage");
47  imageTransitionProtocol->addOutputPort("outputImage", "VuoImage");
48  protocols.push_back(imageTransitionProtocol);
49  });
50 
51  return protocols;
52 }
53 
58 {
59  getProtocols();
60 
61  for (vector<VuoProtocol *>::iterator it = protocols.begin(); it != protocols.end(); ++it)
62  if ((*it)->getId() == id)
63  return *it;
64 
65  VUserLog("Error: Couldn't find protocol '%s'.", id.c_str());
66 
67  return NULL;
68 }
69 
76 VuoProtocol::VuoProtocol(string id, string protocolName)
77 {
78  this->id = id;
79  this->name = protocolName;
80 }
81 
85 string VuoProtocol::getId(void)
86 {
87  return id;
88 }
89 
94 {
95  return name;
96 }
97 
102 vector<pair<string, string> > VuoProtocol::getInputPortNamesAndTypes(void)
103 {
104  return inputPortNamesAndTypes;
105 }
106 
111 vector<pair<string, string> > VuoProtocol::getOutputPortNamesAndTypes(void)
112 {
113  return outputPortNamesAndTypes;
114 }
115 
119 bool VuoProtocol::hasInputPort(string portName)
120 {
121  for (vector<pair<string, string> >::iterator i = inputPortNamesAndTypes.begin(); i != inputPortNamesAndTypes.end(); ++i)
122  {
123  string currentPortName = i->first;
124  if (currentPortName == portName)
125  return true;
126  }
127 
128  return false;
129 }
130 
134 bool VuoProtocol::hasOutputPort(string portName)
135 {
136  for (vector<pair<string, string> >::iterator i = outputPortNamesAndTypes.begin(); i != outputPortNamesAndTypes.end(); ++i)
137  {
138  string currentPortName = i->first;
139  if (currentPortName == portName)
140  return true;
141  }
142 
143  return false;
144 }
145 
149 string VuoProtocol::getTypeForInputPort(string portName)
150 {
151  for (vector<pair<string, string> >::iterator i = inputPortNamesAndTypes.begin(); i != inputPortNamesAndTypes.end(); ++i)
152  {
153  string currentPortName = i->first;
154  string currentPortType = i->second;
155  if (currentPortName == portName)
156  return currentPortType;
157  }
158 
159  VUserLog("Error: Protocol '%s' has no input port with name '%s'.", this->name.c_str(), portName.c_str());
160  return NULL;
161 }
162 
166 string VuoProtocol::getTypeForOutputPort(string portName)
167 {
168  for (vector<pair<string, string> >::iterator i = outputPortNamesAndTypes.begin(); i != outputPortNamesAndTypes.end(); ++i)
169  {
170  string currentPortName = i->first;
171  string currentPortType = i->second;
172  if (currentPortName == portName)
173  return currentPortType;
174  }
175 
176  VUserLog("Error: Protocol '%s' has no output port with name '%s'.", this->name.c_str(), portName.c_str());
177  return NULL;
178 }
179 
188 bool VuoProtocol::isCompositionCompliant(string compositionAsString)
189 {
190  __block int charNum = 0;
191  bool (^getNextLine)(string &linenumber) = ^(string &linenumber){
192  linenumber = "";
193  while (true)
194  {
195  char c = compositionAsString[charNum++];
196  if (c == '\n')
197  break;
198  if (c == 0)
199  return false;
200  linenumber += c;
201  }
202  return true;
203  };
204 
205  // label="PublishedInputs|<image>image\r|<time>time\r"
206  string (^getLabel)(string linenumber) = ^(string linenumber){
207  string labelToken = "label=\"";
208  string::size_type labelLocation = linenumber.find(labelToken);
209  if (labelLocation == string::npos)
210  return (string)"";
211 
212  labelLocation += labelToken.length();
213  string label;
214  while (labelLocation < linenumber.length() && linenumber[labelLocation] != '"')
215  label += linenumber[labelLocation++];
216 
217  return label;
218  };
219 
220  // |<image>image\r
221  bool (^getNextPort)(string &label, string &portID) = ^(string &label, string &portID){
222  portID = "";
223  string portToken = "|<";
224  string::size_type portLocation = label.find(portToken);
225  if (portLocation == string::npos)
226  return false;
227 
228  portLocation += portToken.length();
229  while (portLocation < label.length() && label[portLocation] != '>')
230  portID += label[portLocation++];
231 
232  label = label.substr(portLocation);
233 
234  return true;
235  };
236 
237  // _image_type="VuoImage"
238  string (^getType)(string linenumber, string portID) = ^(string linenumber, string portID){
239  string typeToken = "_" + portID + "_type=\"";
240  string::size_type typeLocation = linenumber.find(typeToken);
241  if (typeLocation == string::npos)
242  return (string)"";
243 
244  typeLocation += typeToken.length();
245  string type;
246  while (typeLocation < linenumber.length() && linenumber[typeLocation] != '"')
247  type += linenumber[typeLocation++];
248 
249  return type;
250  };
251 
252 
253  // portID => portType
254  map<string,string> publishedInputs;
255  map<string,string> publishedOutputs;
256  string linenumber;
257  while (getNextLine(linenumber))
258  {
259  // PublishedInputs [type="vuo.in" label="PublishedInputs|<image>image\r|<time>time\r" _image="" _image_type="VuoImage" _time="" _time_type="VuoReal"];
260  // PublishedOutputs [type="vuo.out" label="PublishedOutputs|<outputImage>outputImage\l" _outputImage_type="VuoImage"];
261  bool isPublishedInputs = false;
262  bool isPublishedOutputs = false;
263  if (VuoStringUtilities::beginsWith(linenumber, "PublishedInputs [type=\"vuo.in\" label=\"PublishedInputs|<"))
264  isPublishedInputs = true;
265  else if (VuoStringUtilities::beginsWith(linenumber, "PublishedOutputs [type=\"vuo.out\" label=\"PublishedOutputs|<"))
266  isPublishedOutputs = true;
267 
268  if (!isPublishedInputs && !isPublishedOutputs)
269  continue;
270 
271  string label = getLabel(linenumber);
272  if (label == "")
273  return false;
274 
275  string portID;
276  while (getNextPort(label, portID))
277  {
278  if (isPublishedInputs)
279  publishedInputs[portID] = getType(linenumber, portID);
280  else
281  publishedOutputs[portID] = getType(linenumber, portID);
282  }
283 
284  }
285 
286  // Check whether the composition contains all of the required input ports.
287  vector<pair<string, string> > protocolInputs = getInputPortNamesAndTypes();
288  for (vector<pair<string, string> >::iterator i = protocolInputs.begin(); i != protocolInputs.end(); ++i)
289  {
290  string protocolInputName = i->first;
291  string protocolInputType = i->second;
292 
293  map<string,string>::iterator publishedInput = publishedInputs.find(protocolInputName);
294  if (publishedInput == publishedInputs.end() || publishedInput->second != protocolInputType)
295  return false;
296  }
297 
298  // Check whether the composition contains all of the required output ports.
299  vector<pair<string, string> > protocolOutputs = getOutputPortNamesAndTypes();
300  for (vector<pair<string, string> >::iterator i = protocolOutputs.begin(); i != protocolOutputs.end(); ++i)
301  {
302  string protocolOutputName = i->first;
303  string protocolOutputType = i->second;
304 
305  map<string,string>::iterator publishedOutput = publishedOutputs.find(protocolOutputName);
306  if (publishedOutput == publishedOutputs.end() || publishedOutput->second != protocolOutputType)
307  return false;
308  }
309 
310  return true;
311 }
312 
317 {
318  // Check whether the composition contains all of the required input ports.
319  vector<VuoRunner::Port *> inputs = runner->getPublishedInputPorts();
320  vector<pair<string, string> > protocolInputs = getInputPortNamesAndTypes();
321  for (vector<pair<string, string> >::iterator i = protocolInputs.begin(); i != protocolInputs.end(); ++i)
322  {
323  string protocolInputName = i->first;
324  string protocolInputType = i->second;
325 
326  bool found = false;
327  for (vector<VuoRunner::Port *>::iterator it = inputs.begin(); it != inputs.end(); ++it)
328  if ((*it)->getName() == protocolInputName
329  && (*it)->getType() == protocolInputType)
330  {
331  found = true;
332  break;
333  }
334  if (!found)
335  return false;
336  }
337 
338  // Check whether the composition contains all of the required output ports.
339  vector<VuoRunner::Port *> outputs = runner->getPublishedOutputPorts();
340  vector<pair<string, string> > protocolOutputs = getOutputPortNamesAndTypes();
341  for (vector<pair<string, string> >::iterator i = protocolOutputs.begin(); i != protocolOutputs.end(); ++i)
342  {
343  string protocolOutputName = i->first;
344  string protocolOutputType = i->second;
345 
346  bool found = false;
347  for (vector<VuoRunner::Port *>::iterator it = outputs.begin(); it != outputs.end(); ++it)
348  if ((*it)->getName() == protocolOutputName
349  && (*it)->getType() == protocolOutputType)
350  {
351  found = true;
352  break;
353  }
354  if (!found)
355  return false;
356  }
357 
358  return true;
359 }
360 
364 vector<VuoProtocol *> VuoProtocol::getCompositionProtocols(string compositionAsString)
365 {
366  vector<VuoProtocol *> allProtocols = VuoProtocol::getProtocols();
367  vector<VuoProtocol *> adheresToProtocols;
368  for (vector<VuoProtocol *>::iterator i = allProtocols.begin(); i != allProtocols.end(); ++i)
369  if ((*i)->isCompositionCompliant(compositionAsString))
370  adheresToProtocols.push_back(*i);
371  return adheresToProtocols;
372 }
373 
377 vector<VuoProtocol *> VuoProtocol::getCompositionProtocols(VuoRunner *runner)
378 {
379  vector<VuoProtocol *> allProtocols = VuoProtocol::getProtocols();
380  vector<VuoProtocol *> adheresToProtocols;
381  for (vector<VuoProtocol *>::iterator i = allProtocols.begin(); i != allProtocols.end(); ++i)
382  if ((*i)->isCompositionCompliant(runner))
383  adheresToProtocols.push_back(*i);
384  return adheresToProtocols;
385 }
386 
393 void VuoProtocol::addInputPort(string portName, string portType)
394 {
395  pair<string, string> portNameAndType = make_pair(portName, portType);
396 
397  for (vector<pair<string, string> >::iterator i = inputPortNamesAndTypes.begin(); i != inputPortNamesAndTypes.end(); ++i)
398  {
399  string currentPortName = i->first;
400  if (currentPortName == portName)
401  {
402  VUserLog("Error: Protocol '%s' already had an input port with name '%s'.", this->name.c_str(), portName.c_str());
403  return;
404  }
405  }
406 
407  inputPortNamesAndTypes.push_back(portNameAndType);
408 }
409 
416 void VuoProtocol::addOutputPort(string portName, string portType)
417 {
418  pair<string, string> portNameAndType = make_pair(portName, portType);
419 
420  for (vector<pair<string, string> >::iterator i = outputPortNamesAndTypes.begin(); i != outputPortNamesAndTypes.end(); ++i)
421  {
422  string currentPortName = i->first;
423  if (currentPortName == portName)
424  {
425  VUserLog("Error: Protocol '%s' already had an output port with name '%s'.", this->name.c_str(), portName.c_str());
426  return;
427  }
428  }
429 
430  outputPortNamesAndTypes.push_back(portNameAndType);
431 }