Vuo  2.4.0
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
16static dispatch_once_t VuoProtocolsCreated = 0;
17
18vector<VuoProtocol *> VuoProtocol::protocols;
19string VuoProtocol::imageFilter = "VuoImageFilter";
20string VuoProtocol::imageGenerator = "VuoImageGenerator";
21string VuoProtocol::imageTransition = "VuoImageTransition";
22
26vector<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{
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
76VuoProtocol::VuoProtocol(string id, string protocolName)
77{
78 this->id = id;
79 this->name = protocolName;
80}
81
86{
87 return id;
88}
89
94{
95 return name;
96}
97
102vector<pair<string, string> > VuoProtocol::getInputPortNamesAndTypes(void)
103{
104 return inputPortNamesAndTypes;
105}
106
111vector<pair<string, string> > VuoProtocol::getOutputPortNamesAndTypes(void)
112{
113 return outputPortNamesAndTypes;
114}
115
119bool 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
134bool 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
149string 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
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
188bool 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
364vector<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
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
393void 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
416void 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}