AudioManager  7.5.11
Native Application Runtime Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
CAmRouter.cpp
Go to the documentation of this file.
1 
25 #include <cassert>
26 #include <algorithm>
27 #include <vector>
28 #include <iterator>
29 #include "CAmRouter.h"
30 #include "IAmDatabaseHandler.h"
31 #include "CAmControlSender.h"
32 #include "CAmDltWrapper.h"
33 
34 
35 
36 namespace am {
37 
38 
39 template <class X> void getMergeConnectionFormats(const X * element,
40  const am_CustomConnectionFormat_t connectionFormat,
41  const std::vector<am_CustomConnectionFormat_t> & listConnectionFormats,
42  std::vector<am_CustomConnectionFormat_t> & outListMergeConnectionFormats)
43 {
44  std::vector<am_CustomConnectionFormat_t> listRestrictedConnectionFormats;
45  CAmRouter::getRestrictedOutputFormats(element->convertionMatrix,
46  element->listSourceFormats,
47  element->listSinkFormats,
48  connectionFormat,
49  listRestrictedConnectionFormats);
50  std::sort(listRestrictedConnectionFormats.begin(), listRestrictedConnectionFormats.end()); //todo: this might be not needed if we use strictly sorted input
51  std::insert_iterator<std::vector<am_CustomConnectionFormat_t> > inserter(outListMergeConnectionFormats, outListMergeConnectionFormats.begin());
52  set_intersection(listConnectionFormats.begin(), listConnectionFormats.end(), listRestrictedConnectionFormats.begin(), listRestrictedConnectionFormats.end(), inserter);
53 }
54 
55 
57  mpDatabaseHandler(iDatabaseHandler), //
58  mpControlSender(iSender),
59  mOnlyFreeConversionNodes(false),
60  mRoutingGraph(),
61  mNodeListSources(),
62  mNodeListSinks(),
63  mNodeListGateways(),
64  mNodeListConverters()
65 {
66  assert(mpDatabaseHandler);
67  assert(mpControlSender);
68 }
69 
71 {
72 }
73 
82 am_Error_e CAmRouter::getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s> & returnList)
83 {
84  returnList.clear();
85  am_Source_s source;
86  am_Sink_s sink;
87  am_Error_e error = mpDatabaseHandler->getSourceInfoDB(sourceID, source);
88  if(error!=E_OK)
89  return error;
90  error = mpDatabaseHandler->getSinkInfoDB(sinkID, sink);
91  if(error!=E_OK)
92  return error;
93  error = getRoute(onlyfree, source, sink, returnList);
94  return error;
95 }
96 
97 
98 am_Error_e CAmRouter::getRoute(const bool onlyfree, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes)
99 {
100  am_Error_e error;
101  load(onlyfree);
102 
103  CAmRoutingNode* pRootSource = sourceNodeWithID(aSource.sourceID);
104  CAmRoutingNode* pRootSink = sinkNodeWithID(aSink.sinkID);
105 
106  assert(pRootSource);
107  assert(pRootSink);
108 
109 #ifdef TRACE_GRAPH
110  mRoutingGraph.trace([&](const CAmRoutingNode & node, const std::vector<CAmVertex<am_RoutingNodeData_s,uint16_t>*> & list) {
111  std::cout << "Node " << node.getIndex() << " :";
112  ((CAmRoutingNode &)node).getData().trace();
113  std::cout << "-->";
114  std::for_each(list.begin(), list.end(), [&](const CAmVertex<am_RoutingNodeData_s,uint16_t>* refVertex){
115  am::CAmNode<am::am_RoutingNodeData_s>* data = refVertex->getNode();
116  std::cout << "Node " << data->getIndex() << " :";
117  data->getData().trace();
118  });
119  std::cout << std::endl;
120  });
121 #endif
122 
123  std::vector<std::vector<CAmRoutingNode*>> pathNodes;
124  error = getAllPaths(*pRootSource, *pRootSink, listRoutes, pathNodes);
125  return error;
126 }
127 
128 void CAmRouter::load(const bool onlyFree)
129 {
130  clear();
131  mOnlyFreeConversionNodes = onlyFree;
132 
133 #if defined (WITH_DATABASE_STORAGE)
134  std::deque<am_Source_s> listSources;
135  std::deque<am_Sink_s> listSinks;
136  std::deque<am_Gateway_s> listGateways;
137  std::deque<am_Converter_s> listConverters;
138 #endif
139  am_RoutingNodeData_s nodeDataSrc;
140  nodeDataSrc.type = CAmNodeDataType::SOURCE;
141  mpDatabaseHandler->enumerateSources([&](const am_Source_s & obj){
142 #if defined (WITH_DATABASE_STORAGE)
143  listSources.push_back(obj);
144  nodeDataSrc.data.source = &listSources.back();
145 #else
146  nodeDataSrc.data.source = (am_Source_s*)&obj;
147 #endif
148  mNodeListSources[nodeDataSrc.data.source->domainID].push_back(&mRoutingGraph.addNode(nodeDataSrc));
149  });
150  am_RoutingNodeData_s nodeDataSink;
151  nodeDataSink.type = CAmNodeDataType::SINK;
152  mpDatabaseHandler->enumerateSinks([&](const am_Sink_s & obj){
153 #if defined (WITH_DATABASE_STORAGE)
154  listSinks.push_back(obj);
155  nodeDataSrc.data.sink = &listSinks.back();
156 #else
157  nodeDataSink.data.sink = (am_Sink_s*)&obj;
158 #endif
159  mNodeListSinks[nodeDataSink.data.sink->domainID].push_back(&mRoutingGraph.addNode(nodeDataSink));
160  });
161  am_RoutingNodeData_s nodeDataGateway;
162  nodeDataGateway.type = CAmNodeDataType::GATEWAY;
163  mpDatabaseHandler->enumerateGateways([&](const am_Gateway_s & obj){
164 #if defined (WITH_DATABASE_STORAGE)
165  listGateways.push_back(obj);
166  nodeDataSrc.data.gateway = &listGateways.back();
167 #else
168  nodeDataGateway.data.gateway = (am_Gateway_s*)&obj;
169 #endif
170  mNodeListGateways[nodeDataGateway.data.gateway->controlDomainID].push_back(&mRoutingGraph.addNode(nodeDataGateway));
171  });
172  am_RoutingNodeData_s nodeDataConverter;
173  nodeDataConverter.type = CAmNodeDataType::CONVERTER;
174  mpDatabaseHandler->enumerateConverters([&](const am_Converter_s & obj){
175 #if defined (WITH_DATABASE_STORAGE)
176  listConverters.push_back(obj);
177  nodeDataSrc.data.converter = &listConverters.back();
178 #else
179  nodeDataConverter.data.converter = (am_Converter_s*)&obj;
180 #endif
181  mNodeListConverters[nodeDataConverter.data.converter->domainID].push_back(&mRoutingGraph.addNode(nodeDataConverter));
182  });
183 
184 #ifdef ROUTING_BUILD_CONNECTIONS
185  constructConverterConnections();
186  constructGatewayConnections();
187  constructSourceSinkConnections();
188 #endif
189 }
190 
192 {
193  mRoutingGraph.clear();
194  mNodeListSources.clear();
195  mNodeListSinks.clear();
196  mNodeListGateways.clear();
197  mNodeListConverters.clear();
198 }
199 
201 {
202  CAmRoutingNode* result = NULL;
203  for(auto it = mNodeListSinks.begin(); it!=mNodeListSinks.end(); it++)
204  {
205  result = sinkNodeWithID(sinkID, it->first);
206  if(result)
207  return result;
208  }
209  return result;
210 }
211 
213 {
214  CAmRoutingNode* result = NULL;
215  std::vector<CAmRoutingNode*> & value = mNodeListSinks[domainID];
216  auto iter = std::find_if(value.begin(), value.end(), [sinkID](CAmRoutingNode* node){
217  return node->getData().data.sink->sinkID==sinkID;
218  });
219  if(iter!=value.end())
220  result = *iter;
221  return result;
222 }
223 
225 {
226  CAmRoutingNode* result = NULL;
227  for(auto it = mNodeListSources.begin(); it!=mNodeListSources.end(); it++)
228  {
229  result = sourceNodeWithID(sourceID, it->first);
230  if(result)
231  return result;
232  }
233  return result;
234 }
235 
237 {
238  CAmRoutingNode* result = NULL;
239  std::vector<CAmRoutingNode*> & value = mNodeListSources[domainID];
240  auto iter = std::find_if(value.begin(), value.end(), [sourceID](CAmRoutingNode* node){
241  return node->getData().data.source->sourceID==sourceID;
242  });
243  if(iter!=value.end())
244  result = *iter;
245  return result;
246 }
247 
249 {
250  CAmRoutingNode* result = NULL;
251  std::vector<CAmRoutingNode*> & value = mNodeListConverters[domainID];
252  auto iter = std::find_if(value.begin(), value.end(), [sinkID](CAmRoutingNode* node){
253  return node->getData().data.converter->sinkID==sinkID;
254  });
255  if(iter!=value.end())
256  result = *iter;
257  return result;
258 }
259 
261 {
262  for(auto it = mNodeListGateways.begin(); it!=mNodeListGateways.end(); it++)
263  {
264  std::vector<CAmRoutingNode*> & value = it->second;
265  auto iter = std::find_if(value.begin(), value.end(), [sinkID](CAmRoutingNode* node){
266  return node->getData().data.gateway->sinkID==sinkID;
267  });
268  if(iter!=value.end())
269  return *iter;
270  }
271  return NULL;
272 }
273 
274 #ifdef ROUTING_BUILD_CONNECTIONS
275 
276 void CAmRouter::constructSourceSinkConnections()
277 {
278  std::vector<am_CustomConnectionFormat_t> intersection;
279  for(auto itSrc = mNodeListSources.begin(); itSrc!=mNodeListSources.end(); itSrc++)
280  {
281  for(auto it = itSrc->second.begin(); it!=itSrc->second.end(); it++)
282  {
283  CAmRoutingNode* srcNode = *it;
284  am_RoutingNodeData_s & srcNodeData = srcNode->getData();
285  am_Source_s * source = srcNodeData.data.source;
286  for(auto itSink = mNodeListSinks[itSrc->first].begin(); itSink!=mNodeListSinks[itSrc->first].end(); itSink++)
287  {
288  CAmRoutingNode* sinkNode = *itSink;
289  am_RoutingNodeData_s & sinkNodeData = sinkNode->getData();
290  am_Sink_s * sink = sinkNodeData.data.sink;
291 
292  intersection.clear();
293  //Check whether the hidden sink formats match the source formats...
295  if(intersection.size()>0)//OK match source -> sink
296  {
297  mRoutingGraph.connectNodes(*srcNode, *sinkNode, CF_UNKNOWN, 1);
298  }
299  }
300  }
301  }
302 }
303 
304 void CAmRouter::constructGatewayConnections()
305 {
306  std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats;
307  for(auto iter = mNodeListGateways.begin(); iter!=mNodeListGateways.end(); iter++)
308  {
309  for(auto it = iter->second.begin(); it!=iter->second.end(); it++)
310  {
311  CAmRoutingNode* gatewayNode = *it;
312  am_RoutingNodeData_s & gatewayNodeData = gatewayNode->getData();
313  am_Gateway_s * gateway = gatewayNodeData.data.gateway;
314  //Get only gateways with end point in current source domain
315  if(!mOnlyFreeConversionNodes || !isComponentConnected(*gateway))
316  {
317  //Get the sink connected to the gateway...
318  CAmRoutingNode *gatewaySinkNode = this->sinkNodeWithID(gateway->sinkID, gateway->domainSinkID);
319  if(gatewaySinkNode)
320  {
321  am_RoutingNodeData_s & gatewaySinkData = gatewaySinkNode->getData();
322  //Check whether the hidden sink formats match the source formats...
323  sourceFormats.clear();
324  sinkFormats.clear();
325  if(getAllowedFormatsFromConvMatrix(gateway->convertionMatrix, gateway->listSourceFormats, gateway->listSinkFormats, sourceFormats, sinkFormats))
326  {
327  CAmRoutingNode *gatewaySourceNode = this->sourceNodeWithID(gateway->sourceID, gateway->domainSourceID);
328  if(gatewaySourceNode)
329  {
330  //Connections hidden_sink->gateway->hidden_source
331  mRoutingGraph.connectNodes(*gatewaySinkNode, *gatewayNode, CF_UNKNOWN, 1);
332  mRoutingGraph.connectNodes(*gatewayNode, *gatewaySourceNode, CF_UNKNOWN, 1);
333  }
334  }
335  }
336  }
337  }
338  }
339 }
340 
341 void CAmRouter::constructConverterConnections()
342 {
343  std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats;
344 
345  for(auto iter = mNodeListConverters.begin(); iter!=mNodeListConverters.end(); iter++)
346  {
347  for(auto it = iter->second.begin(); it!=iter->second.end(); it++)
348  {
349  CAmRoutingNode* converterNode = *it;
350  am_RoutingNodeData_s & converterNodeData = converterNode->getData();
351  am_Converter_s * converter = converterNodeData.data.converter;
352  //Get only converters with end point in current source domain
353  if(!mOnlyFreeConversionNodes || !isComponentConnected(*converter))
354  {
355  //Get the sink connected to the converter...
356  CAmRoutingNode *converterSinkNode = this->sinkNodeWithID(converter->sinkID, converter->domainID);
357  if(converterSinkNode)
358  {
359  am_RoutingNodeData_s & converterSinkData = converterSinkNode->getData();
360  //Check whether the hidden sink formats match the source formats...
361  sourceFormats.clear();
362  sinkFormats.clear();
363  if(getAllowedFormatsFromConvMatrix(converter->convertionMatrix, converter->listSourceFormats, converter->listSinkFormats, sourceFormats, sinkFormats))
364  {
365  CAmRoutingNode *converterSourceNode = this->sourceNodeWithID(converter->sourceID, converter->domainID);
366  if(converterSourceNode)
367  {
368  //Connections hidden_sink->converter->hidden_source
369  mRoutingGraph.connectNodes(*converterSinkNode, *converterNode, CF_UNKNOWN, 1);
370  mRoutingGraph.connectNodes(*converterNode, *converterSourceNode, CF_UNKNOWN, 1);
371  }
372  }
373  }
374  }
375  }
376  }
377 }
378 #else
379 
380 void CAmRouter::getVerticesForSource(const CAmRoutingNode & node, CAmRoutingListVertices & list)
381 {
382  am_RoutingNodeData_s & srcNodeData = ((CAmRoutingNode*)&node)->getData();
383  std::vector<am_CustomConnectionFormat_t> intersection;
384  am_Source_s * source = srcNodeData.data.source;
385  std::vector<CAmRoutingNode*> & sinks = mNodeListSinks[source->domainID];
386  for(auto itSink = sinks.begin(); itSink!=sinks.end(); itSink++)
387  {
388  CAmRoutingNode* sinkNode = *itSink;
389  am_RoutingNodeData_s & sinkNodeData = sinkNode->getData();
390  am_Sink_s * sink = sinkNodeData.data.sink;
391 
392  intersection.clear();
393  //Check whether the hidden sink formats match the source formats...
394  listPossibleConnectionFormats(source->listConnectionFormats, sink->listConnectionFormats, intersection);
395  if(intersection.size()>0)//OK match source -> sink
396  {
397  list.emplace_back(sinkNode, CF_UNKNOWN, 1);
398  }
399  }
400 }
401 
402 void CAmRouter::getVerticesForSink(const CAmRoutingNode & node, CAmRoutingListVertices & list)
403 {
404  am_RoutingNodeData_s & sinkNodeData = ((CAmRoutingNode*)&node)->getData();
405  std::vector<am_CustomConnectionFormat_t> intersection;
406  am_Sink_s * sink = sinkNodeData.data.sink;
407 
408  CAmRoutingNode *converterNode = converterNodeWithSinkID(sink->sinkID, sink->domainID);
409  if(converterNode)
410  {
411  std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats;
412  am_RoutingNodeData_s & converterData = converterNode->getData();
413  am_Converter_s * converter = converterData.data.converter;
414  if(!mOnlyFreeConversionNodes || !isComponentConnected(*converter))
415  {
416  if(getAllowedFormatsFromConvMatrix(converter->convertionMatrix, converter->listSourceFormats, converter->listSinkFormats, sourceFormats, sinkFormats))
417  list.emplace_back(converterNode, CF_UNKNOWN, 1);
418  }
419  }
420  else
421  {
422  std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats;
423  CAmRoutingNode *gatewayNode = gatewayNodeWithSinkID(sink->sinkID);
424  if(gatewayNode)
425  {
426  std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats;
427  am_RoutingNodeData_s & gatewayData = gatewayNode->getData();
428  am_Gateway_s * gateway = gatewayData.data.gateway;
429  if(!mOnlyFreeConversionNodes || !isComponentConnected(*gateway))
430  {
431  if(getAllowedFormatsFromConvMatrix(gateway->convertionMatrix, gateway->listSourceFormats, gateway->listSinkFormats, sourceFormats, sinkFormats))
432  list.emplace_back(gatewayNode, CF_UNKNOWN, 1);
433  }
434  }
435  }
436 
437 }
438 
439 void CAmRouter::getVerticesForConverter(const CAmRoutingNode & node, CAmRoutingListVertices & list)
440 {
441  std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats;
442  am_RoutingNodeData_s & converterNodeData = ((CAmRoutingNode*)&node)->getData();
443  am_Converter_s * converter = converterNodeData.data.converter;
444  //Get only converters with end point in current source domain
445  if(getAllowedFormatsFromConvMatrix(converter->convertionMatrix, converter->listSourceFormats, converter->listSinkFormats, sourceFormats, sinkFormats))
446  {
447  CAmRoutingNode *converterSourceNode = this->sourceNodeWithID(converter->sourceID, converter->domainID);
448  if(converterSourceNode)
449  {
450  list.emplace_back(converterSourceNode, CF_UNKNOWN, 1);
451  }
452  }
453 }
454 
455 void CAmRouter::getVerticesForGateway(const CAmRoutingNode & node, CAmRoutingListVertices & list)
456 {
457  am_RoutingNodeData_s & gatewayNodeData = ((CAmRoutingNode*)&node)->getData();
458  std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats;
459  am_Gateway_s * gateway = gatewayNodeData.data.gateway;
460  if(getAllowedFormatsFromConvMatrix(gateway->convertionMatrix, gateway->listSourceFormats, gateway->listSinkFormats, sourceFormats, sinkFormats))
461  {
462  CAmRoutingNode *gatewaySourceNode = this->sourceNodeWithID(gateway->sourceID, gateway->domainSourceID);
463  if(gatewaySourceNode)
464  {
465  //Connections hidden_sink->gateway->hidden_source
466  list.emplace_back(gatewaySourceNode, CF_UNKNOWN, 1);
467  }
468  }
469 }
470 
471 void CAmRouter::getVerticesForNode(
472  const CAmRoutingNode & node,
474  )
475 {
476  am_RoutingNodeData_s & nodeData = ((CAmRoutingNode*)&node)->getData();
477  if(nodeData.type==CAmNodeDataType::SOURCE)
478  {
479  getVerticesForSource(node, list);
480  }
481  else if(nodeData.type==CAmNodeDataType::SINK)
482  {
483  getVerticesForSink(node, list);
484  }
485  else if(nodeData.type==CAmNodeDataType::CONVERTER)
486  {
487  getVerticesForConverter(node, list);
488  }
489  else if(nodeData.type==CAmNodeDataType::GATEWAY)
490  {
491  getVerticesForGateway(node, list);
492  }
493 }
494 
495 #endif
496 
497 am_Error_e CAmRouter::determineConnectionFormatsForPath(am_Route_s & routeObjects, std::vector<CAmRoutingNode*> & nodes)
498 {
499  std::vector<am_RoutingElement_s>::iterator routingElementIterator = routeObjects.route.begin();
500  std::vector<CAmRoutingNode*>::iterator nodeIterator = nodes.begin();
501  if( routingElementIterator!= routeObjects.route.end() && nodeIterator!=nodes.end() )
502  return doConnectionFormatsForPath(routeObjects, nodes, routingElementIterator, nodeIterator);
503  return E_OK;
504 }
505 
506 am_Error_e CAmRouter::doConnectionFormatsForPath(am_Route_s & routeObjects,
507  std::vector<CAmRoutingNode*> & nodes,
508  std::vector<am_RoutingElement_s>::iterator routingElementIterator,
509  std::vector<CAmRoutingNode*>::iterator nodeIterator)
510 {
511  am_Error_e returnError = E_NOT_POSSIBLE;
512  std::vector<am_CustomConnectionFormat_t> listConnectionFormats;
513  std::vector<am_CustomConnectionFormat_t> listMergeConnectionFormats;
514 
515  std::vector<CAmRoutingNode*>::iterator currentNodeIterator = nodeIterator;
516  std::vector<am_RoutingElement_s>::iterator currentRoutingElementIterator = routingElementIterator;
517 
518  if (currentRoutingElementIterator!=routeObjects.route.begin())
519  {
520  std::vector<am_CustomConnectionFormat_t> listConnectionFormats;
521  std::vector<am_RoutingElement_s>::iterator tempIterator = (currentRoutingElementIterator-1);
522  CAmRoutingNode * currentNode = *currentNodeIterator;
523  getSourceSinkPossibleConnectionFormats(currentNodeIterator+1, currentNodeIterator+2, listConnectionFormats);
524 
525  if(currentNode->getData().type==CAmNodeDataType::GATEWAY)
526  {
527  am_Gateway_s *gateway = currentNode->getData().data.gateway;
528  getMergeConnectionFormats(gateway, tempIterator->connectionFormat, listConnectionFormats, listMergeConnectionFormats);
529  }
530  else if(currentNode->getData().type==CAmNodeDataType::CONVERTER)
531  {
532  am_Converter_s *converter = currentNode->getData().data.converter;
533  getMergeConnectionFormats(converter, tempIterator->connectionFormat, listConnectionFormats, listMergeConnectionFormats);
534  }
535  currentNodeIterator+=3;
536  }
537  else
538  {
539  CAmRoutingNode * currentNode = *currentNodeIterator;
540  assert(currentNode->getData().type==CAmNodeDataType::SOURCE);
541 
542  currentNodeIterator++;
543  assert(currentNodeIterator!=nodes.end());
544 
545  CAmRoutingNode * nodeSink = *currentNodeIterator;
546  assert(nodeSink->getData().type==CAmNodeDataType::SINK);
547 
548  am_Source_s *source = currentNode->getData().data.source;
549  am_Sink_s *sink = nodeSink->getData().data.sink;
550  listPossibleConnectionFormats(source->listConnectionFormats, sink->listConnectionFormats, listMergeConnectionFormats);
551  currentNodeIterator+=1; //now we are on the next converter/gateway
552  }
553 
554  //let the controller decide:
555  std::vector<am_CustomConnectionFormat_t> listPriorityConnectionFormats;
556  mpControlSender->getConnectionFormatChoice(currentRoutingElementIterator->sourceID, currentRoutingElementIterator->sinkID, routeObjects,
557  listMergeConnectionFormats, listPriorityConnectionFormats);
558 
559  //we have the list sorted after priors - now we try one after the other with the next part of the route
560  std::vector<am_CustomConnectionFormat_t>::iterator connectionFormatIterator = listPriorityConnectionFormats.begin();
561  //here we need to check if we are at the end and stop
562  std::vector<am_RoutingElement_s>::iterator nextIterator = currentRoutingElementIterator + 1;//next pair source and sink
563  if (nextIterator == routeObjects.route.end())
564  {
565  if (!listPriorityConnectionFormats.empty())
566  {
567  currentRoutingElementIterator->connectionFormat = listPriorityConnectionFormats.front();
568  return (E_OK);
569  }
570  else
571  return (E_NOT_POSSIBLE);
572  }
573 
574  for (; connectionFormatIterator != listPriorityConnectionFormats.end(); ++connectionFormatIterator)
575  {
576  currentRoutingElementIterator->connectionFormat = *connectionFormatIterator;
577  if ((returnError = doConnectionFormatsForPath(routeObjects, nodes, nextIterator, currentNodeIterator)) == E_OK)
578  {
579  break;
580  }
581  }
582  return (returnError);
583 }
584 
585 #ifdef ROUTING_BUILD_CONNECTIONS
586 
587 void CAmRouter::getShortestPath(const CAmRoutingNode & source,
588  const CAmRoutingNode & destination,
589  std::vector<CAmRoutingNode*> & resultPath)
590 {
591  mRoutingGraph.getShortestPath(source, destination, resultPath);
592 }
593 
595  am_Route_s & resultPath, std::vector<CAmRoutingNode*> & resultNodesPath)
596 {
597  am_RoutingElement_s * element;
598  am_RoutingNodeData_s & sinkNodeData = aSink.getData();
599  am_RoutingNodeData_s & sourceNodeData = aSource.getData();
600  resultPath.sinkID = sinkNodeData.data.sink->sinkID;
601  resultPath.sourceID = sourceNodeData.data.source->sourceID;
602 
603  std::function<void(const am_GraphPathPosition_e, CAmRoutingNode &)> cb = [&](const am_GraphPathPosition_e, CAmRoutingNode & object)
604  {
605  resultNodesPath.insert(resultNodesPath.begin(), (CAmRoutingNode*)&object);
606  am_RoutingNodeData_s & routingData = object.getData();
607  if(routingData.type==CAmNodeDataType::SINK)
608  {
609  auto iter = resultPath.route.emplace(resultPath.route.begin());
610  element = &(*iter);
611  element->domainID = routingData.data.sink->domainID;
612  element->sinkID = routingData.data.sink->sinkID;
613  element->connectionFormat = CF_UNKNOWN;
614  }
615  else if(routingData.type==CAmNodeDataType::SOURCE)
616  {
617  element->domainID = routingData.data.source->domainID;
618  element->sourceID = routingData.data.source->sourceID;
619  element->connectionFormat = CF_UNKNOWN;
620  }
621  };
622  mRoutingGraph.getShortestPath(aSource, aSink, cb);
623 }
624 
625 #endif
626 
628  CAmRoutingNode & aSink,
629  std::vector<am_Route_s> & resultPath,
630  std::vector<std::vector<CAmRoutingNode*>> & resultNodesPath,
631  const bool includeCycles)
632 {
633 #ifndef ROUTING_BUILD_CONNECTIONS
634  bool cycles = false;
635 #else
636  bool cycles = includeCycles;
637 #endif
638  if(((CAmRoutingNode*)&aSource)->getData().type!=CAmNodeDataType::SOURCE ||
639  ((CAmRoutingNode*)&aSink)->getData().type!=CAmNodeDataType::SINK)
640  return E_NOT_POSSIBLE;
641 
642  uint8_t errorsCount = 0, successCount = 0;
643  generateAllPaths(aSource, aSink, cycles, [&](const std::vector<CAmRoutingNode*> & path) {
644  resultNodesPath.push_back(path);
645  resultPath.emplace_back();
646  am_Route_s & nextRoute = resultPath.back();
647  nextRoute.sinkID = aSink.getData().data.sink->sinkID;
648  nextRoute.sourceID = aSource.getData().data.source->sourceID;
649  am_RoutingElement_s * element;
650  for(auto it = path.begin(); it!=path.end(); it++)
651  {
652  am_RoutingNodeData_s & routingData = (*it)->getData();
653  if(routingData.type==CAmNodeDataType::SOURCE)
654  {
655  auto iter = nextRoute.route.emplace(nextRoute.route.end());
656  element = &(*iter);
657  element->domainID = routingData.data.source->domainID;
658  element->sourceID = routingData.data.source->sourceID;
659  element->connectionFormat = CF_UNKNOWN;
660  }
661  else if(routingData.type==CAmNodeDataType::SINK)
662  {
663  element->domainID = routingData.data.sink->domainID;
664  element->sinkID = routingData.data.sink->sinkID;
665  element->connectionFormat = CF_UNKNOWN;
666  }
667  }
668 
669  am_Error_e err = determineConnectionFormatsForPath(nextRoute, (std::vector<CAmRoutingNode*> &)path);
670  if(err!=E_OK)
671  {
672  errorsCount++;
673  auto last = resultPath.end()-1;
674  resultPath.erase(last);
675 #ifdef TRACE_GRAPH
676  std::cout<<"Error by determining connection formats for path from source:"<<nextRoute.sourceID<<" to sink:"<<nextRoute.sinkID<<"\n";
677 #endif
678  }
679  else
680  {
681 #ifdef TRACE_GRAPH
682  std::cout<<"\nSuccessfully determined connection formats for path from source:"<<nextRoute.sourceID<<" to sink:"<<nextRoute.sinkID<<"\n";
683  for(auto it = nextRoute.route.begin(); it!=nextRoute.route.end(); it++)
684  {
685  am_RoutingElement_s & routingElement = *it;
686  std::cout<<"["
687  <<routingElement.sourceID
688  <<"->"
689  <<routingElement.sinkID
690  <<" cf:"
691  <<routingElement.connectionFormat
692  <<" d:"
693  <<routingElement.domainID
694  <<"]";
695  }
696  std::cout<<"\n";
697 #endif
698  successCount++;
699  }
700  });
701  if(successCount)
702  return E_OK;
703  if(errorsCount)
704  return E_NOT_POSSIBLE;
705  return E_OK;
706 }
707 
708 bool CAmRouter::shouldGoInDomain(const std::vector<am_domainID_t> & visitedDomains, const am_domainID_t nodeDomainID)
709 {
710  if(visitedDomains.size())
711  {
712  if(visitedDomains.back()==nodeDomainID)
713  return true;
714 
715  for(auto it=visitedDomains.begin();it!=visitedDomains.end()-1; it++)
716  {
717  if(nodeDomainID==*it)
718  return false;
719  }
720  }
721  return true;
722 }
723 
724 void CAmRouter::generateAllPaths(const CAmRoutingNode & src,
725  const CAmRoutingNode & dst,
726  const bool includeCycles,
727  std::function<void(const std::vector<CAmRoutingNode*> & path)> cb)
728 {
729  if(!includeCycles)
730  {
731  std::vector<CAmRoutingNode*> visited;
732  std::vector<am_domainID_t> visitedDomains;
733  visited.push_back((CAmRoutingNode*)&src);
734  visitedDomains.push_back(((CAmRoutingNode*)&src)->getData().domainID());
735  ((CAmRoutingNode*)&src)->setStatus(GES_VISITED);
736  goThroughAllPaths(dst, visited, visitedDomains, cb);
737  }
738  else
739  mRoutingGraph.getAllPaths(src, dst, cb);
740 }
741 
742 void CAmRouter::goThroughAllPaths(const CAmRoutingNode & dst,
743  std::vector<CAmRoutingNode*> & visited,
744  std::vector<am_domainID_t> & visitedDomains,
745  std::function<void(const std::vector<CAmRoutingNode*> & path)> cb)
746 {
747 #ifndef ROUTING_BUILD_CONNECTIONS
748  CAmRoutingListVertices vertices;
749  getVerticesForNode(*visited.back(), vertices);
750  const CAmRoutingListVertices * nodes = &vertices;
751 #else
752  const CAmRoutingListVertices * nodes = mRoutingGraph.getVertexList()[visited.back()->getIndex()];
753 #endif
754  CAmRoutingListVertices::const_iterator vItr(nodes->begin());
755  for (; vItr != nodes->end(); ++vItr)
756  {
757  const CAmRoutingVertex & vertex = (*vItr);
758  if(vertex.getNode()->getStatus()!=GES_NOT_VISITED || !shouldGoInDomain(visitedDomains, vertex.getNode()->getData().domainID()))
759  continue;
760  if (vertex.getNode()==&dst)
761  {
762  vertex.getNode()->setStatus(GES_IN_PROGRESS);
763  visited.push_back(vertex.getNode());
764  visitedDomains.push_back(vertex.getNode()->getData().domainID());
765  //notify observer
766  cb(visited);
767  //remove last node from the list
768  auto last = visited.end()-1;
769  visited.erase(last);
770  visitedDomains.erase(visitedDomains.end()-1);
771  vertex.getNode()->setStatus(GES_NOT_VISITED);
772  break;
773  }
774  }
775  vItr = nodes->begin();
776  //bfs like loop
777  for (; vItr != nodes->end(); ++vItr)
778  {
779  const CAmRoutingVertex & vertex = (*vItr);
780  if(vertex.getNode()->getStatus()!=GES_NOT_VISITED
781  ||vertex.getNode()==&dst ||
782  !shouldGoInDomain(visitedDomains, vertex.getNode()->getData().domainID()))
783  continue;
784  vertex.getNode()->setStatus(GES_IN_PROGRESS);
785  visited.push_back(vertex.getNode());
786  visitedDomains.push_back(vertex.getNode()->getData().domainID());
787  goThroughAllPaths(dst, visited, visitedDomains, cb);
788  //remove last node from the list
789  auto last = visited.end()-1;
790  visited.erase(last);
791  visitedDomains.erase(visitedDomains.end()-1);
792  vertex.getNode()->setStatus(GES_NOT_VISITED);
793  }
794 }
795 
796 bool CAmRouter::getAllowedFormatsFromConvMatrix( const std::vector<bool> & convertionMatrix,
797  const std::vector<am_CustomConnectionFormat_t> & listSourceFormats,
798  const std::vector<am_CustomConnectionFormat_t> & listSinkFormats,
799  std::vector<am_CustomConnectionFormat_t> & sourceFormats,
800  std::vector<am_CustomConnectionFormat_t> & sinkFormats)
801 {
802  const size_t sizeSourceFormats = listSourceFormats.size();
803  const size_t sizeSinkFormats = listSinkFormats.size();
804  const size_t sizeConvertionMatrix = convertionMatrix.size();
805 
806  if(sizeSourceFormats==0||sizeSinkFormats==0||sizeConvertionMatrix==0||sizeConvertionMatrix!=sizeSinkFormats*sizeSourceFormats)
807  {
808  return false;
809  }
810 
811  std::vector<bool>::const_iterator iterator = convertionMatrix.begin();
812  for (; iterator != convertionMatrix.end(); ++iterator)
813  {
814  if( true == *iterator )
815  {
816  const size_t index = iterator-convertionMatrix.begin();
817  size_t idx = index%sizeSourceFormats;
818  sourceFormats.push_back(listSourceFormats.at(idx));
819  idx = index/sizeSourceFormats;
820  sinkFormats.push_back(listSinkFormats.at(idx));
821  }
822  }
823  return sourceFormats.size()>0;
824 }
825 
826 void CAmRouter::listPossibleConnectionFormats(std::vector<am_CustomConnectionFormat_t> & inListSourceFormats,
827  std::vector<am_CustomConnectionFormat_t> & inListSinkFormats,
828  std::vector<am_CustomConnectionFormat_t> & outListFormats)
829 {
830  std::sort(inListSourceFormats.begin(), inListSourceFormats.end());
831  std::sort(inListSinkFormats.begin(), inListSinkFormats.end());
832  std::insert_iterator<std::vector<am_CustomConnectionFormat_t> > inserter(outListFormats, outListFormats.begin());
833  set_intersection(inListSourceFormats.begin(), inListSourceFormats.end(), inListSinkFormats.begin(), inListSinkFormats.end(), inserter);
834 }
835 
836 
837 bool CAmRouter::getRestrictedOutputFormats(const std::vector<bool> & convertionMatrix,
838  const std::vector<am_CustomConnectionFormat_t> & listSourceFormats,
839  const std::vector<am_CustomConnectionFormat_t> & listSinkFormats,
840  const am_CustomConnectionFormat_t connectionFormat,
841  std::vector<am_CustomConnectionFormat_t> & listFormats)
842 {
843  listFormats.clear();
844  std::vector<am_CustomConnectionFormat_t>::const_iterator rowSinkIterator = listSinkFormats.begin();
845  std::vector<bool>::const_iterator matrixIterator = convertionMatrix.begin();
846 
847  //find the row number of the sink
848  rowSinkIterator = find(listSinkFormats.begin(), listSinkFormats.end(), connectionFormat);
849  int rowNumberSink = rowSinkIterator - listSinkFormats.begin();
850 
851  //go through the convertionMatrix and find out if the conversion is possible, if yes, add connectionFormat ...
852  std::advance(matrixIterator, rowNumberSink);
853 
854  //iterate line-wise through the matrix and add more formats
855  do
856  {
857  if (*matrixIterator)
858  {
859  listFormats.push_back(listSourceFormats.at((matrixIterator - convertionMatrix.begin()) / listSinkFormats.size()));
860  }
861  std::advance(matrixIterator, listSinkFormats.size());
862  } while (convertionMatrix.end() - matrixIterator > 0);
863 
864  return listFormats.size();
865 }
866 
867 
868 void CAmRouter::getSourceSinkPossibleConnectionFormats(std::vector<CAmRoutingNode*>::iterator iteratorSource,
869  std::vector<CAmRoutingNode*>::iterator iteratorSink,
870  std::vector<am_CustomConnectionFormat_t> & outConnectionFormats)
871 {
872  CAmRoutingNode * nodeSink = *iteratorSink;
873  assert(nodeSink->getData().type==CAmNodeDataType::SINK);
874 
875  CAmRoutingNode * nodeSource = *iteratorSource;
876  assert(nodeSource->getData().type==CAmNodeDataType::SOURCE);
877 
878  am_Source_s *source = nodeSource->getData().data.source;
879  am_Sink_s *sink = nodeSink->getData().data.sink;
880  listPossibleConnectionFormats(source->listConnectionFormats, sink->listConnectionFormats, outConnectionFormats);
881 }
882 
883 
884 }
CAmRoutingNode * converterNodeWithSinkID(const am_sinkID_t sinkID, const am_domainID_t domainID)
Returns a converter node for given sinkID.
Definition: CAmRouter.cpp:248
CAmRoutingNode * sourceNodeWithID(const am_sourceID_t sourceID)
Returns a source node with given sourceID.
Definition: CAmRouter.cpp:224
virtual am_Error_e enumerateSources(std::function< void(const am_Source_s &element)> cb) const =0
am_sourceID_t sourceID
the source ID
am_Error_e
the errors of the audiomanager.
void getShortestPath(const CAmNode< T > &source, const CAmListNodePtrs &listTargets, std::vector< CAmListNodePtrs > &resultPath)
Finds the shortest path from given node to all nodes in listTargets.
Definition: CAmGraph.h:519
void connectNodes(const CAmNode< T > &first, const CAmNode< T > &last, const V &vertexData, const int16_t weight=1)
Connect first with last node and set user data and weight to the vertex.
Definition: CAmGraph.h:446
This struct describes the attribiutes of a sink.
NodeData & getData()
Setters and getters.
Definition: CAmGraph.h:91
am_CustomConnectionFormat_t connectionFormat
the connectionformat that is used for the route
am_sinkID_t sinkID
This is the ID of the sink, it is unique in the system.
CAmNode< T > & addNode(const T &in)
Adds a new node to the graph with given user data.
Definition: CAmGraph.h:375
am_domainID_t controlDomainID
This is the ID of the domain that registers the gateway.
am_NodeDataType_e type
data type:sink, source, gateway or converter
Definition: CAmRouter.h:77
uint16_t am_CustomConnectionFormat_t
This type classifies the format in which data is exchanged within a connection.
am_sourceID_t sourceID
the sourceID where the route starts
union am::am_RoutingNodeData_s::@0 data
union pointer to sink, source, gateway or converter
static bool getRestrictedOutputFormats(const std::vector< bool > &convertionMatrix, const std::vector< am_CustomConnectionFormat_t > &listSourceFormats, const std::vector< am_CustomConnectionFormat_t > &listSinkFormats, const am_CustomConnectionFormat_t connectionFormat, std::vector< am_CustomConnectionFormat_t > &listFormats)
Definition: CAmRouter.cpp:837
am_Error_e getAllPaths(CAmRoutingNode &aSource, CAmRoutingNode &aSink, std::vector< am_Route_s > &resultPath, std::vector< std::vector< CAmRoutingNode * >> &resultNodesPath, const bool includeCycles=false)
Definition: CAmRouter.cpp:627
typedef GES_IN_PROGRESS
Definition: CAmGraph.h:48
A_CONST am_CustomConnectionFormat_t CF_UNKNOWN
SPDX license identifier: MPL-2.0.
virtual am_Error_e enumerateConverters(std::function< void(const am_Converter_s &element)> cb) const =0
GRAPH_PATH_END am_GraphPathPosition_e
Definition: CAmGraph.h:58
am_sinkID_t sinkID
the sinkID
am_Error_e getConnectionFormatChoice(const am_sourceID_t sourceID, const am_sinkID_t sinkID, const am_Route_s listRoute, const std::vector< am_CustomConnectionFormat_t > listPossibleConnectionFormats, std::vector< am_CustomConnectionFormat_t > &listPrioConnectionFormats)
SPDX license identifier: MPL-2.0.
am_Source_s * source
Definition: CAmRouter.h:80
virtual am_Error_e getSinkInfoDB(const am_sinkID_t sinkID, am_Sink_s &sinkData) const =0
CAmRoutingNode * sinkNodeWithID(const am_sinkID_t sinkID)
Returns a sink node with given sinkID.
Definition: CAmRouter.cpp:200
static void listPossibleConnectionFormats(std::vector< am_CustomConnectionFormat_t > &inListSourceFormats, std::vector< am_CustomConnectionFormat_t > &inListSinkFormats, std::vector< am_CustomConnectionFormat_t > &outListFormats)
Definition: CAmRouter.cpp:826
This represents one "hopp" in a route.
SPDX license identifier: MPL-2.0.
am_domainID_t domainID
The domainID is the domain the source belongs to.
am_Gateway_s * gateway
Definition: CAmRouter.h:82
uint16_t am_sourceID_t
a source ID
CAmRouter(IAmDatabaseHandler *iDatabaseHandler, CAmControlSender *iSender)
Definition: CAmRouter.cpp:56
sends data to the commandInterface, takes the file of the library that needs to be loaded ...
static bool getAllowedFormatsFromConvMatrix(const std::vector< bool > &convertionMatrix, const std::vector< am_CustomConnectionFormat_t > &listSourceFormats, const std::vector< am_CustomConnectionFormat_t > &listSinkFormats, std::vector< am_CustomConnectionFormat_t > &sourceFormats, std::vector< am_CustomConnectionFormat_t > &sinkFormats)
Definition: CAmRouter.cpp:796
void trace(std::function< void(const CAmNode< T > &, const std::vector< CAmVertex< T, V > * > &)> cb)
Goes through all nodes and vertices and calls the callback.
Definition: CAmGraph.h:500
void getMergeConnectionFormats(const X *element, const am_CustomConnectionFormat_t connectionFormat, const std::vector< am_CustomConnectionFormat_t > &listConnectionFormats, std::vector< am_CustomConnectionFormat_t > &outListMergeConnectionFormats)
Definition: CAmRouter.cpp:39
This class handles and abstracts the database.
This struct describes the attributes of a converter.
CAmNode< am_RoutingNodeData_s > CAmRoutingNode
Definition: CAmRouter.h:140
std::vector< am_RoutingElement_s > route
the actual route as list of routing elements
a list of routing elements that lead from source to sink
virtual am_Error_e enumerateSinks(std::function< void(const am_Sink_s &element)> cb) const =0
am_sourceID_t sourceID
This is the ID of the source, it is unique in the system.
the desired action is not possible
am_Converter_s * converter
Definition: CAmRouter.h:83
std::list< CAmRoutingVertex > CAmRoutingListVertices
Definition: CAmRouter.h:143
virtual am_Error_e enumerateGateways(std::function< void(const am_Gateway_s &element)> cb) const =0
am_domainID_t domainID
This is the ID of the domain that registers the converter.
void clear()
Clears all nodes and vertices.
Definition: CAmGraph.h:488
This struct describes the attributes of a gateway.
am_sinkID_t sinkID
the sinkID where the route ends
CAmRoutingNode * gatewayNodeWithSinkID(const am_sinkID_t sinkID)
Returns a gateway node for given sinkID.
Definition: CAmRouter.cpp:260
uint16_t getIndex() const
Definition: CAmGraph.h:92
uint16_t am_domainID_t
a domain ID
no error - positive reply
SPDX license identifier: MPL-2.0.
void getAllPaths(const CAmNode< T > &src, const CAmNode< T > &dst, std::function< void(const CAmNodeReferenceList &path)> cb)
Finds all possible paths between two given nodes.
Definition: CAmGraph.h:618
void getShortestPath(const CAmRoutingNode &source, const CAmRoutingNode &destination, std::vector< CAmRoutingNode * > &resultPath)
std::vector< am_CustomConnectionFormat_t > listConnectionFormats
This list holds information about the formats that the Source is capable of supporting when deliverin...
This struct describes the attribiutes of a source.
virtual am_Error_e getSourceInfoDB(const am_sourceID_t sourceID, am_Source_s &sourceData) const =0
uint16_t am_sinkID_t
a sink ID
const CAmVertexReferenceList & getVertexList() const
Definition: CAmGraph.h:326
CAmVertex< am_RoutingNodeData_s, uint16_t > CAmRoutingVertex
Definition: CAmRouter.h:142
am_domainID_t domainID
The domainID is the domain the sink belongs to.
am_domainID_t domainID
the domainID the routeElement is in
static void getSourceSinkPossibleConnectionFormats(std::vector< CAmRoutingNode * >::iterator iteratorSource, std::vector< CAmRoutingNode * >::iterator iteratorSink, std::vector< am_CustomConnectionFormat_t > &outConnectionFormats)
Definition: CAmRouter.cpp:868
am_Error_e getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector< am_Route_s > &returnList)
Finds all possible paths between given source and sink.
Definition: CAmRouter.cpp:82
static bool shouldGoInDomain(const std::vector< am_domainID_t > &visitedDomains, const am_domainID_t nodeDomainID)
Definition: CAmRouter.cpp:708
std::vector< am_CustomConnectionFormat_t > listConnectionFormats
This list holds information about the formats that the Source is capable of supporting when deliverin...
void load(const bool onlyFree)
Definition: CAmRouter.cpp:128
A structure used as user data in the graph nodes.
Definition: CAmRouter.h:74