/** * Copyright (C) 2012, BMW AG * * This file is part of GENIVI Project AudioManager. * * Contributions are licensed to the GENIVI Alliance under one or more * Contribution License Agreements. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Christian Mueller, christian.ei.mueller@bmw.de BMW 2011,2012 * \author Aleksandar Donchev, Aleksander.Donchev@partner.bmw.de BMW 2013,2014 * * \file CAmRouter.h * For further information see http://www.genivi.org/. * */ #ifndef ROUTER_H_ #define ROUTER_H_ #include #include #include "audiomanagertypes.h" #include "CAmGraph.h" #include "IAmDatabaseHandler.h" namespace am { /** * Optimal path search between a source and a sink is implemented with a graph which contains nodes - sinks, sources, gateways, converters. * * If EXTENDED_ROUTING_GRAPH is defined the graph will contain nodes, which are identified by sinkID, sourceID, gatewayID, converterID and connectionFormat. * All possible connections between all nodes (1 connection is 1 connection format) are represented in the graph (Node[id=1, connectionFormat=1] ---> Node[id=2, connectionFormat=1]). * * If EXTENDED_ROUTING_GRAPH is NOT defined the graph will contain nodes, which are identified by sinkID, sourceID, gatewayID, converterID. * A possible connection between two nodes represents the facts that the nodes can be connected with one or more connectionFormats (Node[id=1] ---> Node[id=2]). * It is assumption that the two nodes can be connected. The controller itself decides later whether the connection is possible or not. This is default. * */ #undef EXTENDED_ROUTING_GRAPH /** * Trace on/off. */ #undef TRACE_GRAPH class CAmRouter; /** * A structure used as user data in the graph nodes. */ struct am_RoutingNodeData_s { typedef enum:uint8_t {SINK, SOURCE, GATEWAY, CONVERTER} am_NodeDataType_e; am_NodeDataType_e type; //!< data type:sink, source, gateway or converter #ifdef EXTENDED_ROUTING_GRAPH am_CustomConnectionFormat_t inConnectionFormat; //!< input connection format for sink, source, gateway or converter am_CustomConnectionFormat_t outConnectionFormat; //!< output connection format usually for gateways and converters #endif union { am_Source_s *source; am_Sink_s *sink; am_Gateway_s *gateway; am_Converter_s *converter; } data; //!< union pointer to sink, source, gateway or converter am_RoutingNodeData_s():type(SINK) #ifdef EXTENDED_ROUTING_GRAPH ,inConnectionFormat(CF_UNKNOWN) ,outConnectionFormat(CF_UNKNOWN) #endif {} bool operator==(const am_RoutingNodeData_s & anotherObject) const { bool result = false; if(type==anotherObject.type) { #ifdef EXTENDED_ROUTING_GRAPH result = (inConnectionFormat==anotherObject.inConnectionFormat && outConnectionFormat==anotherObject.outConnectionFormat); #else result = true; #endif if(type==SINK) result &= (data.sink->sinkID==anotherObject.data.sink->sinkID); else if(type==SOURCE) result &= (data.source->sourceID==anotherObject.data.source->sourceID); else if(type==GATEWAY) result &= (data.gateway->gatewayID==anotherObject.data.gateway->gatewayID); else if(type==CONVERTER) result &= (data.converter->converterID==anotherObject.data.converter->converterID); } return result; }; #ifdef TRACE_GRAPH void trace() const { if(type==SINK) std::cout << "[SINK:" << data.sink->sinkID << ":" << data.sink->name #ifdef EXTENDED_ROUTING_GRAPH << "(" << inConnectionFormat << "," << outConnectionFormat << ")" #endif << "]"; else if(type==SOURCE) std::cout << "[SOUR:" << data.source->sourceID << ":" << data.source->name #ifdef EXTENDED_ROUTING_GRAPH << "(" << inConnectionFormat << "," << outConnectionFormat << ")" #endif << "]"; else if(type==GATEWAY) std::cout << "[GATE:" << data.gateway->gatewayID << ":" << data.gateway->name #ifdef EXTENDED_ROUTING_GRAPH << "(" << inConnectionFormat << "," << outConnectionFormat << ")" #endif << "]"; else if(type==CONVERTER) std::cout << "[CONV:" << data.converter->converterID << ":" << data.converter->name #ifdef EXTENDED_ROUTING_GRAPH << "(" << inConnectionFormat << "," << outConnectionFormat << ")" #endif << "]"; }; #endif }; #define NodeDataType am_RoutingNodeData_s::am_NodeDataType_e class CAmControlSender; /** * Implements an autorouting algorithm for connecting sinks and sources via different audio domains. */ class CAmRouter { IAmDatabaseHandler* mpDatabaseHandler; //!< pointer to database handler CAmControlSender* mpControlSender; //!< pointer the controlsender - is used to retrieve information for the optimal route bool mOnlyFreeConversionNodes; //!< bool flag whether only disconnected elements should be considered or not CAmGraph mRoutingGraph; //!< graph object std::vector*> mNodeListSources; //!< vector with pointers to nodes with sources, used for quick access std::vector*> mNodeListSinks; //!< vector with pointers to nodes with sinks, used for quick access std::vector*> mNodeListGateways; //!< vector with pointers to nodes with gateways, used for quick access std::vector*> mNodeListConverters;//!< vector with pointers to nodes with converters, used for quick access std::map mNodeListSourceStatus; //!< vector with flags preventing going through group of nodes during the path search std::map mNodeListSinkStatus; //!< vector with flags preventing going through group of nodes during the path search std::map mNodeListConverterStatus; //!< vector with flags preventing going through group of nodes during the path search std::map mNodeListGatewayStatus; //!< vector with flags preventing going through group of nodes during the path search #ifdef EXTENDED_ROUTING_GRAPH am_Source_s *mpRootSource; //!< pointer to source am_Sink_s *mpRootSink; //!< pointer to sink /* * Methods for getting shortest path from the graph. */ void getShortestPath(const am_Source_s & aSource, const am_Sink_s & aSink, std::vector*>> & resultPath); void getShortestPath(std::vector*>> & resultPath); void getShortestPath(const am_Source_s & aSource, const am_Sink_s & aSink, std::vector & resultPath, std::vector*>> & resultNodesPath); void getShortestPath(std::vector & routes, std::vector*>> & nodes); /** * Returns a sink node with given sinkID and connection format. * * @param sinkID sink id. * @param connectionFormat connection format. * @return pointer to node or NULL. */ CAmNode* sinkNodeWithID(const am_sinkID_t sinkID, const am_CustomConnectionFormat_t connectionFormat); /** * Returns a source node with given sourceID and connection format. * * @param sourceID source id. * @param connectionFormat connection format. * @return pointer to node or NULL. */ CAmNode* sourceNodeWithID(const am_sourceID_t sourceID, const am_CustomConnectionFormat_t connectionFormat); #else CAmNode *mpRootSource; //!< pointer to source node CAmNode *mpRootSink; //!< pointer to sink node am_Error_e determineConnectionFormatsForPath(am_Route_s & routeObjects, std::vector*> & nodes); am_Error_e doConnectionFormatsForPath(am_Route_s & routeObjects, std::vector*> & route, std::vector::iterator routingElementIterator, std::vector*>::iterator routeIterator); void getShortestPath(const CAmNode & source, const CAmNode & destination, std::vector*> & resultPath); void getShortestPath(std::vector*> & resultPath); void getShortestPath(CAmNode & aSource, CAmNode & aSink, am_Route_s & resultPath, std::vector*> & resultNodesPath); void getShortestPath(am_Route_s & resultPath, std::vector*> & resultNodesPath); am_Error_e getAllPaths(CAmNode & aSource, CAmNode & aSink, std::vector & resultPath, std::vector*>> & resultNodesPath); am_Error_e getAllPaths(std::vector & resultPath, std::vector*>> & resultNodesPath); /** * Returns a sink node with given sinkID. * * @param sinkID sink id. * @return pointer to node or NULL. */ CAmNode* sinkNodeWithID(const am_sinkID_t sinkID); /** * Returns a source node with given sourceID. * * @param sourceID source id. * @return pointer to node or NULL. */ CAmNode* sourceNodeWithID(const am_sourceID_t sourceID); #endif /** * Makes connection between two nodes. * * @param node1. * @param node2. * @param vertexData associated data. * @param weight connection weight used for finding optimal path. */ void connectNodes(const CAmNode & node1, const CAmNode & node2, const am_CustomConnectionFormat_t vertexData, const int16_t weight = 1); /** * Builds path in a domain from source to sink. * * @param aSource starting point. * @param aSink ending point. */ bool routeInSameDomain(CAmNode & aSource, CAmNode & aSink); /** * Builds path from source to sink when the source and the sink belongs to different domains. * * @param aSource starting point. * @param aSink ending point. */ bool routeInAnotherDomain(CAmNode & aSource, CAmNode & aSink); void clear(); /** * Fills the graph with nodes and connections. * * @param aSource starting point. * @param aSink ending point. */ void buildGraph(const am_Source_s & aSource, const am_Sink_s & aSink); template bool isComponentConnected(const Component & comp) { return mpDatabaseHandler->isComponentConnected(comp); } public: CAmRouter(IAmDatabaseHandler* iDatabaseHandler, CAmControlSender* iSender); ~CAmRouter(); /** * Finds all possible paths between given source and sink. * * @param onlyfree only disconnected elements should be included or not. * @param sourceID starting point. * @param sinkID ending point. * @param returnList list with all possible paths * @return E_OK on success(0 or more paths) or E_NOT_POSSIBLE on failure. */ am_Error_e getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector& returnList); am_Error_e getRoute(const bool onlyfree, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector & listRoutes); /** * Helper methods. */ static bool getAllowedFormatsFromConvMatrix(const std::vector & convertionMatrix, const std::vector & listSourceFormats, const std::vector & listSinkFormats, std::vector & sourceFormats, std::vector & sinkFormats); static bool getRestrictedOutputFormats(const std::vector & convertionMatrix, const std::vector & listSourceFormats, const std::vector & listSinkFormats, const am_CustomConnectionFormat_t connectionFormat, std::vector & listFormats); static void listPossibleConnectionFormats(std::vector & inListSourceFormats, std::vector & inListSinkFormats, std::vector & outConnectionFormats); }; } /* namespace am */ #endif /* ROUTER_H_ */