diff options
Diffstat (limited to 'AudioManagerCore/include')
-rw-r--r-- | AudioManagerCore/include/CAmCommandSender.h | 13 | ||||
-rw-r--r-- | AudioManagerCore/include/CAmDatabaseHandlerMap.h | 168 | ||||
-rw-r--r-- | AudioManagerCore/include/CAmDatabaseObserver.h | 87 | ||||
-rw-r--r-- | AudioManagerCore/include/CAmGraph.h | 161 | ||||
-rw-r--r-- | AudioManagerCore/include/CAmRouter.h | 606 | ||||
-rw-r--r-- | AudioManagerCore/include/CAmRoutingSender.h | 5 | ||||
-rw-r--r-- | AudioManagerCore/include/IAmDatabaseHandler.h | 34 |
7 files changed, 582 insertions, 492 deletions
diff --git a/AudioManagerCore/include/CAmCommandSender.h b/AudioManagerCore/include/CAmCommandSender.h index 82363de..caa72ad 100644 --- a/AudioManagerCore/include/CAmCommandSender.h +++ b/AudioManagerCore/include/CAmCommandSender.h @@ -29,21 +29,24 @@ #endif #include "IAmCommand.h" +#include "CAmDatabaseHandlerMap.h" +#include "CAmSerializer.h" namespace am { class CAmCommandReceiver; +class CAmCommandSender; /** * This class is used to send data to the CommandInterface. * All loaded plugins will be called when a callback is invoked. */ -class CAmCommandSender +class CAmCommandSender: public CAmDatabaseHandlerMap::AmDatabaseObserverCallbacks { public: - CAmCommandSender(const std::vector<std::string>& listOfPluginDirectories); + CAmCommandSender(const std::vector<std::string>& listOfPluginDirectories, CAmSocketHandler *iSocketHandler); ~CAmCommandSender(); am_Error_e startupInterfaces(CAmCommandReceiver* iCommandReceiver); void setCommandReady(); @@ -78,14 +81,18 @@ public: friend class IAmCommandBackdoor; //this is to get access to the loaded plugins and be able to exchange the interfaces #endif private: + void unloadLibraries(void); //!< unload the shared libraries std::vector<IAmCommandSend*> mListInterfaces; //!< list of all interfaces std::vector<void*> mListLibraryHandles; //!< list of all library handles. This information is used to unload the plugins correctly. std::vector<std::string> mListLibraryNames; //!< list of all library names. This information is used for getListPlugins. - + CAmCommandReceiver *mCommandReceiver; + CAmSerializer mSerializer; }; + + } #endif /* COMMANDSENDER_H_ */ diff --git a/AudioManagerCore/include/CAmDatabaseHandlerMap.h b/AudioManagerCore/include/CAmDatabaseHandlerMap.h index 05443b1..3909b05 100644 --- a/AudioManagerCore/include/CAmDatabaseHandlerMap.h +++ b/AudioManagerCore/include/CAmDatabaseHandlerMap.h @@ -74,6 +74,51 @@ class CAmDatabaseHandlerMap : public IAmDatabaseHandler public: CAmDatabaseHandlerMap(); virtual ~CAmDatabaseHandlerMap(); + + /** + * Database observer. + */ + struct AmDatabaseObserverCallbacks: public IAmDatabaseObserver + { + protected: + std::function<void()> dboNumberOfSinkClassesChanged; + std::function<void()> dboNumberOfSourceClassesChanged; + std::function<void(const am_Sink_s&)> dboNewSink; + std::function<void(const am_Source_s&)> dboNewSource; + std::function<void(const am_Domain_s& )> dboNewDomain; + std::function<void (const am_Gateway_s& )> dboNewGateway; + std::function<void (const am_Converter_s& )> dboNewConverter; + std::function<void (const am_Crossfader_s& )> dboNewCrossfader; + std::function<void (const am_MainConnectionType_s& )> dboNewMainConnection; + std::function<void (const am_mainConnectionID_t )> dboRemovedMainConnection; + std::function<void (const am_sinkID_t , const bool )> dboRemovedSink; + std::function<void (const am_sourceID_t , const bool )> dboRemovedSource; + std::function<void (const am_domainID_t )> dboRemoveDomain; + std::function<void (const am_gatewayID_t )> dboRemoveGateway; + std::function<void (const am_converterID_t )> dboRemoveConverter; + std::function<void (const am_crossfaderID_t )> dboRemoveCrossfader; + std::function<void (const am_mainConnectionID_t , const am_ConnectionState_e )> dboMainConnectionStateChanged; + std::function<void (const am_sinkID_t , const am_MainSoundProperty_s& )> dboMainSinkSoundPropertyChanged; + std::function<void (const am_sourceID_t , const am_MainSoundProperty_s& )> dboMainSourceSoundPropertyChanged; + std::function<void (const am_sinkID_t , const am_Availability_s& )> dboSinkAvailabilityChanged; + std::function<void (const am_sourceID_t , const am_Availability_s& )> dboSourceAvailabilityChanged; + std::function<void (const am_sinkID_t , const am_mainVolume_t )> dboVolumeChanged; + std::function<void (const am_sinkID_t , const am_MuteState_e )> dboSinkMuteStateChanged; + std::function<void (const am_SystemProperty_s& )>dboSystemPropertyChanged; + std::function<void (const am_mainConnectionID_t , const am_timeSync_t )>dboTimingInformationChanged; + std::function<void (const am_sinkID_t , const am_sinkClass_t , const std::vector<am_MainSoundProperty_s>& , const bool )>dboSinkUpdated; + std::function<void (const am_sourceID_t , const am_sourceClass_t , const std::vector<am_MainSoundProperty_s>& , const bool )>dboSourceUpdated; + std::function<void (const am_sinkID_t , const am_NotificationConfiguration_s )> dboSinkMainNotificationConfigurationChanged; + std::function<void (const am_sourceID_t , const am_NotificationConfiguration_s )> dboSourceMainNotificationConfigurationChanged; + public: + friend class CAmDatabaseHandlerMap; + AmDatabaseObserverCallbacks():IAmDatabaseObserver(), mpDatabaseHandler(nullptr) {} + virtual ~AmDatabaseObserverCallbacks(){ if(mpDatabaseHandler) mpDatabaseHandler->unregisterObserver(this);} + protected: + CAmDatabaseHandlerMap *mpDatabaseHandler; + + }; + am_Error_e enterDomainDB(const am_Domain_s& domainData, am_domainID_t& domainID); am_Error_e enterMainConnectionDB(const am_MainConnection_s& mainConnectionData, am_mainConnectionID_t& connectionID); am_Error_e enterSinkDB(const am_Sink_s& sinkData, am_sinkID_t& sinkID); @@ -196,7 +241,6 @@ public: bool existConverter(const am_converterID_t converterID) const; bool existSinkClass(const am_sinkClass_t sinkClassID) const; bool existSourceClass(const am_sourceClass_t sourceClassID) const; - void registerObserver(CAmDatabaseObserver *iObserver); bool sourceVisible(const am_sourceID_t sourceID) const; bool sinkVisible(const am_sinkID_t sinkID) const; bool isComponentConnected(const am_Gateway_s & gateway) const; @@ -206,6 +250,11 @@ public: am_Error_e enumerateSinks(std::function<void(const am_Sink_s & element)> cb) const; am_Error_e enumerateGateways(std::function<void(const am_Gateway_s & element)> cb) const; am_Error_e enumerateConverters(std::function<void(const am_Converter_s & element)> cb) const; + + bool registerObserver(IAmDatabaseObserver * iObserver); + bool unregisterObserver(IAmDatabaseObserver * iObserver); + unsigned countObservers(); + /** * The following structures extend the base structures with the field 'reserved'. */ @@ -276,55 +325,55 @@ public: AM_SUBCLASS_COPY_OP_END()\ AM_SUBCLASS_OP(Subclass, Class)\ - +private: AM_TYPEDEF_SUBCLASS_RESERVED_FLAG_BEGIN(am_Domain_Database_s,am_Domain_s) - AM_SUBCLASS_END(CAmDomain) + AM_SUBCLASS_END(AmDomain) AM_TYPEDEF_SUBCLASS_SOUND_PROPERTIES_BEGIN(am_Sink_Database_s,am_Sink_s) void getSinkType(am_SinkType_s & sinkType) const;\ - AM_SUBCLASS_END(CAmSink) + AM_SUBCLASS_END(AmSink) AM_TYPEDEF_SUBCLASS_SOUND_PROPERTIES_BEGIN(am_Source_Database_s,am_Source_s) void getSourceType(am_SourceType_s & sourceType) const;\ - AM_SUBCLASS_END(CAmSource) + AM_SUBCLASS_END(AmSource) AM_TYPEDEF_SUBCLASS_RESERVED_FLAG_BEGIN(am_Connection_Database_s,am_Connection_s) - AM_SUBCLASS_END(CAmConnection) + AM_SUBCLASS_END(AmConnection) /** * The following structures extend the base structures with print capabilities. */ AM_TYPEDEF_SUBCLASS_BEGIN(am_MainConnection_Database_s, am_MainConnection_s) void getMainConnectionType(am_MainConnectionType_s & connectionType) const;\ - AM_SUBCLASS_END(CAmMainConnection) + AM_SUBCLASS_END(AmMainConnection) AM_TYPEDEF_SUBCLASS_BEGIN(am_SourceClass_Database_s, am_SourceClass_s) - AM_SUBCLASS_END(CAmSourceClass) + AM_SUBCLASS_END(AmSourceClass) AM_TYPEDEF_SUBCLASS_BEGIN(am_SinkClass_Database_s, am_SinkClass_s) - AM_SUBCLASS_END(CAmSinkClass) + AM_SUBCLASS_END(AmSinkClass) AM_TYPEDEF_SUBCLASS_BEGIN(am_Gateway_Database_s, am_Gateway_s) - AM_SUBCLASS_END(CAmGateway) + AM_SUBCLASS_END(AmGateway) AM_TYPEDEF_SUBCLASS_BEGIN(am_Converter_Database_s, am_Converter_s) - AM_SUBCLASS_END(CAmConverter) + AM_SUBCLASS_END(AmConverter) AM_TYPEDEF_SUBCLASS_BEGIN(am_Crossfader_Database_s, am_Crossfader_s) - AM_SUBCLASS_END(CAmCrossfader) - - private: - typedef std::unordered_map<am_domainID_t, CAmDomain> CAmMapDomain; - typedef std::unordered_map<am_sourceClass_t, CAmSourceClass> CAmMapSourceClass; - typedef std::unordered_map<am_sinkClass_t, CAmSinkClass> CAmMapSinkClass; - typedef std::unordered_map<am_sinkID_t, CAmSink> CAmMapSink; - typedef std::unordered_map<am_sourceID_t, CAmSource> CAmMapSource; - typedef std::unordered_map<am_gatewayID_t, CAmGateway> CAmMapGateway; - typedef std::unordered_map<am_converterID_t, CAmConverter> CAmMapConverter; - typedef std::unordered_map<am_crossfaderID_t, CAmCrossfader> CAmMapCrossfader; - typedef std::unordered_map<am_connectionID_t, CAmConnection> CAmMapConnection; - typedef std::unordered_map<am_mainConnectionID_t, CAmMainConnection> CAmMapMainConnection; - typedef std::vector<am_SystemProperty_s> CAmVectorSystemProperties; + AM_SUBCLASS_END(AmCrossfader) + + + typedef std::unordered_map<am_domainID_t, AmDomain> AmMapDomain; + typedef std::unordered_map<am_sourceClass_t, AmSourceClass> AmMapSourceClass; + typedef std::unordered_map<am_sinkClass_t, AmSinkClass> AmMapSinkClass; + typedef std::unordered_map<am_sinkID_t, AmSink> AmMapSink; + typedef std::unordered_map<am_sourceID_t, AmSource> AmMapSource; + typedef std::unordered_map<am_gatewayID_t, AmGateway> AmMapGateway; + typedef std::unordered_map<am_converterID_t, AmConverter> AmMapConverter; + typedef std::unordered_map<am_crossfaderID_t, AmCrossfader> AmMapCrossfader; + typedef std::unordered_map<am_connectionID_t, AmConnection> AmMapConnection; + typedef std::unordered_map<am_mainConnectionID_t, AmMainConnection> AmMapMainConnection; + typedef std::vector<am_SystemProperty_s> AmVectorSystemProperties; /** * The following structure groups the map objects needed for the implementation. * Every map object is coupled with an identifier, which hold the current value. @@ -332,46 +381,46 @@ public: * The IDs can be increased through the method increaseID(...), which follows the AudioManager logic. * For more information about the static and dynamic IDs, please see the documentation. */ - typedef struct CAmMappedData + struct AmMappedData { /** * The structure encapsulates the id boundary and the current id value. * It defines a range within the id can vary. */ - struct am_Identifier_s + struct AmIdentifier { int16_t mMin; //!< min possible value int16_t mMax; //!< max possible value int16_t mCurrentValue; //!< current value - am_Identifier_s():mMin(DYNAMIC_ID_BOUNDARY), mMax(SHRT_MAX), mCurrentValue(mMin){}; - am_Identifier_s(const int16_t & min, const int16_t & max):mMin(min), mMax(max), mCurrentValue(mMin){assert(min<max);}; + AmIdentifier():mMin(DYNAMIC_ID_BOUNDARY), mMax(SHRT_MAX), mCurrentValue(mMin){}; + AmIdentifier(const int16_t & min, const int16_t & max):mMin(min), mMax(max), mCurrentValue(mMin){assert(min<max);}; }; - am_Identifier_s mCurrentDomainID; //!< domain ID - am_Identifier_s mCurrentSourceClassesID; //!< source classes ID - am_Identifier_s mCurrentSinkClassesID; //!< sink classes ID - am_Identifier_s mCurrentSinkID; //!< sink ID - am_Identifier_s mCurrentSourceID; //!< source ID - am_Identifier_s mCurrentGatewayID; //!< gateway ID - am_Identifier_s mCurrentConverterID; //!< converter ID - am_Identifier_s mCurrentCrossfaderID; //!< crossfader ID - am_Identifier_s mCurrentConnectionID; //!< connection ID - am_Identifier_s mCurrentMainConnectionID; //!< mainconnection ID - - CAmVectorSystemProperties mSystemProperties; //!< vector with system properties - CAmMapDomain mDomainMap; //!< map for domain structures - CAmMapSourceClass mSourceClassesMap; //!< map for source classes structures - CAmMapSinkClass mSinkClassesMap; //!< map for sink classes structures - CAmMapSink mSinkMap; //!< map for sink structures - CAmMapSource mSourceMap; //!< map for source structures - CAmMapGateway mGatewayMap; //!< map for gateway structures - CAmMapConverter mConverterMap; //!< map for converter structures - CAmMapCrossfader mCrossfaderMap; //!< map for crossfader structures - CAmMapConnection mConnectionMap; //!< map for connection structures - CAmMapMainConnection mMainConnectionMap; //!< map for main connection structures - - CAmMappedData(): //For Domain, MainConnections, Connections we don't have static IDs. + AmIdentifier mCurrentDomainID; //!< domain ID + AmIdentifier mCurrentSourceClassesID; //!< source classes ID + AmIdentifier mCurrentSinkClassesID; //!< sink classes ID + AmIdentifier mCurrentSinkID; //!< sink ID + AmIdentifier mCurrentSourceID; //!< source ID + AmIdentifier mCurrentGatewayID; //!< gateway ID + AmIdentifier mCurrentConverterID; //!< converter ID + AmIdentifier mCurrentCrossfaderID; //!< crossfader ID + AmIdentifier mCurrentConnectionID; //!< connection ID + AmIdentifier mCurrentMainConnectionID; //!< mainconnection ID + + AmVectorSystemProperties mSystemProperties; //!< vector with system properties + AmMapDomain mDomainMap; //!< map for domain structures + AmMapSourceClass mSourceClassesMap; //!< map for source classes structures + AmMapSinkClass mSinkClassesMap; //!< map for sink classes structures + AmMapSink mSinkMap; //!< map for sink structures + AmMapSource mSourceMap; //!< map for source structures + AmMapGateway mGatewayMap; //!< map for gateway structures + AmMapConverter mConverterMap; //!< map for converter structures + AmMapCrossfader mCrossfaderMap; //!< map for crossfader structures + AmMapConnection mConnectionMap; //!< map for connection structures + AmMapMainConnection mMainConnectionMap; //!< map for main connection structures + + AmMappedData(): //For Domain, MainConnections, Connections we don't have static IDs. mCurrentDomainID(DYNAMIC_ID_BOUNDARY, SHRT_MAX), mCurrentSourceClassesID(DYNAMIC_ID_BOUNDARY, SHRT_MAX), mCurrentSinkClassesID(DYNAMIC_ID_BOUNDARY, SHRT_MAX), @@ -399,7 +448,7 @@ public: * @param preferedStaticIDBoundary A limit for a given dynamic ID. Default is DYNAMIC_ID_BOUNDARY. * @return TRUE on successfully changed ID. */ - bool increaseID(int16_t & resultID, am_Identifier_s & sourceID, int16_t const desiredStaticID); + bool increaseID(int16_t & resultID, AmIdentifier & sourceID, int16_t const desiredStaticID); /** * \brief Increases the main connection ID. * @@ -426,12 +475,13 @@ public: { typename std::unordered_map<TPrintMapKey, TPrintMapObject>::const_iterator iter = t.begin(); for(; iter!=t.end(); iter++) - CAmMappedData::print(iter->second, output); + AmMappedData::print(iter->second, output); } private: - template <typename TMapKey,class TMapObject> bool getNextConnectionID(int16_t & resultID, am_Identifier_s & sourceID, + template <typename TMapKey,class TMapObject> bool getNextConnectionID(int16_t & resultID, AmIdentifier & sourceID, const std::unordered_map<TMapKey, TMapObject> & map); - } CAmMappedData; + }; + /* * Helper methods. */ @@ -469,9 +519,9 @@ public: } ); } - CAmDatabaseObserver *mpDatabaseObserver; //!< pointer to the Observer ListConnectionFormat mListConnectionFormat; //!< list of connection formats - CAmMappedData mMappedData; //!< Internal structure encapsulating all the maps used in this class + AmMappedData mMappedData; //!< Internal structure encapsulating all the maps used in this class + std::vector<AmDatabaseObserverCallbacks*> mDatabaseObservers; #ifdef UNIT_TEST public: diff --git a/AudioManagerCore/include/CAmDatabaseObserver.h b/AudioManagerCore/include/CAmDatabaseObserver.h deleted file mode 100644 index 7d18be4..0000000 --- a/AudioManagerCore/include/CAmDatabaseObserver.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * SPDX license identifier: MPL-2.0 - * - * 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 Linke, christian.linke@bmw.de BMW 2011,2012 - * - * \file CAmDatabaseObserver.h - * For further information see http://www.genivi.org/. - * - */ - -#ifndef DATABASEOBSERVER_H_ -#define DATABASEOBSERVER_H_ - -#include "audiomanagertypes.h" -#include <queue> -#include "CAmSerializer.h" - -namespace am -{ - -class CAmTelnetServer; -class CAmCommandSender; -class CAmRoutingSender; -class CAmSocketHandler; - -/** - * This class observes the Database and notifies other classes about important events, mainly the CommandSender. - */ -class CAmDatabaseObserver -{ -public: - CAmDatabaseObserver(CAmCommandSender *iCommandSender, CAmRoutingSender *iRoutingSender, CAmSocketHandler *iSocketHandler); - CAmDatabaseObserver(CAmCommandSender *iCommandSender, CAmRoutingSender *iRoutingSender, CAmSocketHandler *iSocketHandler, CAmTelnetServer *iTelnetServer); - ~CAmDatabaseObserver(); - void numberOfSinkClassesChanged(); - void numberOfSourceClassesChanged(); - void newSink(const am_Sink_s& sink); - void newSource(const am_Source_s& source); - void newDomain(const am_Domain_s& domain); - void newGateway(const am_Gateway_s& gateway); - void newConverter(const am_Converter_s& coverter); - void newCrossfader(const am_Crossfader_s& crossfader); - void newMainConnection(const am_MainConnectionType_s& mainConnection); - void removedMainConnection(const am_mainConnectionID_t mainConnection); - void removedSink(const am_sinkID_t sinkID, const bool visible); - void removedSource(const am_sourceID_t sourceID, const bool visible); - void removeDomain(const am_domainID_t domainID); - void removeGateway(const am_gatewayID_t gatewayID); - void removeConverter(const am_converterID_t converterID); - void removeCrossfader(const am_crossfaderID_t crossfaderID); - void mainConnectionStateChanged(const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState); - void mainSinkSoundPropertyChanged(const am_sinkID_t sinkID, const am_MainSoundProperty_s& SoundProperty); - void mainSourceSoundPropertyChanged(const am_sourceID_t sourceID, const am_MainSoundProperty_s& SoundProperty); - void sinkAvailabilityChanged(const am_sinkID_t sinkID, const am_Availability_s& availability); - void sourceAvailabilityChanged(const am_sourceID_t sourceID, const am_Availability_s& availability); - void volumeChanged(const am_sinkID_t sinkID, const am_mainVolume_t volume); - void sinkMuteStateChanged(const am_sinkID_t sinkID, const am_MuteState_e muteState); - void systemPropertyChanged(const am_SystemProperty_s& SystemProperty); - void timingInformationChanged(const am_mainConnectionID_t mainConnection, const am_timeSync_t time); - void sinkUpdated(const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible); - void sourceUpdated(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible); - void sinkMainNotificationConfigurationChanged(const am_sinkID_t sinkID, const am_NotificationConfiguration_s mainNotificationConfiguration); - void sourceMainNotificationConfigurationChanged(const am_sourceID_t sourceID, const am_NotificationConfiguration_s mainNotificationConfiguration); - -private: - CAmCommandSender *mCommandSender; //!< pointer to the comandSender - CAmRoutingSender* mRoutingSender; //!< pointer to the routingSender - CAmTelnetServer* mTelnetServer; //!< pointer to the telnetserver - CAmSerializer mSerializer; //!< serializer to handle the CommandInterface via the mainloop -}; - -} - -#endif /* DATABASEOBSERVER_H_ */ diff --git a/AudioManagerCore/include/CAmGraph.h b/AudioManagerCore/include/CAmGraph.h index ff4a09c..45043f7 100644 --- a/AudioManagerCore/include/CAmGraph.h +++ b/AudioManagerCore/include/CAmGraph.h @@ -89,6 +89,7 @@ namespace am * Setters and getters. */ NodeData & getData() { return mData; } + const NodeData & getData() const { return mData; } uint16_t getIndex() const { return mIndex; } void setIndex(uint16_t index) { mIndex = index; } }; @@ -120,13 +121,13 @@ namespace am typedef typename std::vector<CAmNode<T>*> CAmListNodePtrs; typedef typename std::list<CAmVertex<T,V>> CAmListVertices; typedef typename std::list<CAmVertex<T,V>>::iterator CAmListVerticesItr; - typedef typename std::list<CAmVertex<T,V>>::const_iterator CAmListVerticesItrConst; - typedef typename std::list<CAmListVertices> CAmNodesAdjList; - typedef typename std::list<CAmListVertices>::iterator CAmNodesAdjListItr; - typedef typename std::list<CAmListVertices>::const_iterator CAmNodesAdjListItrConst; - typedef typename std::list<CAmNode<T>> CAmListNodes; - typedef typename std::list<CAmNode<T>>::iterator CAmListNodesItr; - typedef typename std::list<CAmNode<T>>::const_iterator CAmListNodesItrConst; + typedef typename std::list<CAmVertex<T,V>>::const_iterator CAmListVerticesItrConst; + typedef typename std::list<CAmListVertices> CAmNodesAdjList; + typedef typename std::list<CAmListVertices>::iterator CAmNodesAdjListItr; + typedef typename std::list<CAmListVertices>::const_iterator CAmNodesAdjListItrConst; + typedef typename std::list<CAmNode<T>> CAmListNodes; + typedef typename std::list<CAmNode<T>>::iterator CAmListNodesItr; + typedef typename std::list<CAmNode<T>>::const_iterator CAmListNodesItrConst; typedef typename std::vector<CAmNode<T>*> CAmNodeReferenceList; typedef typename std::vector<CAmListVertices*> CAmVertexReferenceList; @@ -136,6 +137,24 @@ namespace am CAmVertexReferenceList mPointersAdjList; //!< CAmVertexReferenceList vector with pointers to vertices for direct access bool mIsCyclic; //!< bool the graph has cycles or not + struct IterateThroughAllNodesDelegate + { + CAmNode<T> * source; + CAmNode<T> * destination; + CAmNodeReferenceList visited; + std::function<bool(const CAmNode<T> * )> shouldVisitNode; + std::function<void(const CAmNode<T> *)> willVisitNode; + std::function<void(const CAmNode<T> *)> didVisitNode; + std::function<void(const CAmNodeReferenceList & path)> didFindPath; + }; + + struct VisitNodeDelegate + { + CAmNode<T> * source; + CAmNode<T> * destination; + std::function<void(const am_GraphPathPosition_e, CAmNode<T> &)> visitedNode; + }; + /** * Updates the node indexes after adding or removing nodes. * @@ -162,7 +181,7 @@ namespace am typedef uint16_t vertex_t; typedef uint16_t weight_t; - void findShortestsPathsFromNode(const CAmNode<T> & node, std::vector<weight_t> &minDistance, std::vector<CAmNode<T> *> &previous) + void findShortestPathsFromNode(const CAmNode<T> & node, std::vector<weight_t> &minDistance, std::vector<CAmNode<T> *> &previous) { typename CAmListVertices::const_iterator nIter; CAmListVertices * neighbors; @@ -256,32 +275,40 @@ namespace am } /** - * Generates list with all possible paths to given destination node after findShortestsPathsFromNode has been called. - * Finding paths is observed through the callback. The caller is informed after a new path has been found. + * Iterate through the nodes and generate all paths to given node. * * @param dst end node. * @param visited vector with current path. - * @param cb callback which is mostly used for constructing. + * @param delegate enumeration delegate. */ - void goThroughAllPaths(const CAmNode<T> & dst, std::vector<CAmNode<T>*> & visited, std::function<void(const CAmNodeReferenceList & path)> cb) + void findAllPaths(IterateThroughAllNodesDelegate & delegate) { - CAmListVertices * nodes = mPointersAdjList[visited.back()->getIndex()]; + CAmListVertices * nodes = mPointersAdjList[delegate.visited.back()->getIndex()]; CAmListVerticesItrConst vItr(nodes->begin()); + + CAmVertex<T,V> * pNextVertex; + CAmNode<T> * pNextNode; for (; vItr != nodes->end(); ++vItr) { - const CAmVertex<T,V> & vertex = (*vItr); - if(vertex.getNode()->getStatus()!=GES_NOT_VISITED) + pNextVertex = (CAmVertex<T,V> *)&(*vItr); + pNextNode = pNextVertex->getNode(); + if( + pNextNode->getStatus()!=GES_NOT_VISITED || + !delegate.shouldVisitNode(pNextNode) + ) continue; - if (vertex.getNode()==&dst) + if (pNextNode==delegate.destination) { - vertex.getNode()->setStatus(GES_IN_PROGRESS); - visited.push_back(vertex.getNode()); + delegate.willVisitNode(pNextNode); + pNextNode->setStatus(GES_IN_PROGRESS); + delegate.visited.push_back(pNextNode); //notify observer - cb(visited); + delegate.didFindPath(delegate.visited); //remove last node from the list - auto last = visited.end()-1; - visited.erase(last); - vertex.getNode()->setStatus(GES_NOT_VISITED); + auto last = delegate.visited.end()-1; + delegate.visited.erase(last); + pNextNode->setStatus(GES_NOT_VISITED); + delegate.didVisitNode(pNextNode); break; } } @@ -289,20 +316,28 @@ namespace am //bfs like loop for (; vItr != nodes->end(); ++vItr) { - const CAmVertex<T,V> & vertex = (*vItr); - if(vertex.getNode()->getStatus()!=GES_NOT_VISITED||vertex.getNode()==&dst) + pNextVertex = (CAmVertex<T,V> *)&(*vItr); + pNextNode = pNextVertex->getNode(); + + if(pNextNode->getStatus()!=GES_NOT_VISITED || + pNextNode==delegate.destination || + !delegate.shouldVisitNode(pNextNode) + ) continue; - vertex.getNode()->setStatus(GES_IN_PROGRESS); - visited.push_back(vertex.getNode()); - goThroughAllPaths(dst, visited, cb); + delegate.willVisitNode(pNextNode); + pNextNode->setStatus(GES_IN_PROGRESS); + delegate.visited.push_back(pNextNode); + findAllPaths(delegate); //remove last node from the list - auto last = visited.end()-1; - visited.erase(last); - vertex.getNode()->setStatus(GES_NOT_VISITED); + auto last = delegate.visited.end()-1; + delegate.visited.erase(last); + pNextNode->setStatus(GES_NOT_VISITED); + delegate.didVisitNode(pNextNode); } } public: + explicit CAmGraph(const std::vector<T> &v):mStoreNodes(), mStoreAdjList(), mPointersNodes(), mPointersAdjList() { typedef typename std::vector<T>::const_iterator inItr; @@ -374,12 +409,12 @@ namespace am */ CAmNode<T> & addNode(const T & in) { - size_t index = mStoreNodes.size(); - mStoreNodes.emplace_back(in, index); - mStoreAdjList.emplace_back(); - mPointersNodes.push_back(&mStoreNodes.back()); - mPointersAdjList.push_back(&mStoreAdjList.back()); - return mStoreNodes.back(); + size_t index = mStoreNodes.size(); + mStoreNodes.emplace_back(in, index); + mStoreAdjList.emplace_back(); + mPointersNodes.push_back(&mStoreNodes.back()); + mPointersAdjList.push_back(&mStoreAdjList.back()); + return mStoreNodes.back(); } /** @@ -428,16 +463,16 @@ namespace am */ void removeNode(const CAmNode<T> & node) { - uint16_t index = node.getIndex(); - removeAllVerticesToNode(node); - mPointersAdjList.erase(mPointersAdjList.begin()+index); - mPointersNodes.erase(mPointersNodes.begin()+index); - auto iter = std::find_if(mStoreNodes.begin(), mStoreNodes.end(), [&node](const CAmNode<T> & otherNode){ - return &otherNode==&node; - }); - if(iter!=mStoreNodes.end()) - mStoreNodes.erase(iter); - updateIndexes(index); + uint16_t index = node.getIndex(); + removeAllVerticesToNode(node); + mPointersAdjList.erase(mPointersAdjList.begin()+index); + mPointersNodes.erase(mPointersNodes.begin()+index); + auto iter = std::find_if(mStoreNodes.begin(), mStoreNodes.end(), [&node](const CAmNode<T> & otherNode){ + return &otherNode==&node; + }); + if(iter!=mStoreNodes.end()) + mStoreNodes.erase(iter); + updateIndexes(index); } /** @@ -524,7 +559,7 @@ namespace am std::vector<weight_t> min_distance; std::vector<CAmNode<T>*> previous; - findShortestsPathsFromNode(source, min_distance, previous); + findShortestPathsFromNode(source, min_distance, previous); for(auto it=listTargets.begin(); it!=listTargets.end(); it++) { @@ -554,7 +589,7 @@ namespace am return; std::vector<weight_t> min_distance; std::vector<CAmNode<T>*> previous; - findShortestsPathsFromNode(source, min_distance, previous); + findShortestPathsFromNode(source, min_distance, previous); constructShortestPathTo(destination, previous, resultPath); } @@ -576,7 +611,7 @@ namespace am std::vector<weight_t> min_distance; std::vector<CAmNode<T>*> previous; - findShortestsPathsFromNode(source, min_distance, previous); + findShortestPathsFromNode(source, min_distance, previous); for(auto it=listTargets.begin(); it!=listTargets.end(); it++) { @@ -603,7 +638,7 @@ namespace am std::vector<weight_t> min_distance; std::vector<CAmNode<T>*> previous; - findShortestsPathsFromNode(source, min_distance, previous); + findShortestPathsFromNode(source, min_distance, previous); constructShortestPathTo(destination, previous, cb); } @@ -613,15 +648,29 @@ namespace am * * @param src start node. * @param dst destination node. - * @param cb callabck. + * @param cbShouldVisitNode ask the delegate if we should proceed with the current node. + * @param cbWillVisitNode tell the delegate the current node will be visited. + * @param cbDidVisitNode tell the delegate the current node was visited. + * @param cbDidFindPath return the path to the delegate. */ - void getAllPaths(const CAmNode<T> & src, const CAmNode<T> & dst, std::function<void(const CAmNodeReferenceList & path)> cb) + void getAllPaths(CAmNode<T> & src, + CAmNode<T> & dst, + std::function<bool(const CAmNode<T> * )> cbShouldVisitNode, + std::function<void(const CAmNode<T> *)> cbWillVisitNode, + std::function<void(const CAmNode<T> *)> cbDidVisitNode, + std::function<void(const CAmNodeReferenceList & path)> cbDidFindPath) { - CAmNodeReferenceList visited; - visited.push_back((CAmNode<T>*)&src); + IterateThroughAllNodesDelegate delegate; + delegate.source = &src; + delegate.destination = &dst; + delegate.shouldVisitNode = cbShouldVisitNode; + delegate.willVisitNode = cbWillVisitNode; + delegate.didVisitNode = cbDidVisitNode; + delegate.didFindPath = cbDidFindPath; + delegate.visited.push_back((CAmNode<T>*)&src); ((CAmNode<T>*)&src)->setStatus(GES_VISITED); - goThroughAllPaths(dst, visited, cb); - reset(); + findAllPaths(delegate); + ((CAmNode<T>*)&src)->setStatus(GES_NOT_VISITED); } }; diff --git a/AudioManagerCore/include/CAmRouter.h b/AudioManagerCore/include/CAmRouter.h index 7e52b7c..88f73ea 100644 --- a/AudioManagerCore/include/CAmRouter.h +++ b/AudioManagerCore/include/CAmRouter.h @@ -27,293 +27,353 @@ #include <assert.h> #include <vector> +#include <iomanip> #include <functional> #include "audiomanagertypes.h" #include "CAmGraph.h" -#include "IAmDatabaseHandler.h" - +#include "CAmDatabaseHandlerMap.h" namespace am { -#define ROUTING_BUILD_CONNECTIONS 1 - -/** - * Optimal path search between a source and a sink is implemented with a graph which contains nodes - sinks, sources, gateways, converters. - * The nodes 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. - * - */ - -/** - * Trace on/off. - */ -#if !defined(ROUTING_BUILD_CONNECTIONS) - #undef TRACE_GRAPH -#endif -/** - * Default behavior is to do the search in one step without connections, which are identified during the search. - * Alternatively the search can be done in two steps. - */ -#if !defined(ROUTING_BUILD_CONNECTIONS) - #undef ROUTING_BUILD_CONNECTIONS -#endif - -#if defined(TRACE_GRAPH) -#if !defined(ROUTING_BUILD_CONNECTIONS) -#warning "You should define ROUTING_BUILD_CONNECTIONS in order to be able to see the connections in the trace." + /** + * Optimal path search is implemented with graph which contains nodes - sinks, sources, gateways, converters. + * The nodes 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. + * + */ + + /** + * Trace on/off. + */ +#undef TRACE_GRAPH + + /** + * Max paths count returned to the controller + */ +#ifndef MAX_ROUTING_PATHS +#define MAX_ROUTING_PATHS 5 #endif + /** + * How many times the routing algorithm should look back into domains. + * + * 0 - no cycles are allowed + * 1 - default is one cycle + * ... + * UINT_MAX - set this define to UINT_MAX in order to allow cycles. + * + */ +#ifndef MAX_ALLOWED_DOMAIN_CYCLES +#define MAX_ALLOWED_DOMAIN_CYCLES 1 #endif -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 - 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) - {} - - bool operator==(const am_RoutingNodeData_s & anotherObject) const - { - bool result = false; - if(type==anotherObject.type) - { - result = true; - 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; - }; + class CAmRouter; + + /** + * A structure used as user data in the graph nodes. + */ + struct am_RoutingNodeData_s + { + typedef enum + :int + { SINK, SOURCE, GATEWAY, CONVERTER + } am_NodeDataType_e; + am_NodeDataType_e type; //!< data type:sink, source, gateway or converter + 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) + { + } + + bool operator==(const am_RoutingNodeData_s & anotherObject) const + { + bool result = false; + if (type == anotherObject.type) + { + result = true; + 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 << "(" << data.sink->domainID << ")" - << "]"; - else if(type==SOURCE) - std::cout << "[SOUR:" << data.source->sourceID << ":" << data.source->name << "(" << data.source->domainID << ")" - << "]"; - else if(type==GATEWAY) - std::cout << "[GATE:" << data.gateway->gatewayID << ":" << data.gateway->name << "(" << data.gateway->controlDomainID << ")" - << "]"; - else if(type==CONVERTER) - std::cout << "[CONV:" << data.converter->converterID << ":" << data.converter->name << "(" << data.converter->domainID << ")" - << "]"; - }; -#endif - - am_domainID_t domainID() const - { - if(type==SINK) - return data.sink->domainID; - else if(type==SOURCE) - return data.source->domainID; - else if(type==GATEWAY) - return data.gateway->controlDomainID; - else if(type==CONVERTER) - return data.converter->domainID; - return 0; - }; -}; - -typedef am_RoutingNodeData_s::am_NodeDataType_e CAmNodeDataType; -typedef CAmNode<am_RoutingNodeData_s> CAmRoutingNode; -typedef CAmGraph<am_RoutingNodeData_s, uint16_t> CAmRoutingGraph; -typedef CAmVertex<am_RoutingNodeData_s, uint16_t> CAmRoutingVertex; -typedef std::list<CAmRoutingVertex> CAmRoutingListVertices; -typedef std::vector<CAmRoutingListVertices*> CAmRoutingVertexReferenceList; - -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 - CAmRoutingGraph mRoutingGraph; //!< graph object - std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListSources; //!< map with pointers to nodes with sources, used for quick access - std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListSinks; //!< map with pointers to nodes with sinks, used for quick access - std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListGateways; //!< map with pointers to nodes with gateways, used for quick access - std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListConverters;//!< map with pointers to nodes with converters, used for quick access - - am_Error_e determineConnectionFormatsForPath(am_Route_s & routeObjects, std::vector<CAmRoutingNode*> & nodes); - am_Error_e doConnectionFormatsForPath(am_Route_s & routeObjects, - std::vector<CAmRoutingNode*> & route, - std::vector<am_RoutingElement_s>::iterator routingElementIterator, - std::vector<CAmRoutingNode*>::iterator routeIterator); - - - /** - * Check whether given converter or gateway has been connected. - * - * @param comp converter or gateway . - */ - template <class Component> bool isComponentConnected(const Component & comp) - { - return mpDatabaseHandler->isComponentConnected(comp); - } - void generateAllPaths(const CAmRoutingNode & src, - const CAmRoutingNode & dst, - const bool includeCycles, - std::function<void(const std::vector<CAmRoutingNode*> & path)> cb); - void goThroughAllPaths(const CAmRoutingNode & dst, - std::vector<CAmRoutingNode*> & visited, - std::vector<am_domainID_t> & visitedDomains, - std::function<void(const std::vector<CAmRoutingNode*> & path)> cb); - -#ifdef ROUTING_BUILD_CONNECTIONS - /** - * Connects all converters to its sink and sources if possible. - * - */ - void constructConverterConnections(); - - /** - * Connects all gateways to its sink and sources if possible. - * - */ - void constructGatewayConnections(); - - /** - * Connects all sources to the sinks if possible. - * - */ - void constructSourceSinkConnections(); -#else - /** - * Construct a list with all vertices - */ - void getVerticesForNode(const CAmRoutingNode & node, CAmRoutingListVertices & list); - - /** - * Construct a list with all vertices from given source. - */ - void getVerticesForSource(const CAmRoutingNode & node, CAmRoutingListVertices & list); - - /** - * Construct a list with all vertices from given sink. - */ - void getVerticesForSink(const CAmRoutingNode & node, CAmRoutingListVertices & list); - - /** - * Construct a list with all vertices from given converter. - */ - void getVerticesForConverter(const CAmRoutingNode & node, CAmRoutingListVertices & list); - - /** - * Construct a list with all vertices from given gateway. - */ - void getVerticesForGateway(const CAmRoutingNode & node, CAmRoutingListVertices & list); -#endif - -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<am_Route_s>& returnList); - am_Error_e getRoute(const bool onlyfree, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes); - - am_Error_e getAllPaths(CAmRoutingNode & aSource, CAmRoutingNode & aSink, - std::vector<am_Route_s> & resultPath, std::vector<std::vector<CAmRoutingNode*>> & resultNodesPath, -#if !defined(ROUTING_BUILD_CONNECTIONS) - __attribute__((unused)) -#endif - const bool includeCycles = false); -#ifdef ROUTING_BUILD_CONNECTIONS - void getShortestPath(const CAmRoutingNode & source, const CAmRoutingNode & destination, std::vector<CAmRoutingNode*> & resultPath); - void getShortestPath(CAmRoutingNode & aSource, CAmRoutingNode & aSink, am_Route_s & resultPath, std::vector<CAmRoutingNode*> & resultNodesPath); +#define COUT_NODE(HEAD, NAME, ID) \ + std::cout << HEAD << "(" << std::setfill('0') << std::setw(4) << ID << " " << NAME << ")"; + + void trace() const + { + if(type==SINK) + COUT_NODE("SI", data.sink->name, data.sink->sinkID ) + else if(type==SOURCE) + COUT_NODE("SO", data.source->name, data.source->sourceID ) + else if(type==GATEWAY) + COUT_NODE("GA", data.gateway->name, data.gateway->gatewayID ) + else if(type==CONVERTER) + COUT_NODE("CO", data.converter->name, data.converter->converterID ) + }; #endif - 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); - static void listPossibleConnectionFormats(std::vector<am_CustomConnectionFormat_t> & inListSourceFormats, - std::vector<am_CustomConnectionFormat_t> & inListSinkFormats, - std::vector<am_CustomConnectionFormat_t> & outListFormats); - 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); - static void getSourceSinkPossibleConnectionFormats(std::vector<CAmRoutingNode*>::iterator iteratorSource, - std::vector<CAmRoutingNode*>::iterator iteratorSink, - std::vector<am_CustomConnectionFormat_t> & outConnectionFormats); - - static bool shouldGoInDomain(const std::vector<am_domainID_t> & visitedDomains, const am_domainID_t nodeDomainID); - - /** - * Returns a sink node with given sinkID. - * - * @param sinkID sink id. - * @return pointer to node or NULL. - */ - CAmRoutingNode* sinkNodeWithID(const am_sinkID_t sinkID); - CAmRoutingNode* sinkNodeWithID(const am_sinkID_t sinkID, const am_domainID_t domainID); - - /** - * Returns a source node with given sourceID. - * - * @param sourceID source id. - * @return pointer to node or NULL. - */ - CAmRoutingNode* sourceNodeWithID(const am_sourceID_t sourceID); - CAmRoutingNode* sourceNodeWithID(const am_sourceID_t sourceID, const am_domainID_t domainID); - - /** - * Returns a converter node for given sinkID. - * - * @param sinkID sink id. - * @param domainID domain id. - * @return pointer to node or NULL. - */ - CAmRoutingNode* converterNodeWithSinkID(const am_sinkID_t sinkID, const am_domainID_t domainID); - - /** - * Returns a gateway node for given sinkID. - * - * @param sinkID sink id. - * @return pointer to node or NULL. - */ - CAmRoutingNode* gatewayNodeWithSinkID(const am_sinkID_t sinkID); - - void load(const bool onlyFree); - void clear(); -}; + am_domainID_t domainID() const + { + if (type == SINK) + return data.sink->domainID; + else if (type == SOURCE) + return data.source->domainID; + else if (type == GATEWAY) + return data.gateway->controlDomainID; + else if (type == CONVERTER) + return data.converter->domainID; + return 0; + } + ; + }; + + typedef am_RoutingNodeData_s::am_NodeDataType_e CAmNodeDataType; + typedef CAmNode<am_RoutingNodeData_s> CAmRoutingNode; + typedef CAmGraph<am_RoutingNodeData_s, uint16_t> CAmRoutingGraph; + typedef CAmVertex<am_RoutingNodeData_s, uint16_t> CAmRoutingVertex; + typedef std::list<CAmRoutingVertex> CAmRoutingListVertices; + typedef std::vector<CAmRoutingListVertices*> CAmRoutingVertexReferenceList; + + class CAmControlSender; + + /** + * Implements autorouting algorithm for connecting sinks and sources via different audio domains. + */ + class CAmRouter: public CAmDatabaseHandlerMap::AmDatabaseObserverCallbacks + { + IAmDatabaseHandler* mpDatabaseHandler; //!< pointer to database handler + CAmControlSender* mpControlSender; //!< pointer the controlsender - is used to retrieve information for the optimal route + bool mUpdateGraphNodesAction; //!< Flag which marks whether the graph should be rebuild + unsigned mMaxAllowedCycles; //!< max allowed cycles, default is 1 + unsigned mMaxPathCount; //!< max paths count returned to the controller, default is 5 + CAmRoutingGraph mRoutingGraph; //!< graph object + std::map<am_domainID_t, std::vector<CAmRoutingNode*>> mNodeListSources; //!< map with pointers to nodes with sources, used for quick access + std::map<am_domainID_t, std::vector<CAmRoutingNode*>> mNodeListSinks; //!< map with pointers to nodes with sinks, used for quick access + std::map<am_domainID_t, std::vector<CAmRoutingNode*>> mNodeListGateways; //!< map with pointers to nodes with gateways, used for quick access + std::map<am_domainID_t, std::vector<CAmRoutingNode*>> mNodeListConverters; //!< map with pointers to nodes with converters, used for quick access + + /** + * Check whether given converter or gateway has been connected. + * + * @param comp converter or gateway . + */ + template<class Component> bool isComponentConnected(const Component & comp) + { + return mpDatabaseHandler->isComponentConnected(comp); + } + + /** + * Connect all converters to its sink and sources if possible. + * + */ + void constructConverterConnections(); + + /** + * Connect all gateways to its sink and sources if possible. + * + */ + void constructGatewayConnections(); + + /** + * Connect all sources to the sinks if possible. + * + */ + void constructSourceSinkConnections(); + + /** + * Construct list with all vertices + */ + void getVerticesForNode(const CAmRoutingNode & node, CAmRoutingListVertices & list); + + /** + * Construct list with all vertices from given source. + */ + void getVerticesForSource(const CAmRoutingNode & node, CAmRoutingListVertices & list); + + /** + * Construct list with all vertices from given sink. + */ + void getVerticesForSink(const CAmRoutingNode & node, CAmRoutingListVertices & list); + + /** + * Construct list with all vertices from given converter. + */ + void getVerticesForConverter(const CAmRoutingNode & node, CAmRoutingListVertices & list); + + /** + * Construct list with all vertices from given gateway. + */ + void getVerticesForGateway(const CAmRoutingNode & node, CAmRoutingListVertices & list); + + /** + * Connection format permutations. + * + * @return E_OK on success(1 or more paths), E_NOT_POSSIBLE if the CF couldn't be matached or E_UNKNOWN in any other error case. + */ + am_Error_e determineConnectionFormatsForPath(am_Route_s & routeObjects, std::vector<CAmRoutingNode*> & nodes, std::vector<am_Route_s> & result); + am_Error_e doConnectionFormatsForPath(am_Route_s & routeObjects, std::vector<CAmRoutingNode*> & route, + std::vector<am_RoutingElement_s>::iterator routingElementIterator, std::vector<CAmRoutingNode*>::iterator routeIterator, + std::vector<am_Route_s> & result); + am_Error_e cfPermutationsForPath(am_Route_s shortestRoute, std::vector<CAmRoutingNode*> resultNodesPath, std::vector<am_Route_s>& resultPath); + + /** + * Helper method. + */ + static int insertPostion(const std::vector<CAmRoutingNode*>& path, const std::vector<std::vector<CAmRoutingNode*> >& nodes); + + public: + CAmRouter(IAmDatabaseHandler* iDatabaseHandler, CAmControlSender* iSender); + ~CAmRouter(); + + unsigned getMaxAllowedCycles() + { + return mMaxAllowedCycles; + } + void setMaxAllowedCycles(unsigned count) + { + mMaxAllowedCycles = count; + } + + unsigned getMaxPathCount() + { + return mMaxPathCount; + } + void setMaxPathCount(unsigned count) + { + mMaxPathCount = count; + } + + bool getUpdateGraphNodesAction() + { + return mUpdateGraphNodesAction; + } + + /** + * Find first mMaxPathCount paths between given source and sink. This method will call the method load() if the parameter mUpdateGraphNodesAction is set which will rebuild the graph. + * + * @param onlyfree only disconnected elements should be included or not. + * @param sourceID start point. + * @param sinkID end point. + * @param returnList list with all possible paths + * @return E_OK on success(1 or more paths), E_NOT_POSSIBLE if the CF couldn't be matached or E_UNKNOWN in any other error case. + */ + am_Error_e getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s>& returnList); + am_Error_e getRoute(const bool onlyfree, const am_Source_s & source, const am_Sink_s & sink, std::vector<am_Route_s> & listRoutes); + + /** + * Find first mMaxPathCount paths between given source and sink after the nodes have been loaded. This method doesn't call load(). + * + * @param onlyfree only disconnected elements should be included or not. + * @param sourceID start point. + * @param sinkID end point. + * @param returnList list with all possible paths + * @return E_OK on success(1 or more paths), E_NOT_POSSIBLE if the CF couldn't be matached or E_UNKNOWN in any other error case. + */ + am_Error_e getRouteFromLoadedNodes(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s> & returnList); + am_Error_e getRouteFromLoadedNodes(const bool onlyfree, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes); + + /** + * Find first mMaxPathCount paths between given source and sink. This method doesn't call load(). + * + * @param onlyfree only disconnected elements should be included or not. + * @param cycles allowed domain cycles. + * @param maxPathCount max count of returned paths. + * @param source start point. + * @param sink end point. + * @param returnList list with all possible paths. + * @return E_OK on success(1 or more paths), E_NOT_POSSIBLE if the CF couldn't be matached or E_UNKNOWN in any other error case. + */ + am_Error_e getFirstNShortestPaths(const bool onlyfree, const unsigned cycles, const unsigned maxPathCount, CAmRoutingNode & source, + CAmRoutingNode & sink, std::vector<am_Route_s> & resultPath); + + /** + * Find the shortest path between given source and sink. This method doesn't call load(). + * It goes through all possible paths and returns the shortest of them. + * + * @param source start point. + * @param sink end point. + * @param returnList list with the connection format permutations of the shortest path. + * @return E_OK on success(1 or more paths), E_NOT_POSSIBLE if the CF couldn't be matached or E_UNKNOWN in any other error case. + */ + am_Error_e getShortestPath(CAmRoutingNode & source, CAmRoutingNode & sink, std::vector<am_Route_s> & resultPath); + + 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); + static void listPossibleConnectionFormats(std::vector<am_CustomConnectionFormat_t> & inListSourceFormats, + std::vector<am_CustomConnectionFormat_t> & inListSinkFormats, std::vector<am_CustomConnectionFormat_t> & outListFormats); + 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); + static am_Error_e getSourceSinkPossibleConnectionFormats(std::vector<CAmRoutingNode*>::iterator iteratorSource, + std::vector<CAmRoutingNode*>::iterator iteratorSink, std::vector<am_CustomConnectionFormat_t> & outConnectionFormats); + + static bool shouldGoInDomain(const std::vector<am_domainID_t> & visitedDomains, const am_domainID_t nodeDomainID, const unsigned maxCyclesNumber); + bool shouldGoInDomain(const std::vector<am_domainID_t> & visitedDomains, const am_domainID_t nodeDomainID); + /** + * Returns a sink node with given sinkID. + * + * @param sinkID sink id. + * @return pointer to node or NULL. + */ + CAmRoutingNode* sinkNodeWithID(const am_sinkID_t sinkID); + CAmRoutingNode* sinkNodeWithID(const am_sinkID_t sinkID, const am_domainID_t domainID); + + /** + * Returns a source node with given sourceID. + * + * @param sourceID source id. + * @return pointer to node or NULL. + */ + CAmRoutingNode* sourceNodeWithID(const am_sourceID_t sourceID); + CAmRoutingNode* sourceNodeWithID(const am_sourceID_t sourceID, const am_domainID_t domainID); + + /** + * Returns a converter node for given sinkID. + * + * @param sinkID sink id. + * @param domainID domain id. + * @return pointer to node or NULL. + */ + CAmRoutingNode* converterNodeWithSinkID(const am_sinkID_t sinkID, const am_domainID_t domainID); + + /** + * Returns a gateway node for given sinkID. + * + * @param sinkID sink id. + * @return pointer to node or NULL. + */ + CAmRoutingNode* gatewayNodeWithSinkID(const am_sinkID_t sinkID); + + void load(); + void clear(); + + /** + * DEPRECATED! + */ + public: + am_Error_e getAllPaths(CAmRoutingNode & aSource, CAmRoutingNode & aSink, std::vector<am_Route_s> & resultPath, + std::vector<std::vector<CAmRoutingNode*>> & resultNodesPath, const bool includeCycles = false, + const bool onlyFree = false) + __attribute__((deprecated("You should use am_Error_e getFirstNShortestPaths(const bool onlyFree, CAmRoutingNode &, CAmRoutingNode &, std::vector<am_Route_s> &) instead!"))); + }; } /* namespace am */ #endif /* ROUTER_H_ */ diff --git a/AudioManagerCore/include/CAmRoutingSender.h b/AudioManagerCore/include/CAmRoutingSender.h index 8804d90..8d8a063 100644 --- a/AudioManagerCore/include/CAmRoutingSender.h +++ b/AudioManagerCore/include/CAmRoutingSender.h @@ -32,16 +32,17 @@ #include "../test/IAmRoutingBackdoor.h" #endif +#include "CAmDatabaseHandlerMap.h" + namespace am { class CAmRoutingReceiver; -class IAmDatabaseHandler; /** * Implements the RoutingSendInterface. Loads all plugins and dispatches calls to the plugins */ -class CAmRoutingSender +class CAmRoutingSender: public CAmDatabaseHandlerMap::AmDatabaseObserverCallbacks { public: CAmRoutingSender(const std::vector<std::string>& listOfPluginDirectories, IAmDatabaseHandler* databaseHandler); diff --git a/AudioManagerCore/include/IAmDatabaseHandler.h b/AudioManagerCore/include/IAmDatabaseHandler.h index aa275db..f4fe8a1 100644 --- a/AudioManagerCore/include/IAmDatabaseHandler.h +++ b/AudioManagerCore/include/IAmDatabaseHandler.h @@ -30,18 +30,14 @@ #include <string> #include <iostream> #include <functional> +#include <memory> +#include <assert.h> +#include <algorithm> #include "audiomanagerconfig.h" namespace am { -class CAmDatabaseObserver; -class CAmRoutingTree; -class CAmRoutingTreeItem; - - -//enum { DYNAMIC_ID_BOUNDARY = 100 }; //!< the value below is reserved for staticIDs, the value above will be assigned to dynamically registered items - //todo: check the enum values before entering & changing in the database. //todo: change asserts for dynamic boundary checks into failure answers.# //todo: check autoincrement boundary and set to 16bit limits @@ -59,8 +55,12 @@ typedef std::map<am_gatewayID_t, std::vector<bool> > ListConnectionFormat; //!< class IAmDatabaseHandler { public: - IAmDatabaseHandler () {}; - virtual ~IAmDatabaseHandler () {}; + IAmDatabaseHandler (){} + virtual ~IAmDatabaseHandler (){} + + /** + * The following interface methods must be implemented by the subclass. + */ virtual am_Error_e enterDomainDB(const am_Domain_s& domainData, am_domainID_t& domainID) = 0; virtual am_Error_e enterMainConnectionDB(const am_MainConnection_s& mainConnectionData, am_mainConnectionID_t& connectionID) = 0; virtual am_Error_e enterSinkDB(const am_Sink_s& sinkData, am_sinkID_t& sinkID) = 0; @@ -117,7 +117,7 @@ public: virtual am_Error_e getSourceVolume(const am_sourceID_t sourceID, am_volume_t& volume) const = 0; virtual am_Error_e getSinkSoundPropertyValue(const am_sinkID_t sinkID, const am_CustomSoundPropertyType_t propertyType, int16_t& value) const = 0; virtual am_Error_e getSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomSoundPropertyType_t propertyType, int16_t& value) const = 0; - virtual am_Error_e getListSinkSoundProperties(const am_sinkID_t sinkID, std::vector<am_SoundProperty_s>& listSoundproperties) const =0; + virtual am_Error_e getListSinkSoundProperties(const am_sinkID_t sinkID, std::vector<am_SoundProperty_s>& listSoundproperties) const =0; virtual am_Error_e getListSourceSoundProperties(const am_sourceID_t sourceID, std::vector<am_SoundProperty_s>& listSoundproperties) const =0; virtual am_Error_e getMainSinkSoundPropertyValue(const am_sinkID_t sinkID, const am_CustomMainSoundPropertyType_t propertyType, int16_t& value) const = 0; virtual am_Error_e getMainSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomMainSoundPropertyType_t propertyType, int16_t& value) const = 0; @@ -166,7 +166,6 @@ public: virtual am_Error_e changeConverterDB(const am_converterID_t converterID, const std::vector<am_CustomConnectionFormat_t>& listSourceConnectionFormats, const std::vector<am_CustomConnectionFormat_t>& listSinkConnectionFormats, const std::vector<bool>& convertionMatrix) = 0; virtual am_Error_e changeSinkNotificationConfigurationDB(const am_sinkID_t sinkID,const am_NotificationConfiguration_s notificationConfiguration) = 0; virtual am_Error_e changeSourceNotificationConfigurationDB(const am_sourceID_t sourceID,const am_NotificationConfiguration_s notificationConfiguration) = 0; - virtual bool existMainConnection(const am_mainConnectionID_t mainConnectionID) const = 0; virtual bool existCrossFader(const am_crossfaderID_t crossfaderID) const = 0; virtual bool existConnection(const am_Connection_s & connection) const = 0; @@ -181,7 +180,6 @@ public: virtual bool existGateway(const am_gatewayID_t gatewayID) const = 0; virtual bool existSinkClass(const am_sinkClass_t sinkClassID) const = 0; virtual bool existSourceClass(const am_sourceClass_t sourceClassID) const = 0; - virtual void registerObserver(CAmDatabaseObserver *iObserver) = 0; virtual bool sourceVisible(const am_sourceID_t sourceID) const = 0; virtual bool sinkVisible(const am_sinkID_t sinkID) const = 0; virtual bool isComponentConnected(const am_Gateway_s & gateway) const = 0; @@ -192,7 +190,19 @@ public: virtual am_Error_e enumerateSinks(std::function<void(const am_Sink_s & element)> cb) const = 0 ; virtual am_Error_e enumerateGateways(std::function<void(const am_Gateway_s & element)> cb) const = 0 ; virtual am_Error_e enumerateConverters(std::function<void(const am_Converter_s & element)> cb) const = 0 ; + /** + * Database observer protocol + */ + class IAmDatabaseObserver + { + public: + IAmDatabaseObserver() {} + virtual ~IAmDatabaseObserver(){} + }; + virtual bool registerObserver(IAmDatabaseObserver * iObserver) = 0; + virtual bool unregisterObserver(IAmDatabaseObserver * iObserver) = 0; + virtual unsigned countObservers() = 0; }; |