diff options
author | Aleksandar Donchev <Aleksander.Donchev@partner.bmw.de> | 2014-08-26 18:15:19 +0200 |
---|---|---|
committer | Christian Linke <christian.linke@bmw.de> | 2014-11-05 18:35:35 +0100 |
commit | 57c2f4ea0148287d0bcea913cb34ba716489df4b (patch) | |
tree | 0aa026a28c4f4f2d727da882b0bee03cc671cb28 /AudioManagerDaemon/src | |
parent | afadaf4260e8d436b454289e61e85ac8c5bab071 (diff) | |
download | audiomanager-57c2f4ea0148287d0bcea913cb34ba716489df4b.tar.gz |
* Converter Implementation .6.2
Signed-off-by: Christian Linke <christian.linke@bmw.de>
Diffstat (limited to 'AudioManagerDaemon/src')
-rw-r--r-- | AudioManagerDaemon/src/CAmControlReceiver.cpp | 32 | ||||
-rw-r--r-- | AudioManagerDaemon/src/CAmControlSender.cpp | 18 | ||||
-rw-r--r-- | AudioManagerDaemon/src/CAmDatabaseHandlerMap.cpp | 270 | ||||
-rw-r--r-- | AudioManagerDaemon/src/CAmDatabaseHandlerSQLite.cpp | 1085 | ||||
-rw-r--r-- | AudioManagerDaemon/src/CAmDatabaseObserver.cpp | 12 | ||||
-rw-r--r-- | AudioManagerDaemon/src/CAmRouter.cpp | 1114 | ||||
-rw-r--r-- | AudioManagerDaemon/src/CAmRoutingReceiver.cpp | 15 | ||||
-rw-r--r-- | AudioManagerDaemon/src/CAmRoutingSender.cpp | 16 |
8 files changed, 1935 insertions, 627 deletions
diff --git a/AudioManagerDaemon/src/CAmControlReceiver.cpp b/AudioManagerDaemon/src/CAmControlReceiver.cpp index ae017e2..f576f5e 100644 --- a/AudioManagerDaemon/src/CAmControlReceiver.cpp +++ b/AudioManagerDaemon/src/CAmControlReceiver.cpp @@ -184,6 +184,11 @@ am_Error_e CAmControlReceiver::enterGatewayDB(const am_Gateway_s & gatewayData, return (mDatabaseHandler->enterGatewayDB(gatewayData, gatewayID)); } +am_Error_e CAmControlReceiver::enterConverterDB(const am_Converter_s & converterData, am_converterID_t & converterID) +{ + return (mDatabaseHandler->enterConverterDB(converterData, converterID)); +} + am_Error_e CAmControlReceiver::enterSourceDB(const am_Source_s & sourceData, am_sourceID_t & sourceID) { return (mDatabaseHandler->enterSourceDB(sourceData, sourceID)); @@ -274,6 +279,11 @@ am_Error_e CAmControlReceiver::removeGatewayDB(const am_gatewayID_t gatewayID) return (mDatabaseHandler->removeGatewayDB(gatewayID)); } +am_Error_e CAmControlReceiver::removeConverterDB(const am_converterID_t converterID) +{ + return (mDatabaseHandler->removeConverterDB(converterID)); +} + am_Error_e CAmControlReceiver::removeCrossfaderDB(const am_crossfaderID_t crossfaderID) { return (mDatabaseHandler->removeCrossfaderDB(crossfaderID)); @@ -314,6 +324,12 @@ am_Error_e CAmControlReceiver::getGatewayInfoDB(const am_gatewayID_t gatewayID, return (mDatabaseHandler->getGatewayInfoDB(gatewayID, gatewayData)); } +am_Error_e CAmControlReceiver::getConverterInfoDB(const am_converterID_t converterID, am_Converter_s & converterData) const +{ + return (mDatabaseHandler->getConverterInfoDB(converterID, converterData)); +} + + am_Error_e CAmControlReceiver::getCrossfaderInfoDB(const am_crossfaderID_t crossfaderID, am_Crossfader_s & crossfaderData) const { return (mDatabaseHandler->getCrossfaderInfoDB(crossfaderID, crossfaderData)); @@ -339,6 +355,11 @@ am_Error_e CAmControlReceiver::getListGatewaysOfDomain(const am_domainID_t domai return (mDatabaseHandler->getListGatewaysOfDomain(domainID, listGatewaysID)); } +am_Error_e CAmControlReceiver::getListConvertersOfDomain(const am_domainID_t domainID,std::vector<am_converterID_t>& listConverterID) const +{ + return (mDatabaseHandler->getListConvertersOfDomain(domainID,listConverterID)); +} + am_Error_e CAmControlReceiver::getListMainConnections(std::vector<am_MainConnection_s> & listMainConnections) const { return (mDatabaseHandler->getListMainConnections(listMainConnections)); @@ -384,6 +405,11 @@ am_Error_e CAmControlReceiver::getListGateways(std::vector<am_Gateway_s> & listG return (mDatabaseHandler->getListGateways(listGateways)); } +am_Error_e CAmControlReceiver::getListConverters(std::vector<am_Converter_s>& listConverters) const +{ + return (mDatabaseHandler->getListConverters(listConverters)); +} + am_Error_e CAmControlReceiver::getListSinkClasses(std::vector<am_SinkClass_s> & listSinkClasses) const { return (mDatabaseHandler->getListSinkClasses(listSinkClasses)); @@ -489,6 +515,12 @@ am_Error_e CAmControlReceiver::changeGatewayDB(const am_gatewayID_t gatewayID, c return (mDatabaseHandler->changeGatewayDB(gatewayID,listSourceConnectionFormats,listSinkConnectionFormats,convertionMatrix)); } +am_Error_e CAmControlReceiver::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) +{ + logInfo("CAmControlReceiver::changeConverterDB was called with converterID", converterID); + return (mDatabaseHandler->changeConverterDB(converterID,listSourceConnectionFormats,listSinkConnectionFormats,convertionMatrix)); +} + am_Error_e CAmControlReceiver::setVolumes(am_Handle_s& handle, const std::vector<am_Volumes_s>& listVolumes) { logInfo("CAmControlReceiver::setVolumes got called"); diff --git a/AudioManagerDaemon/src/CAmControlSender.cpp b/AudioManagerDaemon/src/CAmControlSender.cpp index 229a28b..dd3558e 100644 --- a/AudioManagerDaemon/src/CAmControlSender.cpp +++ b/AudioManagerDaemon/src/CAmControlSender.cpp @@ -193,12 +193,24 @@ am_Error_e CAmControlSender::hookSystemRegisterGateway(const am_Gateway_s & gate return (mController->hookSystemRegisterGateway(gatewayData, gatewayID)); } +am_Error_e CAmControlSender::hookSystemRegisterConverter(const am_Converter_s& converterData, am_converterID_t& converterID) +{ + assert(mController); + return (mController->hookSystemRegisterConverter(converterData, converterID)); +} + am_Error_e CAmControlSender::hookSystemDeregisterGateway(const am_gatewayID_t gatewayID) { assert(mController); return (mController->hookSystemDeregisterGateway(gatewayID)); } +am_Error_e CAmControlSender::hookSystemDeregisterConverter(const am_converterID_t converterID) +{ + assert(mController); + return (mController->hookSystemDeregisterConverter(converterID)); +} + am_Error_e CAmControlSender::hookSystemRegisterCrossfader(const am_Crossfader_s & crossfaderData, am_crossfaderID_t & crossfaderID) { assert(mController); @@ -414,6 +426,12 @@ am_Error_e CAmControlSender::hookSystemUpdateGateway(const am_gatewayID_t gatewa return (mController->hookSystemUpdateGateway(gatewayID,listSourceConnectionFormats,listSinkConnectionFromats,convertionMatrix)); } +am_Error_e CAmControlSender::hookSystemUpdateConverter(const am_converterID_t converterID, const std::vector<am_CustomConnectionFormat_t>& listSourceConnectionFormats, const std::vector<am_CustomConnectionFormat_t>& listSinkConnectionFromats, const std::vector<bool>& convertionMatrix) +{ + assert(mController); + return (mController->hookSystemUpdateConverter(converterID,listSourceConnectionFormats,listSinkConnectionFromats,convertionMatrix)); +} + void CAmControlSender::cbAckSetVolume(const am_Handle_s handle, const std::vector<am_Volumes_s>& listVolumes, const am_Error_e error) { assert(mController); diff --git a/AudioManagerDaemon/src/CAmDatabaseHandlerMap.cpp b/AudioManagerDaemon/src/CAmDatabaseHandlerMap.cpp index a7b765d..713eea1 100644 --- a/AudioManagerDaemon/src/CAmDatabaseHandlerMap.cpp +++ b/AudioManagerDaemon/src/CAmDatabaseHandlerMap.cpp @@ -26,13 +26,13 @@ #include <fstream> #include <sstream> #include <string> -#include <algorithm> #include <limits> #include "CAmDatabaseHandlerMap.h" #include "CAmDatabaseObserver.h" #include "CAmRouter.h" #include "shared/CAmDltWrapper.h" + namespace am { @@ -428,6 +428,7 @@ bool CAmDatabaseHandlerMap::CAmMappedData::increaseConnectionID(int16_t & result CAmDatabaseHandlerMap::CAmDatabaseHandlerMap(): mFirstStaticSink(true), // mFirstStaticSource(true), // mFirstStaticGateway(true), // + mFirstStaticConverter(true), // mFirstStaticSinkClass(true), // mFirstStaticSourceClass(true), // mFirstStaticCrossfader(true), // @@ -665,7 +666,7 @@ am_Error_e CAmDatabaseHandlerMap::enterCrossfaderDB(const am_Crossfader_s & cros if (crossfaderData.crossfaderID != 0 || mFirstStaticCrossfader) { //check if the ID already exists - if (existcrossFader(crossfaderData.crossfaderID)) + if (existCrossFader(crossfaderData.crossfaderID)) { crossfaderID = crossfaderData.crossfaderID; return (E_ALREADY_EXISTS); @@ -758,6 +759,71 @@ am_Error_e CAmDatabaseHandlerMap::enterGatewayDB(const am_Gateway_s & gatewayDat return (E_OK); } +bool CAmDatabaseHandlerMap::insertConverterDB(const am_Converter_s & converteData, am_converterID_t & converterID) +{ + int16_t nextID = 0; + if(mMappedData.increaseID(nextID, mMappedData.mCurrentConverterID, converteData.converterID)) + { + converterID = nextID; + mMappedData.mConverterMap[nextID] = converteData; + mMappedData.mConverterMap[nextID].converterID = nextID; + return (true); + } + else + { + converterID = 0; + logInfo(__PRETTY_FUNCTION__,"Max limit reached."); + return (false); + } +} + +am_Error_e CAmDatabaseHandlerMap::enterConverterDB(const am_Converter_s & converterData, am_converterID_t & converterID) +{ + assert(converterData.converterID<DYNAMIC_ID_BOUNDARY); + assert(converterData.sinkID!=0); + assert(converterData.sourceID!=0); + assert(converterData.domainID!=0); + assert(!converterData.name.empty()); + assert(!converterData.convertionMatrix.empty()); + assert(!converterData.listSinkFormats.empty()); + assert(!converterData.listSourceFormats.empty()); + + //might be that the sinks and sources are not there during registration time + //assert(existSink(gatewayData.sinkID)); + //assert(existSource(gatewayData.sourceID)); + + am_converterID_t tempID = 0; + am_converterID_t tempIndex = 0; + //if gatewayData is zero and the first Static Sink was already entered, the ID is created + bool result; + if (converterData.converterID != 0 || mFirstStaticConverter) + { + //check if the ID already exists + if (existGateway(converterData.converterID)) + { + converterID = converterData.converterID; + return (E_ALREADY_EXISTS); + } + } + result = insertConverterDB(converterData, tempID); + if( false == result ) + return (E_UNKNOWN); + + tempIndex = tempID; + //if the ID is not created, we add it to the query + if (converterData.converterID == 0 && mFirstStaticConverter) + { + mFirstStaticConverter = false; + } + mMappedData.mConverterMap[tempIndex].converterID = tempID; + converterID = tempID; + + logInfo("DatabaseHandler::enterConverterDB entered new converter with name", converterData.name, "sourceID:", converterData.sourceID, "sinkID:", converterData.sinkID, "assigned ID:", converterID); + if (mpDatabaseObserver) + mpDatabaseObserver->newConverter(mMappedData.mConverterMap[tempIndex]); + return (E_OK); +} + void CAmDatabaseHandlerMap::dump( std::ostream & output ) const { output << std::endl << "****************** DUMP START ******************" << std::endl; @@ -1274,11 +1340,28 @@ am_Error_e CAmDatabaseHandlerMap::removeGatewayDB(const am_gatewayID_t gatewayID return (E_OK); } +am_Error_e CAmDatabaseHandlerMap::removeConverterDB(const am_converterID_t converterID) +{ + assert(converterID!=0); + + if (!existConverter(converterID)) + { + return (E_NON_EXISTENT); + } + + mMappedData.mConverterMap.erase(converterID); + + logInfo("DatabaseHandler::removeConverterDB removed:", converterID); + if (mpDatabaseObserver) + mpDatabaseObserver->removeConverter(converterID); + return (E_OK); +} + am_Error_e CAmDatabaseHandlerMap::removeCrossfaderDB(const am_crossfaderID_t crossfaderID) { assert(crossfaderID!=0); - if (!existcrossFader(crossfaderID)) + if (!existCrossFader(crossfaderID)) { return (E_NON_EXISTENT); } @@ -1480,10 +1563,24 @@ am_Error_e CAmDatabaseHandlerMap::getGatewayInfoDB(const am_gatewayID_t gatewayI } +am_Error_e CAmDatabaseHandlerMap::getConverterInfoDB(const am_converterID_t converterID, am_Converter_s& converterData) const +{ + assert(converterID!=0); + if (!existConverter(converterID)) + { + return (E_NON_EXISTENT); + } + + converterData = mMappedData.mConverterMap.at(converterID); + + return (E_OK); + +} + am_Error_e CAmDatabaseHandlerMap::getCrossfaderInfoDB(const am_crossfaderID_t crossfaderID, am_Crossfader_s & crossfaderData) const { assert(crossfaderID!=0); - if (!existcrossFader(crossfaderID)) + if (!existCrossFader(crossfaderID)) { return (E_NON_EXISTENT); } @@ -1574,6 +1671,24 @@ am_Error_e CAmDatabaseHandlerMap::getListGatewaysOfDomain(const am_domainID_t do return (E_OK); } +am_Error_e CAmDatabaseHandlerMap::getListConvertersOfDomain(const am_domainID_t domainID, std::vector<am_converterID_t>& listConvertersID) const +{ + assert(domainID!=0); + listConvertersID.clear(); + if (!existDomain(domainID)) + { + return (E_NON_EXISTENT); + } + + CAmMapConverter::const_iterator elementIterator = mMappedData.mConverterMap.begin(); + for (;elementIterator != mMappedData.mConverterMap.end(); ++elementIterator) + { + if (domainID==elementIterator->second.domainID) + listConvertersID.push_back(elementIterator->second.converterID); + } + return (E_OK); +} + am_Error_e CAmDatabaseHandlerMap::getListMainConnections(std::vector<am_MainConnection_s> & listMainConnections) const { listMainConnections.clear(); @@ -1673,6 +1788,17 @@ am_Error_e CAmDatabaseHandlerMap::getListGateways(std::vector<am_Gateway_s> & li return (E_OK); } +am_Error_e CAmDatabaseHandlerMap::getListConverters(std::vector<am_Converter_s> & listConverters) const +{ + listConverters.clear(); + + std::for_each(mMappedData.mConverterMap.begin(), mMappedData.mConverterMap.end(), [&](const std::pair<am_converterID_t, am_Converter_s>& ref) { + listConverters.push_back(ref.second); + }); + + return (E_OK); +} + am_Error_e CAmDatabaseHandlerMap::getListSinkClasses(std::vector<am_SinkClass_s> & listSinkClasses) const { listSinkClasses.clear(); @@ -1959,6 +2085,11 @@ bool CAmDatabaseHandlerMap::existGateway(const am_gatewayID_t gatewayID) const return existsObjectWithKeyInMap(gatewayID, mMappedData.mGatewayMap); } +bool CAmDatabaseHandlerMap::existConverter(const am_converterID_t converterID) const +{ + return existsObjectWithKeyInMap(converterID, mMappedData.mConverterMap); +} + am_Error_e CAmDatabaseHandlerMap::getDomainOfSource(const am_sourceID_t sourceID, am_domainID_t & domainID) const { assert(sourceID!=0); @@ -2141,7 +2272,7 @@ bool CAmDatabaseHandlerMap::existConnectionID(const am_connectionID_t connection * @param crossfaderID the ID of the crossfader to be checked * @return true if exists */ -bool CAmDatabaseHandlerMap::existcrossFader(const am_crossfaderID_t crossfaderID) const +bool CAmDatabaseHandlerMap::existCrossFader(const am_crossfaderID_t crossfaderID) const { return existsObjectWithKeyInMap(crossfaderID, mMappedData.mCrossfaderMap); } @@ -2421,7 +2552,7 @@ am_Error_e CAmDatabaseHandlerMap::changeCrossFaderHotSink(const am_crossfaderID_ assert(crossfaderID!=0); assert(hotsink!=HS_UNKNOWN); - if (!existcrossFader(crossfaderID)) + if (!existCrossFader(crossfaderID)) { return (E_NON_EXISTENT); } @@ -2430,54 +2561,16 @@ am_Error_e CAmDatabaseHandlerMap::changeCrossFaderHotSink(const am_crossfaderID_ return (E_OK); } -am_Error_e CAmDatabaseHandlerMap::getRoutingTree(bool onlyfree, CAmRoutingTree& tree, std::vector<CAmRoutingTreeItem*>& flatTree) +bool CAmDatabaseHandlerMap::isComponentConnected(const am_Gateway_s & gateway) const { - am_domainID_t rootID = tree.returnRootDomainID(); - CAmRoutingTreeItem *parent = tree.returnRootItem(); - size_t i = 0; - - do - { - if (i != 0) - { - parent = flatTree.at(i - 1); - rootID = parent->returnDomainID(); - } - std::for_each(mMappedData.mGatewayMap.begin(),mMappedData.mGatewayMap.end(), [&](const std::pair<am_gatewayID_t, am_Gateway_s>& refGateway) { - if( rootID==refGateway.second.domainSinkID ) - { - if(!onlyfree || std::find_if(mMappedData.mConnectionMap.begin(), - mMappedData.mConnectionMap.end(), - [&](const std::pair<am_connectionID_t, am_Connection_Database_s>& refConnection) - { - return (refConnection.second.sinkID == refGateway.second.sinkID || - refConnection.second.sourceID ==refGateway.second.sourceID); - })==mMappedData.mConnectionMap.end() ) - { - // additional check to avoid cyclic routes - const am_domainID_t domainSourceID = refGateway.second.domainSourceID; - bool sourceDomainAlreadyHandledAsSink = false; - for (std::vector<CAmRoutingTreeItem*>::const_iterator iFT = flatTree.begin(); iFT != flatTree.end(); ++iFT) - { - if (domainSourceID == (*iFT)->returnParent()->returnDomainID()) - { - sourceDomainAlreadyHandledAsSink = true; - break; - } - } - - if (!sourceDomainAlreadyHandledAsSink) - { - // logInfo("DatabaseHandler::getRoutingTree ", rootID, ", ", domainSourceID, ", ", sqlite3_column_int(query, 1)); - flatTree.push_back(tree.insertItem(domainSourceID, refGateway.second.gatewayID, parent)); - } - } - } - }); - i++; - } while (flatTree.size() > (i - 1)); + bool ret = isConnected(gateway); + return ret; +} - return (E_OK); +bool CAmDatabaseHandlerMap::isComponentConnected(const am_Converter_s & converter) const +{ + bool ret = isConnected(converter); + return ret; } am_Error_e am::CAmDatabaseHandlerMap::peekSinkClassID(const std::string & name, am_sinkClass_t & sinkClassID) @@ -2731,6 +2824,37 @@ am_Error_e CAmDatabaseHandlerMap::changeGatewayDB(const am_gatewayID_t gatewayID return (E_OK); } +am_Error_e CAmDatabaseHandlerMap::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) +{ + assert(converterID!=0); + + if (!existConverter(converterID)) + { + return (E_NON_EXISTENT); + } + + if (!listSourceConnectionFormats.empty()) + { + mMappedData.mConverterMap.at(converterID).listSourceFormats = listSourceConnectionFormats; + } + + if (!listSinkConnectionFormats.empty()) + { + mMappedData.mConverterMap.at(converterID).listSinkFormats = listSinkConnectionFormats; + } + + if (!convertionMatrix.empty()) + { + mListConnectionFormat.clear(); + mListConnectionFormat.insert(std::make_pair(converterID, convertionMatrix)); + } + + logInfo("DatabaseHandler::changeConverterDB changed Gateway with ID", converterID); + + //todo: check if observer needs to be adopted. + return (E_OK); +} + bool changeNotificationConfiguration(std::vector<am_NotificationConfiguration_s> & listNotificationConfigurations, const am_NotificationConfiguration_s & notificationConfiguration) { bool changed = false; @@ -2782,4 +2906,46 @@ am_Error_e CAmDatabaseHandlerMap::changeSourceNotificationConfigurationDB(const return (E_NON_EXISTENT); } +am_Error_e CAmDatabaseHandlerMap::enumerateSources(std::function<void(const am_Source_s & element)> cb) const +{ + for(auto it = mMappedData.mSourceMap.begin(); it!=mMappedData.mSourceMap.end(); it++) + { + const am_Source_Database_s *pObject = &it->second; + if( 0==pObject->reserved ) + cb(*pObject); + } + return E_OK; +} + +am_Error_e CAmDatabaseHandlerMap::enumerateSinks(std::function<void(const am_Sink_s & element)> cb) const +{ + for(auto it = mMappedData.mSinkMap.begin(); it!=mMappedData.mSinkMap.end(); it++) + { + const am_Sink_Database_s *pObject = &it->second; + if( 0==pObject->reserved ) + cb(*pObject); + } + return E_OK; +} + +am_Error_e CAmDatabaseHandlerMap::enumerateGateways(std::function<void(const am_Gateway_s & element)> cb) const +{ + for(auto it = mMappedData.mGatewayMap.begin(); it!=mMappedData.mGatewayMap.end(); it++) + { + const am_Gateway_s *pObject = &it->second; + cb(*pObject); + } + return E_OK; +} + +am_Error_e CAmDatabaseHandlerMap::enumerateConverters(std::function<void(const am_Converter_s & element)> cb) const +{ + for(auto it = mMappedData.mConverterMap.begin(); it!=mMappedData.mConverterMap.end(); it++) + { + const am_Converter_s *pObject = &it->second; + cb(*pObject); + } + return E_OK; +} + } diff --git a/AudioManagerDaemon/src/CAmDatabaseHandlerSQLite.cpp b/AudioManagerDaemon/src/CAmDatabaseHandlerSQLite.cpp index 1390fc4..cb95ec6 100644 --- a/AudioManagerDaemon/src/CAmDatabaseHandlerSQLite.cpp +++ b/AudioManagerDaemon/src/CAmDatabaseHandlerSQLite.cpp @@ -104,6 +104,7 @@ namespace am #define SOURCE_TABLE "Sources" //!< source table #define SINK_TABLE "Sinks" //!< sink table #define GATEWAY_TABLE "Gateways" //!< gateway table +#define CONVERTER_TABLE "Converters" //!< converter table #define CROSSFADER_TABLE "Crossfaders" //!< crossfader table #define CONNECTION_TABLE "Connections" //!< connection table #define MAINCONNECTION_TABLE "MainConnections" //!< main connection table @@ -118,6 +119,7 @@ const std::string databaseTables[] = " Sources (sourceID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, domainID INTEGER, name VARCHAR(50), sourceClassID INTEGER, sourceState INTEGER, volume INTEGER, visible BOOL, availability INTEGER, availabilityReason INTEGER, interruptState INTEGER, reserved BOOL);", // " Sinks (sinkID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name VARCHAR(50), domainID INTEGER, sinkClassID INTEGER, volume INTEGER, visible BOOL, availability INTEGER, availabilityReason INTEGER, muteState INTEGER, mainVolume INTEGER, reserved BOOL);", // " Gateways (gatewayID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name VARCHAR(50), sinkID INTEGER, sourceID INTEGER, domainSinkID INTEGER, domainSourceID INTEGER, controlDomainID INTEGER);", // + " Converters (converterID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name VARCHAR(50), sinkID INTEGER, sourceID INTEGER, domainID INTEGER);", // " Crossfaders (crossfaderID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name VARCHAR(50), sinkID_A INTEGER, sinkID_B INTEGER, sourceID INTEGER, hotSink INTEGER);", // " Connections (connectionID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, sourceID INTEGER, sinkID INTEGER, delay INTEGER, connectionFormat INTEGER, reserved BOOL);", // " MainConnections (mainConnectionID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, sourceID INTEGER, sinkID INTEGER, connectionState INTEGER, delay INTEGER);", // @@ -140,6 +142,7 @@ CAmDatabaseHandlerSQLite::CAmDatabaseHandlerSQLite():mpDatabaseObserver(NULL), / mFirstStaticSink(true), // mFirstStaticSource(true), // mFirstStaticGateway(true), // + mFirstStaticConverter(true), mFirstStaticSinkClass(true), // mFirstStaticSourceClass(true), // mFirstStaticCrossfader(true), // @@ -154,6 +157,7 @@ CAmDatabaseHandlerSQLite::CAmDatabaseHandlerSQLite(std::string databasePath):mpD mFirstStaticSink(true), // mFirstStaticSource(true), // mFirstStaticGateway(true), // + mFirstStaticConverter(true), mFirstStaticSinkClass(true), // mFirstStaticSourceClass(true), // mFirstStaticCrossfader(true), // @@ -582,7 +586,7 @@ am_Error_e CAmDatabaseHandlerSQLite::enterCrossfaderDB(const am_Crossfader_s & c else { //check if the ID already exists - if (existcrossFader(crossfaderData.crossfaderID)) + if (existCrossFader(crossfaderData.crossfaderID)) return (E_ALREADY_EXISTS); command = "INSERT INTO " + std::string(CROSSFADER_TABLE) + "(name, sinkID_A, sinkID_B, sourceID, hotSink, crossfaderID) VALUES (?,?,?,?,?,?)"; } @@ -760,6 +764,119 @@ am_Error_e CAmDatabaseHandlerSQLite::enterGatewayDB(const am_Gateway_s & gateway return (E_OK); } +am_Error_e CAmDatabaseHandlerSQLite::enterConverterDB(const am_Converter_s & converterData, am_converterID_t & converterID) +{ + assert(converterData.converterID<DYNAMIC_ID_BOUNDARY); + assert(converterData.sinkID!=0); + assert(converterData.sourceID!=0); + assert(converterData.domainID!=0); + assert(!converterData.name.empty()); + assert(!converterData.convertionMatrix.empty()); + assert(!converterData.listSinkFormats.empty()); + assert(!converterData.listSourceFormats.empty()); + + //might be that the sinks and sources are not there during registration time + //assert(existSink(gatewayData.sinkID)); + //assert(existSource(gatewayData.sourceID)); + + sqlite3_stmt* query = NULL; + int eCode = 0; + std::string command; + + //if gatewayData is zero and the first Static Sink was already entered, the ID is created + if (converterData.converterID == 0 && !mFirstStaticConverter) + { + command = "INSERT INTO " + std::string(CONVERTER_TABLE) + "(name, sinkID, sourceID, domainID) VALUES (?,?,?,?)"; + } + else + { + //check if the ID already exists + if (existConverter(converterData.converterID)) + return (E_ALREADY_EXISTS); + command = "INSERT INTO " + std::string(CONVERTER_TABLE) + "(name, sinkID, sourceID, domainID, converterID) VALUES (?,?,?,?,?)"; + } + + MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) + MY_SQLITE_BIND_TEXT(query, 1, converterData.name.c_str(), converterData.name.size(), SQLITE_STATIC) + MY_SQLITE_BIND_INT(query, 2, converterData.sinkID) + MY_SQLITE_BIND_INT(query, 3, converterData.sourceID) + MY_SQLITE_BIND_INT(query, 4, converterData.domainID) + + //if the ID is not created, we add it to the query + if (converterData.converterID != 0) + { + MY_SQLITE_BIND_INT(query, 5, converterData.converterID) + } + + //if the first static sink is entered, we need to set it onto the boundary + else if (mFirstStaticConverter) + { + MY_SQLITE_BIND_INT(query, 5, DYNAMIC_ID_BOUNDARY) + mFirstStaticConverter = false; + } + + if ((eCode = sqlite3_step(query)) != SQLITE_DONE) + { + logError("DatabaseHandler::enterConverterDB SQLITE Step error code:", eCode); + MY_SQLITE_FINALIZE(query) + return (E_DATABASE_ERROR); + } + + MY_SQLITE_FINALIZE(query) + + converterID = sqlite3_last_insert_rowid(mpDatabase); + + //now the convertion matrix todo: change the map implementation sometimes to blob in sqlite + mListConnectionFormat.insert(std::make_pair(converterID, converterData.convertionMatrix)); + + command = "CREATE TABLE ConverterSourceFormat" + i2s(converterID) + std::string("(soundFormat INTEGER)"); + if (!this->sqQuery(command)) + return (E_DATABASE_ERROR); + command = "CREATE TABLE ConverterSinkFormat" + i2s(converterID) + std::string("(soundFormat INTEGER)"); + if (!this->sqQuery(command)) + return (E_DATABASE_ERROR); + + //fill ConnectionFormats + command = "INSERT INTO ConverterSourceFormat" + i2s(converterID) + std::string("(soundFormat) VALUES (?)"); + MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) + std::vector<am_CustomConnectionFormat_t>::const_iterator connectionFormatIterator = converterData.listSourceFormats.begin(); + for (; connectionFormatIterator < converterData.listSourceFormats.end(); ++connectionFormatIterator) + { + MY_SQLITE_BIND_INT(query, 1, *connectionFormatIterator) + if ((eCode = sqlite3_step(query)) != SQLITE_DONE) + { + logError("DatabaseHandler::enterConverterDB SQLITE Step error code:", eCode); + MY_SQLITE_FINALIZE(query) + return (E_DATABASE_ERROR); + } + MY_SQLITE_RESET(query) + } + MY_SQLITE_FINALIZE(query) + + command = "INSERT INTO ConverterSinkFormat" + i2s(converterID) + std::string("(soundFormat) VALUES (?)"); + MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) + connectionFormatIterator = converterData.listSinkFormats.begin(); + for (; connectionFormatIterator < converterData.listSinkFormats.end(); ++connectionFormatIterator) + { + MY_SQLITE_BIND_INT(query, 1, *connectionFormatIterator) + if ((eCode = sqlite3_step(query)) != SQLITE_DONE) + { + logError("DatabaseHandler::enterConverterDB SQLITE Step error code:", eCode); + MY_SQLITE_FINALIZE(query) + return (E_DATABASE_ERROR); + } + MY_SQLITE_RESET(query) + } + MY_SQLITE_FINALIZE(query) + + logInfo("DatabaseHandler::enterConverterDB entered new gateway with name", converterData.name, "sourceID:", converterData.sourceID, "sinkID:", converterData.sinkID, "assigned ID:", converterID); + am_Converter_s converter = converterData; + converter.converterID = converterID; + if (mpDatabaseObserver) + mpDatabaseObserver->newConverter(converter); + return (E_OK); +} + am_Error_e CAmDatabaseHandlerSQLite::enterSourceDB(const am_Source_s & sourceData, am_sourceID_t & sourceID) { assert(sourceData.sourceID<DYNAMIC_ID_BOUNDARY); @@ -1438,11 +1555,28 @@ am_Error_e CAmDatabaseHandlerSQLite::removeGatewayDB(const am_gatewayID_t gatewa return (E_OK); } +am_Error_e CAmDatabaseHandlerSQLite::removeConverterDB(const am_converterID_t converterID) +{ + assert(converterID!=0); + + if (!existConverter(converterID)) + { + return (E_NON_EXISTENT); + } + std::string command = "DELETE from " + std::string(CONVERTER_TABLE) + " WHERE converterID=" + i2s(converterID); + if (!sqQuery(command)) + return (E_DATABASE_ERROR); + logInfo("DatabaseHandler::removeConverterDB removed:", converterID); + if (mpDatabaseObserver) + mpDatabaseObserver->removeConverter(converterID); + return (E_OK); +} + am_Error_e CAmDatabaseHandlerSQLite::removeCrossfaderDB(const am_crossfaderID_t crossfaderID) { assert(crossfaderID!=0); - if (!existcrossFader(crossfaderID)) + if (!existCrossFader(crossfaderID)) { return (E_NON_EXISTENT); } @@ -2061,10 +2195,79 @@ am_Error_e CAmDatabaseHandlerSQLite::getGatewayInfoDB(const am_gatewayID_t gatew } +am_Error_e CAmDatabaseHandlerSQLite::getConverterInfoDB(const am_converterID_t converterID, am_Converter_s& converterData) const +{ + assert(converterID!=0); + if (!existConverter(converterID)) + { + return (E_NON_EXISTENT); + } + sqlite3_stmt* query = NULL, *qSinkConnectionFormat = NULL, *qSourceConnectionFormat = NULL; + int eCode = 0; + am_CustomConnectionFormat_t tempConnectionFormat; + std::string command = "SELECT name, sinkID, sourceID, domainID, converterID FROM " + std::string(CONVERTER_TABLE) + " WHERE converterID=" + i2s(converterID); + MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) + + while ((eCode = sqlite3_step(query)) == SQLITE_ROW) + { + converterData.name = std::string((const char*) sqlite3_column_text(query, 0)); + converterData.sinkID = sqlite3_column_int(query, 1); + converterData.sourceID = sqlite3_column_int(query, 2); + converterData.domainID = sqlite3_column_int(query, 3); + converterData.converterID = sqlite3_column_int(query, 4); + + //convertionMatrix: + ListConnectionFormat::const_iterator iter = mListConnectionFormat.begin(); + iter = mListConnectionFormat.find(converterData.converterID); + if (iter == mListConnectionFormat.end()) + { + logError("DatabaseHandler::getConverterInfoDB database error with convertionFormat"); + MY_SQLITE_FINALIZE(query) + return (E_DATABASE_ERROR); + } + converterData.convertionMatrix = iter->second; + + //read out the connectionFormats + std::string commandConnectionFormat = "SELECT soundFormat FROM ConverterSourceFormat" + i2s(converterData.converterID); + MY_SQLITE_PREPARE_V2(mpDatabase, commandConnectionFormat.c_str(), -1, &qSourceConnectionFormat, NULL) + while ((eCode = sqlite3_step(qSourceConnectionFormat)) == SQLITE_ROW) + { + tempConnectionFormat = (am_CustomConnectionFormat_t) sqlite3_column_int(qSourceConnectionFormat, 0); + converterData.listSourceFormats.push_back(tempConnectionFormat); + } + + MY_SQLITE_FINALIZE(qSourceConnectionFormat) + + //read out sound properties + commandConnectionFormat = "SELECT soundFormat FROM ConverterSinkFormat" + i2s(converterData.converterID); + MY_SQLITE_PREPARE_V2(mpDatabase, commandConnectionFormat.c_str(), -1, &qSinkConnectionFormat, NULL) + while ((eCode = sqlite3_step(qSinkConnectionFormat)) == SQLITE_ROW) + { + tempConnectionFormat = (am_CustomConnectionFormat_t) sqlite3_column_int(qSinkConnectionFormat, 0); + converterData.listSinkFormats.push_back(tempConnectionFormat); + } + + MY_SQLITE_FINALIZE(qSinkConnectionFormat) + + } + + if (eCode != SQLITE_DONE) + { + logError("DatabaseHandler::getConverterInfoDB SQLITE error code:", eCode); + MY_SQLITE_FINALIZE(query) + return (E_DATABASE_ERROR); + } + + MY_SQLITE_FINALIZE(query) + + return (E_OK); + +} + am_Error_e CAmDatabaseHandlerSQLite::getCrossfaderInfoDB(const am_crossfaderID_t crossfaderID, am_Crossfader_s & crossfaderData) const { assert(crossfaderID!=0); - if (!existcrossFader(crossfaderID)) + if (!existCrossFader(crossfaderID)) { return (E_NON_EXISTENT); } @@ -2226,6 +2429,39 @@ am_Error_e CAmDatabaseHandlerSQLite::getListGatewaysOfDomain(const am_domainID_t return (E_OK); } +am_Error_e CAmDatabaseHandlerSQLite::getListConvertersOfDomain(const am_domainID_t domainID, std::vector<am_converterID_t>& listConvertersID) const +{ + assert(domainID!=0); + listConvertersID.clear(); + if (!existDomain(domainID)) + { + return (E_NON_EXISTENT); + } + sqlite3_stmt* query = NULL; + int eCode = 0; + am_gatewayID_t temp; + + std::string command = "SELECT converterID FROM " + std::string(CONVERTER_TABLE) + " WHERE domainID=" + i2s(domainID); + MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) + + while ((eCode = sqlite3_step(query)) == SQLITE_ROW) + { + temp = sqlite3_column_int(query, 0); + listConvertersID.push_back(temp); + } + + if (eCode != SQLITE_DONE) + { + logError("DatabaseHandler::getListConvertersOfDomain SQLITE error code:", eCode); + MY_SQLITE_FINALIZE(query) + return (E_DATABASE_ERROR); + } + + MY_SQLITE_FINALIZE(query) + + return (E_OK); +} + am_Error_e CAmDatabaseHandlerSQLite::getListMainConnections(std::vector<am_MainConnection_s> & listMainConnections) const { listMainConnections.clear(); @@ -2332,217 +2568,13 @@ am_Error_e CAmDatabaseHandlerSQLite::getListConnections(std::vector<am_Connectio am_Error_e CAmDatabaseHandlerSQLite::getListSinks(std::vector<am_Sink_s> & listSinks) const { listSinks.clear(); - sqlite3_stmt* query = NULL, *qConnectionFormat = NULL, *qSoundProperty = NULL, *qNotificationConfiguration= NULL, *qMAinSoundProperty = NULL, *qMainNotificationConfiguration= NULL; - int eCode = 0; - am_Sink_s temp; - am_CustomConnectionFormat_t tempConnectionFormat; - am_SoundProperty_s tempSoundProperty; - am_MainSoundProperty_s tempMainSoundProperty; - am_NotificationConfiguration_s tempNotificationConfiguration; - am_NotificationConfiguration_s tempMainNotificationConfiguration; - std::string command = "SELECT name, domainID, sinkClassID, volume, visible, availability, availabilityReason, muteState, mainVolume, sinkID FROM " + std::string(SINK_TABLE) + " WHERE reserved=0"; - MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) - - while ((eCode = sqlite3_step(query)) == SQLITE_ROW) - { - temp.name = std::string((const char*) sqlite3_column_text(query, 0)); - temp.domainID = sqlite3_column_int(query, 1); - temp.sinkClassID = sqlite3_column_int(query, 2); - temp.volume = sqlite3_column_int(query, 3); - temp.visible = sqlite3_column_int(query, 4); - temp.available.availability = (am_Availability_e) sqlite3_column_int(query, 5); - temp.available.availabilityReason = (am_CustomAvailabilityReason_t) sqlite3_column_int(query, 6); - temp.muteState = (am_MuteState_e) sqlite3_column_int(query, 7); - temp.mainVolume = sqlite3_column_int(query, 8); - temp.sinkID = sqlite3_column_int(query, 9); - - //read out the connectionFormats - std::string commandConnectionFormat = "SELECT soundFormat FROM SinkConnectionFormat" + i2s(temp.sinkID); - MY_SQLITE_PREPARE_V2(mpDatabase, commandConnectionFormat.c_str(), -1, &qConnectionFormat, NULL) - while ((eCode = sqlite3_step(qConnectionFormat)) == SQLITE_ROW) - { - tempConnectionFormat = (am_CustomConnectionFormat_t) sqlite3_column_int(qConnectionFormat, 0); - temp.listConnectionFormats.push_back(tempConnectionFormat); - } - - MY_SQLITE_FINALIZE(qConnectionFormat) - - //read out sound properties - std::string commandSoundProperty = "SELECT soundPropertyType, value FROM SinkSoundProperty" + i2s(temp.sinkID); - MY_SQLITE_PREPARE_V2(mpDatabase, commandSoundProperty.c_str(), -1, &qSoundProperty, NULL) - while ((eCode = sqlite3_step(qSoundProperty)) == SQLITE_ROW) - { - tempSoundProperty.type = (am_CustomSoundPropertyType_t) sqlite3_column_int(qSoundProperty, 0); - tempSoundProperty.value = sqlite3_column_int(qSoundProperty, 1); - temp.listSoundProperties.push_back(tempSoundProperty); - } - - MY_SQLITE_FINALIZE(qSoundProperty) - - //read out notifications - std::string commandNotificationConfiguration = "SELECT type, status, parameter FROM SinkNotificationConfiguration" + i2s(temp.sinkID); - MY_SQLITE_PREPARE_V2(mpDatabase, commandNotificationConfiguration.c_str(), -1, &qNotificationConfiguration, NULL) - while ((eCode = sqlite3_step(qNotificationConfiguration)) == SQLITE_ROW) - { - tempNotificationConfiguration.type = static_cast<am_CustomNotificationType_t> (sqlite3_column_int(qNotificationConfiguration, 0)); - tempNotificationConfiguration.status = static_cast<am_NotificationStatus_e> (sqlite3_column_int(qNotificationConfiguration, 1)); - tempNotificationConfiguration.parameter = static_cast<int16_t> (sqlite3_column_int(qNotificationConfiguration, 2)); - temp.listNotificationConfigurations.push_back(tempNotificationConfiguration); - } - - MY_SQLITE_FINALIZE(qNotificationConfiguration) - - //read out MainSoundProperties if sink is visible - if(temp.visible) - { - std::string commandMainSoundProperty = "SELECT soundPropertyType, value FROM SinkMainSoundProperty" + i2s(temp.sinkID); - MY_SQLITE_PREPARE_V2(mpDatabase, commandMainSoundProperty.c_str(), -1, &qMAinSoundProperty, NULL) - while ((eCode = sqlite3_step(qMAinSoundProperty)) == SQLITE_ROW) - { - tempMainSoundProperty.type = (am_CustomMainSoundPropertyType_t) sqlite3_column_int(qMAinSoundProperty, 0); - tempMainSoundProperty.value = sqlite3_column_int(qMAinSoundProperty, 1); - temp.listMainSoundProperties.push_back(tempMainSoundProperty); - } - - MY_SQLITE_FINALIZE(qMAinSoundProperty) - - //and mainNotificationConfigurations - std::string commandMainNotificationConfiguration = "SELECT type, status, parameter FROM SinkMainNotificationConfiguration" + i2s(temp.sinkID); - MY_SQLITE_PREPARE_V2(mpDatabase, commandMainNotificationConfiguration.c_str(), -1, &qMainNotificationConfiguration, NULL) - while ((eCode = sqlite3_step(qMainNotificationConfiguration)) == SQLITE_ROW) - { - tempMainNotificationConfiguration.type = static_cast <am_CustomNotificationType_t> (sqlite3_column_int(qMainNotificationConfiguration, 0)); - tempMainNotificationConfiguration.status = static_cast <am_NotificationStatus_e> (sqlite3_column_int(qMainNotificationConfiguration, 1)); - tempMainNotificationConfiguration.parameter = static_cast <uint16_t>(sqlite3_column_int(qMainNotificationConfiguration, 2)); - temp.listMainNotificationConfigurations.push_back(tempMainNotificationConfiguration); - } - - MY_SQLITE_FINALIZE(qMainNotificationConfiguration) - } - - listSinks.push_back(temp); - temp.listConnectionFormats.clear(); - temp.listMainSoundProperties.clear(); - temp.listSoundProperties.clear(); - } - - if (eCode != SQLITE_DONE) - { - logError("DatabaseHandler::getListSinks SQLITE error code:", eCode); - MY_SQLITE_FINALIZE(query) - return (E_DATABASE_ERROR); - } - - MY_SQLITE_FINALIZE(query) - - return (E_OK); + return enumerateSinks([&](const am_Sink_s & sink){ listSinks.push_back(sink);}); } am_Error_e CAmDatabaseHandlerSQLite::getListSources(std::vector<am_Source_s> & listSources) const { listSources.clear(); - sqlite3_stmt* query = NULL, *qConnectionFormat = NULL, *qSoundProperty = NULL, *qMAinSoundProperty = NULL, *qNotification(NULL), *qMainNotification(NULL); - int eCode = 0; - am_Source_s temp; - am_CustomConnectionFormat_t tempConnectionFormat; - am_SoundProperty_s tempSoundProperty; - am_MainSoundProperty_s tempMainSoundProperty; - am_NotificationConfiguration_s tempNotificationConfiguration; - std::string command = "SELECT name, domainID, sourceClassID, sourceState, volume, visible, availability, availabilityReason, interruptState, sourceID FROM " + std::string(SOURCE_TABLE) + " WHERE reserved=0"; - MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) - - while ((eCode = sqlite3_step(query)) == SQLITE_ROW) - { - temp.name = std::string((const char*) sqlite3_column_text(query, 0)); - temp.domainID = sqlite3_column_int(query, 1); - temp.sourceClassID = sqlite3_column_int(query, 2); - temp.sourceState = (am_SourceState_e) sqlite3_column_int(query, 3); - temp.volume = sqlite3_column_int(query, 4); - temp.visible = sqlite3_column_int(query, 5); - temp.available.availability = (am_Availability_e) sqlite3_column_int(query, 6); - temp.available.availabilityReason = (am_CustomAvailabilityReason_t) sqlite3_column_int(query, 7); - temp.interruptState = (am_InterruptState_e) sqlite3_column_int(query, 8); - temp.sourceID = sqlite3_column_int(query, 9); - - //read out the connectionFormats - std::string commandConnectionFormat = "SELECT soundFormat FROM SourceConnectionFormat" + i2s(temp.sourceID); - MY_SQLITE_PREPARE_V2(mpDatabase, commandConnectionFormat.c_str(), -1, &qConnectionFormat, NULL) - while ((eCode = sqlite3_step(qConnectionFormat)) == SQLITE_ROW) - { - tempConnectionFormat = (am_CustomConnectionFormat_t) sqlite3_column_int(qConnectionFormat, 0); - temp.listConnectionFormats.push_back(tempConnectionFormat); - } - - MY_SQLITE_FINALIZE(qConnectionFormat) - - //read out sound properties - std::string commandSoundProperty = "SELECT soundPropertyType, value FROM SourceSoundProperty" + i2s(temp.sourceID); - MY_SQLITE_PREPARE_V2(mpDatabase, commandSoundProperty.c_str(), -1, &qSoundProperty, NULL) - while ((eCode = sqlite3_step(qSoundProperty)) == SQLITE_ROW) - { - tempSoundProperty.type = (am_CustomSoundPropertyType_t) sqlite3_column_int(qSoundProperty, 0); - tempSoundProperty.value = sqlite3_column_int(qSoundProperty, 1); - temp.listSoundProperties.push_back(tempSoundProperty); - } - - MY_SQLITE_FINALIZE(qSoundProperty) - - std::string notificationCommand = "SELECT type, status, parameter FROM SourceNotificationConfiguration" + i2s(temp.sourceID); - MY_SQLITE_PREPARE_V2(mpDatabase, notificationCommand.c_str(), -1, &qNotification, NULL) - - while ((eCode = sqlite3_step(qNotification)) == SQLITE_ROW) - { - tempNotificationConfiguration.type = static_cast<am_CustomNotificationType_t>(sqlite3_column_int(qNotification, 0)); - tempNotificationConfiguration.status = static_cast<am_NotificationStatus_e>(sqlite3_column_int(qNotification, 1)); - tempNotificationConfiguration.parameter= static_cast<int16_t>(sqlite3_column_int(qNotification, 2)); - temp.listNotificationConfigurations.push_back(tempNotificationConfiguration); - } - MY_SQLITE_FINALIZE(qNotification) - - //read out MainSoundProperties if source is visible - if(temp.visible) - { - std::string commandMainSoundProperty = "SELECT soundPropertyType, value FROM SourceMainSoundProperty" + i2s(temp.sourceID); - MY_SQLITE_PREPARE_V2(mpDatabase, commandMainSoundProperty.c_str(), -1, &qMAinSoundProperty, NULL) - while ((eCode = sqlite3_step(qMAinSoundProperty)) == SQLITE_ROW) - { - tempMainSoundProperty.type = (am_CustomMainSoundPropertyType_t) sqlite3_column_int(qMAinSoundProperty, 0); - tempMainSoundProperty.value = sqlite3_column_int(qMAinSoundProperty, 1); - temp.listMainSoundProperties.push_back(tempMainSoundProperty); - } - - MY_SQLITE_FINALIZE(qMAinSoundProperty) - - std::string mainNotificationCommand = "SELECT type, status, parameter FROM SourceMainNotificationConfiguration" + i2s(temp.sourceID); - MY_SQLITE_PREPARE_V2(mpDatabase, mainNotificationCommand.c_str(), -1, &qMainNotification, NULL) - - while ((eCode = sqlite3_step(qMainNotification)) == SQLITE_ROW) - { - tempNotificationConfiguration.type = static_cast<am_CustomNotificationType_t>(sqlite3_column_int(qMainNotification, 0)); - tempNotificationConfiguration.status = static_cast<am_NotificationStatus_e>(sqlite3_column_int(qMainNotification, 1)); - tempNotificationConfiguration.parameter= static_cast<int16_t>(sqlite3_column_int(qMainNotification, 2)); - temp.listMainNotificationConfigurations.push_back(tempNotificationConfiguration); - } - MY_SQLITE_FINALIZE(qMainNotification) - } - - - listSources.push_back(temp); - temp.listConnectionFormats.clear(); - temp.listMainSoundProperties.clear(); - temp.listSoundProperties.clear(); - } - - if (eCode != SQLITE_DONE) - { - logError("DatabaseHandler::getListSources SQLITE error code:", eCode); - MY_SQLITE_FINALIZE(query) - return (E_DATABASE_ERROR); - } - - MY_SQLITE_FINALIZE(query) - - return (E_OK); + return enumerateSources([&](const am_Source_s & source){ listSources.push_back(source);}); } am_Error_e CAmDatabaseHandlerSQLite::getListSourceClasses(std::vector<am_SourceClass_s> & listSourceClasses) const @@ -2634,72 +2666,13 @@ am_Error_e CAmDatabaseHandlerSQLite::getListCrossfaders(std::vector<am_Crossfade am_Error_e CAmDatabaseHandlerSQLite::getListGateways(std::vector<am_Gateway_s> & listGateways) const { listGateways.clear(); - sqlite3_stmt* query = NULL, *qSinkConnectionFormat = NULL, *qSourceConnectionFormat = NULL; - int eCode = 0; - am_Gateway_s temp; - am_CustomConnectionFormat_t tempConnectionFormat; - - std::string command = "SELECT name, sinkID, sourceID, domainSinkID, domainSourceID, controlDomainID, gatewayID FROM " + std::string(GATEWAY_TABLE); - MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) - - while ((eCode = sqlite3_step(query)) == SQLITE_ROW) - { - temp.name = std::string((const char*) sqlite3_column_text(query, 0)); - temp.sinkID = sqlite3_column_int(query, 1); - temp.sourceID = sqlite3_column_int(query, 2); - temp.domainSinkID = sqlite3_column_int(query, 3); - temp.domainSourceID = sqlite3_column_int(query, 4); - temp.controlDomainID = sqlite3_column_int(query, 5); - temp.gatewayID = sqlite3_column_int(query, 6); - - //convertionMatrix: - ListConnectionFormat::const_iterator iter = mListConnectionFormat.begin(); - iter = mListConnectionFormat.find(temp.gatewayID); - if (iter == mListConnectionFormat.end()) - { - logError("DatabaseHandler::getListGateways database error with convertionFormat"); - - return (E_DATABASE_ERROR); - } - temp.convertionMatrix = iter->second; - - //read out the connectionFormats - std::string commandConnectionFormat = "SELECT soundFormat FROM GatewaySourceFormat" + i2s(temp.gatewayID); - MY_SQLITE_PREPARE_V2(mpDatabase, commandConnectionFormat.c_str(), -1, &qSourceConnectionFormat, NULL) - while ((eCode = sqlite3_step(qSourceConnectionFormat)) == SQLITE_ROW) - { - tempConnectionFormat = (am_CustomConnectionFormat_t) sqlite3_column_int(qSourceConnectionFormat, 0); - temp.listSourceFormats.push_back(tempConnectionFormat); - } - - MY_SQLITE_FINALIZE(qSourceConnectionFormat) - - //read out sound properties - commandConnectionFormat = "SELECT soundFormat FROM GatewaySinkFormat" + i2s(temp.gatewayID); - MY_SQLITE_PREPARE_V2(mpDatabase, commandConnectionFormat.c_str(), -1, &qSinkConnectionFormat, NULL) - while ((eCode = sqlite3_step(qSinkConnectionFormat)) == SQLITE_ROW) - { - tempConnectionFormat = (am_CustomConnectionFormat_t) sqlite3_column_int(qSinkConnectionFormat, 0); - temp.listSinkFormats.push_back(tempConnectionFormat); - } - - MY_SQLITE_FINALIZE(qSinkConnectionFormat) - - listGateways.push_back(temp); - temp.listSinkFormats.clear(); - temp.listSourceFormats.clear(); - } - - if (eCode != SQLITE_DONE) - { - logError("DatabaseHandler::getListGateways SQLITE error code:", eCode); - MY_SQLITE_FINALIZE(query) - return (E_DATABASE_ERROR); - } - - MY_SQLITE_FINALIZE(query) + return enumerateGateways([&](const am_Gateway_s & gateway){ listGateways.push_back(gateway);}); +} - return (E_OK); +am_Error_e CAmDatabaseHandlerSQLite::getListConverters(std::vector<am_Converter_s> & listConverters) const +{ + listConverters.clear(); + return enumerateConverters([&](const am_Converter_s & converter){ listConverters.push_back(converter);}); } am_Error_e CAmDatabaseHandlerSQLite::getListSinkClasses(std::vector<am_SinkClass_s> & listSinkClasses) const @@ -3001,6 +2974,21 @@ am_Error_e am::CAmDatabaseHandlerSQLite::getListGatewayConnectionFormats(const a return (E_OK); } +am_Error_e am::CAmDatabaseHandlerSQLite::getListConverterConnectionFormats(const am_converterID_t converterID, std::vector<bool> & listConnectionFormat) const +{ + ListConnectionFormat::const_iterator iter = mListConnectionFormat.begin(); + iter = mListConnectionFormat.find(converterID); + if (iter == mListConnectionFormat.end()) + { + logError("DatabaseHandler::getListConverterConnectionFormats database error with convertionFormat"); + + return (E_DATABASE_ERROR); + } + listConnectionFormat = iter->second; + + return (E_OK); +} + am_Error_e CAmDatabaseHandlerSQLite::getTimingInformation(const am_mainConnectionID_t mainConnectionID, am_timeSync_t & delay) const { assert(mainConnectionID!=0); @@ -3573,6 +3561,26 @@ bool CAmDatabaseHandlerSQLite::existGateway(const am_gatewayID_t gatewayID) cons return (returnVal); } +bool CAmDatabaseHandlerSQLite::existConverter(const am_converterID_t converterID) const +{ + sqlite3_stmt* query = NULL; + std::string command = "SELECT converterID FROM " + std::string(CONVERTER_TABLE) + " WHERE converterID=" + i2s(converterID); + int eCode = 0; + bool returnVal = true; + MY_SQLITE_PREPARE_V2_BOOL(mpDatabase, command.c_str(), -1, &query, NULL) + + if ((eCode = sqlite3_step(query)) == SQLITE_DONE) + returnVal = false; + else if (eCode != SQLITE_ROW) + { + returnVal = false; + logError("DatabaseHandler::existConverter database error!:", eCode); + } + + MY_SQLITE_FINALIZE_BOOL(query) + return (returnVal); +} + am_Error_e CAmDatabaseHandlerSQLite::getDomainOfSource(const am_sourceID_t sourceID, am_domainID_t & domainID) const { assert(sourceID!=0); @@ -3928,7 +3936,7 @@ bool CAmDatabaseHandlerSQLite::existConnectionID(const am_connectionID_t connect * @param crossfaderID the ID of the crossfader to be checked * @return true if exists */ -bool CAmDatabaseHandlerSQLite::existcrossFader(const am_crossfaderID_t crossfaderID) const +bool CAmDatabaseHandlerSQLite::existCrossFader(const am_crossfaderID_t crossfaderID) const { sqlite3_stmt* query = NULL; std::string command = "SELECT crossfaderID FROM " + std::string(CROSSFADER_TABLE) + " WHERE crossfaderID=?"; @@ -4367,7 +4375,7 @@ am_Error_e CAmDatabaseHandlerSQLite::changeCrossFaderHotSink(const am_crossfader int eCode = 0; std::string command; - if (!existcrossFader(crossfaderID)) + if (!existCrossFader(crossfaderID)) { return (E_NON_EXISTENT); } @@ -4385,63 +4393,53 @@ am_Error_e CAmDatabaseHandlerSQLite::changeCrossFaderHotSink(const am_crossfader return (E_OK); } -am_Error_e CAmDatabaseHandlerSQLite::getRoutingTree(bool onlyfree, CAmRoutingTree& tree, std::vector<CAmRoutingTreeItem*>& flatTree) +bool CAmDatabaseHandlerSQLite::isComponentConnected(const am_Gateway_s & gateway) const { - sqlite3_stmt* query = NULL; - int eCode = 0; - size_t i = 0; - std::string command; - am_domainID_t rootID = tree.returnRootDomainID(); - CAmRoutingTreeItem *parent = tree.returnRootItem(); - - if (onlyfree) - { - command = "SELECT g.domainSourceID,g.gatewayID FROM " + std::string(GATEWAY_TABLE) + " g WHERE domainSinkID=? AND NOT EXISTS (SELECT NULL FROM " + std::string(CONNECTION_TABLE) + " c WHERE c.sinkID = g.sinkID OR c.sourceID = g.sourceID )"; - } - else - { - command = "SELECT domainSourceID,gatewayID FROM " + std::string(GATEWAY_TABLE) + " WHERE domainSinkID=?"; - } - - do - { - if (i != 0) - { - parent = flatTree.at(i - 1); - rootID = parent->returnDomainID(); - } - MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) - MY_SQLITE_BIND_INT(query, 1, rootID) - - while ((eCode = sqlite3_step(query)) == SQLITE_ROW) - { - // additional check to avoid cyclic routes - const am_domainID_t domainSourceID = sqlite3_column_int(query, 0); - bool sourceDomainAlreadyHandledAsSink = false; - for (std::vector<CAmRoutingTreeItem*>::const_iterator iFT = flatTree.begin(); iFT != flatTree.end(); ++iFT) - { - if (domainSourceID == (*iFT)->returnParent()->returnDomainID()) sourceDomainAlreadyHandledAsSink = true; - } - - if (!sourceDomainAlreadyHandledAsSink) - { - // logInfo("DatabaseHandler::getRoutingTree ", rootID, ", ", domainSourceID, ", ", sqlite3_column_int(query, 1)); - flatTree.push_back(tree.insertItem(domainSourceID, sqlite3_column_int(query, 1), parent)); - } - } - - if (eCode != SQLITE_DONE) - { - logError("DatabaseHandler::getRoutingTree SQLITE error code:", eCode); - MY_SQLITE_FINALIZE(query) - return (E_DATABASE_ERROR); - } - - MY_SQLITE_FINALIZE(query) - i++; - } while (flatTree.size() > (i - 1)); + sqlite3_stmt* query = NULL; + int eCode = 0; + std::string command; + bool returnVal = true; + command = "SELECT 1 FROM " + std::string(CONNECTION_TABLE) + " c WHERE c.sinkID = ? OR c.sourceID = ?"; + + MY_SQLITE_PREPARE_V2_BOOL(mpDatabase, command.c_str(), -1, &query, NULL) + MY_SQLITE_BIND_INT(query, 1, gateway.sinkID) + MY_SQLITE_BIND_INT(query, 2, gateway.sourceID) + if ((eCode = sqlite3_step(query)) == SQLITE_DONE) + { + returnVal = false; + } + else if (eCode != SQLITE_ROW) + { + returnVal = false; + logError("DatabaseHandler::isComponentConnected database error!:", eCode); + } + MY_SQLITE_FINALIZE(query) + return returnVal; +} - return (E_OK); +bool CAmDatabaseHandlerSQLite::isComponentConnected(const am_Converter_s & converter) const +{ + sqlite3_stmt* query = NULL; + int eCode = 0; + std::string command; + bool returnVal = true; + command = "SELECT 1 FROM " + std::string(CONNECTION_TABLE) + " c WHERE c.sinkID = ? OR c.sourceID = ?"; + + MY_SQLITE_PREPARE_V2_BOOL(mpDatabase, command.c_str(), -1, &query, NULL) + MY_SQLITE_BIND_INT(query, 1, converter.sinkID) + MY_SQLITE_BIND_INT(query, 2, converter.sourceID) + if ((eCode = sqlite3_step(query)) == SQLITE_DONE) + { + returnVal = false; + } + else if (eCode != SQLITE_ROW) + { + returnVal = false; + logError("DatabaseHandler::isComponentConnected database error!:", eCode); + } + MY_SQLITE_FINALIZE(query) + + return returnVal; } am_Error_e am::CAmDatabaseHandlerSQLite::peekSinkClassID(const std::string & name, am_sinkClass_t & sinkClassID) @@ -4979,6 +4977,80 @@ am_Error_e CAmDatabaseHandlerSQLite::changeGatewayDB(const am_gatewayID_t gatewa return (E_OK); } +am_Error_e CAmDatabaseHandlerSQLite::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) +{ + assert(converterID!=0); + + sqlite3_stmt* query = NULL; + int eCode = 0; + std::string command; + + if (!existConverter(converterID)) + { + return (E_NON_EXISTENT); + } + + if (!listSourceConnectionFormats.empty()) + { + //clear Database + command = "DELETE from ConverterSourceFormat" + i2s(converterID); + if (!sqQuery(command)) + return (E_DATABASE_ERROR); + + //fill ConnectionFormats + command = "INSERT INTO ConverterSourceFormat" + i2s(converterID) + std::string("(soundFormat) VALUES (?)"); + MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) + std::vector<am_CustomConnectionFormat_t>::const_iterator connectionFormatIterator = listSourceConnectionFormats.begin(); + for (; connectionFormatIterator < listSourceConnectionFormats.end(); ++connectionFormatIterator) + { + MY_SQLITE_BIND_INT(query, 1, *connectionFormatIterator) + if ((eCode = sqlite3_step(query)) != SQLITE_DONE) + { + logError("DatabaseHandler::enterConverterDB SQLITE Step error code:", eCode); + MY_SQLITE_FINALIZE(query) + return (E_DATABASE_ERROR); + } + MY_SQLITE_RESET(query) + } + MY_SQLITE_FINALIZE(query) + } + + if (!listSinkConnectionFormats.empty()) + { + //clear Database + command = "DELETE from ConverterSinkFormat" + i2s(converterID); + if (!sqQuery(command)) + return (E_DATABASE_ERROR); + + command = "INSERT INTO ConverterSinkFormat" + i2s(converterID) + std::string("(soundFormat) VALUES (?)"); + MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) + std::vector<am_CustomConnectionFormat_t>::const_iterator connectionFormatIterator = listSinkConnectionFormats.begin(); + for (; connectionFormatIterator < listSinkConnectionFormats.end(); ++connectionFormatIterator) + { + MY_SQLITE_BIND_INT(query, 1, *connectionFormatIterator) + if ((eCode = sqlite3_step(query)) != SQLITE_DONE) + { + logError("DatabaseHandler::enterConverterDB SQLITE Step error code:", eCode); + MY_SQLITE_FINALIZE(query) + return (E_DATABASE_ERROR); + } + MY_SQLITE_RESET(query) + } + MY_SQLITE_FINALIZE(query) + } + + if (!convertionMatrix.empty()) + { + mListConnectionFormat.clear(); + mListConnectionFormat.insert(std::make_pair(converterID, convertionMatrix)); + } + + logInfo("DatabaseHandler::changeConverterDB changed Gateway with ID", converterID); + + //todo: check if observer needs to be adopted. + return (E_OK); +} + am_Error_e CAmDatabaseHandlerSQLite::changeSinkNotificationConfigurationDB(const am_sinkID_t sinkID, const am_NotificationConfiguration_s notificationConfiguration) { assert(sinkID!=0); @@ -5048,4 +5120,355 @@ void CAmDatabaseHandlerSQLite::createTables() } } +am_Error_e CAmDatabaseHandlerSQLite::enumerateSources(std::function<void(const am_Source_s & element)> cb) const +{ + sqlite3_stmt* query = NULL, *qConnectionFormat = NULL, *qSoundProperty = NULL, *qMAinSoundProperty = NULL, *qNotification(NULL), *qMainNotification(NULL); + int eCode = 0; + am_Source_s temp; + am_CustomConnectionFormat_t tempConnectionFormat; + am_SoundProperty_s tempSoundProperty; + am_MainSoundProperty_s tempMainSoundProperty; + am_NotificationConfiguration_s tempNotificationConfiguration; + std::string command = "SELECT name, domainID, sourceClassID, sourceState, volume, visible, availability, availabilityReason, interruptState, sourceID FROM " + std::string(SOURCE_TABLE) + " WHERE reserved=0"; + MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) + + while ((eCode = sqlite3_step(query)) == SQLITE_ROW) + { + temp.name = std::string((const char*) sqlite3_column_text(query, 0)); + temp.domainID = sqlite3_column_int(query, 1); + temp.sourceClassID = sqlite3_column_int(query, 2); + temp.sourceState = (am_SourceState_e) sqlite3_column_int(query, 3); + temp.volume = sqlite3_column_int(query, 4); + temp.visible = sqlite3_column_int(query, 5); + temp.available.availability = (am_Availability_e) sqlite3_column_int(query, 6); + temp.available.availabilityReason = (am_CustomAvailabilityReason_t) sqlite3_column_int(query, 7); + temp.interruptState = (am_InterruptState_e) sqlite3_column_int(query, 8); + temp.sourceID = sqlite3_column_int(query, 9); + + //read out the connectionFormats + std::string commandConnectionFormat = "SELECT soundFormat FROM SourceConnectionFormat" + i2s(temp.sourceID); + MY_SQLITE_PREPARE_V2(mpDatabase, commandConnectionFormat.c_str(), -1, &qConnectionFormat, NULL) + while ((eCode = sqlite3_step(qConnectionFormat)) == SQLITE_ROW) + { + tempConnectionFormat = (am_CustomConnectionFormat_t) sqlite3_column_int(qConnectionFormat, 0); + temp.listConnectionFormats.push_back(tempConnectionFormat); + } + + MY_SQLITE_FINALIZE(qConnectionFormat) + + //read out sound properties + std::string commandSoundProperty = "SELECT soundPropertyType, value FROM SourceSoundProperty" + i2s(temp.sourceID); + MY_SQLITE_PREPARE_V2(mpDatabase, commandSoundProperty.c_str(), -1, &qSoundProperty, NULL) + while ((eCode = sqlite3_step(qSoundProperty)) == SQLITE_ROW) + { + tempSoundProperty.type = (am_CustomSoundPropertyType_t) sqlite3_column_int(qSoundProperty, 0); + tempSoundProperty.value = sqlite3_column_int(qSoundProperty, 1); + temp.listSoundProperties.push_back(tempSoundProperty); + } + + MY_SQLITE_FINALIZE(qSoundProperty) + + std::string notificationCommand = "SELECT type, status, parameter FROM SourceNotificationConfiguration" + i2s(temp.sourceID); + MY_SQLITE_PREPARE_V2(mpDatabase, notificationCommand.c_str(), -1, &qNotification, NULL) + + while ((eCode = sqlite3_step(qNotification)) == SQLITE_ROW) + { + tempNotificationConfiguration.type = static_cast<am_CustomNotificationType_t>(sqlite3_column_int(qNotification, 0)); + tempNotificationConfiguration.status = static_cast<am_NotificationStatus_e>(sqlite3_column_int(qNotification, 1)); + tempNotificationConfiguration.parameter= static_cast<int16_t>(sqlite3_column_int(qNotification, 2)); + temp.listNotificationConfigurations.push_back(tempNotificationConfiguration); + } + MY_SQLITE_FINALIZE(qNotification) + + //read out MainSoundProperties if source is visible + if(temp.visible) + { + std::string commandMainSoundProperty = "SELECT soundPropertyType, value FROM SourceMainSoundProperty" + i2s(temp.sourceID); + MY_SQLITE_PREPARE_V2(mpDatabase, commandMainSoundProperty.c_str(), -1, &qMAinSoundProperty, NULL) + while ((eCode = sqlite3_step(qMAinSoundProperty)) == SQLITE_ROW) + { + tempMainSoundProperty.type = (am_CustomMainSoundPropertyType_t) sqlite3_column_int(qMAinSoundProperty, 0); + tempMainSoundProperty.value = sqlite3_column_int(qMAinSoundProperty, 1); + temp.listMainSoundProperties.push_back(tempMainSoundProperty); + } + + MY_SQLITE_FINALIZE(qMAinSoundProperty) + + std::string mainNotificationCommand = "SELECT type, status, parameter FROM SourceMainNotificationConfiguration" + i2s(temp.sourceID); + MY_SQLITE_PREPARE_V2(mpDatabase, mainNotificationCommand.c_str(), -1, &qMainNotification, NULL) + + while ((eCode = sqlite3_step(qMainNotification)) == SQLITE_ROW) + { + tempNotificationConfiguration.type = static_cast<am_CustomNotificationType_t>(sqlite3_column_int(qMainNotification, 0)); + tempNotificationConfiguration.status = static_cast<am_NotificationStatus_e>(sqlite3_column_int(qMainNotification, 1)); + tempNotificationConfiguration.parameter= static_cast<int16_t>(sqlite3_column_int(qMainNotification, 2)); + temp.listMainNotificationConfigurations.push_back(tempNotificationConfiguration); + } + MY_SQLITE_FINALIZE(qMainNotification) + } + + + cb(temp); + temp.listConnectionFormats.clear(); + temp.listMainSoundProperties.clear(); + temp.listSoundProperties.clear(); + } + + if (eCode != SQLITE_DONE) + { + logError("DatabaseHandler::getListSources SQLITE error code:", eCode); + MY_SQLITE_FINALIZE(query) + return (E_DATABASE_ERROR); + } + + MY_SQLITE_FINALIZE(query) + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerSQLite::enumerateSinks(std::function<void(const am_Sink_s & element)> cb) const +{ + sqlite3_stmt* query = NULL, *qConnectionFormat = NULL, *qSoundProperty = NULL, *qNotificationConfiguration= NULL, *qMAinSoundProperty = NULL, *qMainNotificationConfiguration= NULL; + int eCode = 0; + am_Sink_s temp; + am_CustomConnectionFormat_t tempConnectionFormat; + am_SoundProperty_s tempSoundProperty; + am_MainSoundProperty_s tempMainSoundProperty; + am_NotificationConfiguration_s tempNotificationConfiguration; + am_NotificationConfiguration_s tempMainNotificationConfiguration; + std::string command = "SELECT name, domainID, sinkClassID, volume, visible, availability, availabilityReason, muteState, mainVolume, sinkID FROM " + std::string(SINK_TABLE) + " WHERE reserved=0"; + MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) + + while ((eCode = sqlite3_step(query)) == SQLITE_ROW) + { + temp.name = std::string((const char*) sqlite3_column_text(query, 0)); + temp.domainID = sqlite3_column_int(query, 1); + temp.sinkClassID = sqlite3_column_int(query, 2); + temp.volume = sqlite3_column_int(query, 3); + temp.visible = sqlite3_column_int(query, 4); + temp.available.availability = (am_Availability_e) sqlite3_column_int(query, 5); + temp.available.availabilityReason = (am_CustomAvailabilityReason_t) sqlite3_column_int(query, 6); + temp.muteState = (am_MuteState_e) sqlite3_column_int(query, 7); + temp.mainVolume = sqlite3_column_int(query, 8); + temp.sinkID = sqlite3_column_int(query, 9); + + //read out the connectionFormats + std::string commandConnectionFormat = "SELECT soundFormat FROM SinkConnectionFormat" + i2s(temp.sinkID); + MY_SQLITE_PREPARE_V2(mpDatabase, commandConnectionFormat.c_str(), -1, &qConnectionFormat, NULL) + while ((eCode = sqlite3_step(qConnectionFormat)) == SQLITE_ROW) + { + tempConnectionFormat = (am_CustomConnectionFormat_t) sqlite3_column_int(qConnectionFormat, 0); + temp.listConnectionFormats.push_back(tempConnectionFormat); + } + + MY_SQLITE_FINALIZE(qConnectionFormat) + + //read out sound properties + std::string commandSoundProperty = "SELECT soundPropertyType, value FROM SinkSoundProperty" + i2s(temp.sinkID); + MY_SQLITE_PREPARE_V2(mpDatabase, commandSoundProperty.c_str(), -1, &qSoundProperty, NULL) + while ((eCode = sqlite3_step(qSoundProperty)) == SQLITE_ROW) + { + tempSoundProperty.type = (am_CustomSoundPropertyType_t) sqlite3_column_int(qSoundProperty, 0); + tempSoundProperty.value = sqlite3_column_int(qSoundProperty, 1); + temp.listSoundProperties.push_back(tempSoundProperty); + } + + MY_SQLITE_FINALIZE(qSoundProperty) + + //read out notifications + std::string commandNotificationConfiguration = "SELECT type, status, parameter FROM SinkNotificationConfiguration" + i2s(temp.sinkID); + MY_SQLITE_PREPARE_V2(mpDatabase, commandNotificationConfiguration.c_str(), -1, &qNotificationConfiguration, NULL) + while ((eCode = sqlite3_step(qNotificationConfiguration)) == SQLITE_ROW) + { + tempNotificationConfiguration.type = static_cast<am_CustomNotificationType_t> (sqlite3_column_int(qNotificationConfiguration, 0)); + tempNotificationConfiguration.status = static_cast<am_NotificationStatus_e> (sqlite3_column_int(qNotificationConfiguration, 1)); + tempNotificationConfiguration.parameter = static_cast<int16_t> (sqlite3_column_int(qNotificationConfiguration, 2)); + temp.listNotificationConfigurations.push_back(tempNotificationConfiguration); + } + + MY_SQLITE_FINALIZE(qNotificationConfiguration) + + //read out MainSoundProperties if sink is visible + if(temp.visible) + { + std::string commandMainSoundProperty = "SELECT soundPropertyType, value FROM SinkMainSoundProperty" + i2s(temp.sinkID); + MY_SQLITE_PREPARE_V2(mpDatabase, commandMainSoundProperty.c_str(), -1, &qMAinSoundProperty, NULL) + while ((eCode = sqlite3_step(qMAinSoundProperty)) == SQLITE_ROW) + { + tempMainSoundProperty.type = (am_CustomMainSoundPropertyType_t) sqlite3_column_int(qMAinSoundProperty, 0); + tempMainSoundProperty.value = sqlite3_column_int(qMAinSoundProperty, 1); + temp.listMainSoundProperties.push_back(tempMainSoundProperty); + } + + MY_SQLITE_FINALIZE(qMAinSoundProperty) + + //and mainNotificationConfigurations + std::string commandMainNotificationConfiguration = "SELECT type, status, parameter FROM SinkMainNotificationConfiguration" + i2s(temp.sinkID); + MY_SQLITE_PREPARE_V2(mpDatabase, commandMainNotificationConfiguration.c_str(), -1, &qMainNotificationConfiguration, NULL) + while ((eCode = sqlite3_step(qMainNotificationConfiguration)) == SQLITE_ROW) + { + tempMainNotificationConfiguration.type = static_cast <am_CustomNotificationType_t> (sqlite3_column_int(qMainNotificationConfiguration, 0)); + tempMainNotificationConfiguration.status = static_cast <am_NotificationStatus_e> (sqlite3_column_int(qMainNotificationConfiguration, 1)); + tempMainNotificationConfiguration.parameter = static_cast <uint16_t>(sqlite3_column_int(qMainNotificationConfiguration, 2)); + temp.listMainNotificationConfigurations.push_back(tempMainNotificationConfiguration); + } + + MY_SQLITE_FINALIZE(qMainNotificationConfiguration) + } + + cb(temp); + temp.listConnectionFormats.clear(); + temp.listMainSoundProperties.clear(); + temp.listSoundProperties.clear(); + } + + if (eCode != SQLITE_DONE) + { + logError("DatabaseHandler::getListSinks SQLITE error code:", eCode); + MY_SQLITE_FINALIZE(query) + return (E_DATABASE_ERROR); + } + + MY_SQLITE_FINALIZE(query) + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerSQLite::enumerateGateways(std::function<void(const am_Gateway_s & element)> cb) const +{ + sqlite3_stmt* query = NULL, *qSinkConnectionFormat = NULL, *qSourceConnectionFormat = NULL; + int eCode = 0; + am_Gateway_s temp; + am_CustomConnectionFormat_t tempConnectionFormat; + + std::string command = "SELECT name, sinkID, sourceID, domainSinkID, domainSourceID, controlDomainID, gatewayID FROM " + std::string(GATEWAY_TABLE); + MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) + + while ((eCode = sqlite3_step(query)) == SQLITE_ROW) + { + temp.name = std::string((const char*) sqlite3_column_text(query, 0)); + temp.sinkID = sqlite3_column_int(query, 1); + temp.sourceID = sqlite3_column_int(query, 2); + temp.domainSinkID = sqlite3_column_int(query, 3); + temp.domainSourceID = sqlite3_column_int(query, 4); + temp.controlDomainID = sqlite3_column_int(query, 5); + temp.gatewayID = sqlite3_column_int(query, 6); + + //convertionMatrix: + ListConnectionFormat::const_iterator iter = mListConnectionFormat.begin(); + iter = mListConnectionFormat.find(temp.gatewayID); + if (iter == mListConnectionFormat.end()) + { + logError("DatabaseHandler::getListGateways database error with convertionFormat"); + + return (E_DATABASE_ERROR); + } + temp.convertionMatrix = iter->second; + + //read out the connectionFormats + std::string commandConnectionFormat = "SELECT soundFormat FROM GatewaySourceFormat" + i2s(temp.gatewayID); + MY_SQLITE_PREPARE_V2(mpDatabase, commandConnectionFormat.c_str(), -1, &qSourceConnectionFormat, NULL) + while ((eCode = sqlite3_step(qSourceConnectionFormat)) == SQLITE_ROW) + { + tempConnectionFormat = (am_CustomConnectionFormat_t) sqlite3_column_int(qSourceConnectionFormat, 0); + temp.listSourceFormats.push_back(tempConnectionFormat); + } + + MY_SQLITE_FINALIZE(qSourceConnectionFormat) + + //read out sound properties + commandConnectionFormat = "SELECT soundFormat FROM GatewaySinkFormat" + i2s(temp.gatewayID); + MY_SQLITE_PREPARE_V2(mpDatabase, commandConnectionFormat.c_str(), -1, &qSinkConnectionFormat, NULL) + while ((eCode = sqlite3_step(qSinkConnectionFormat)) == SQLITE_ROW) + { + tempConnectionFormat = (am_CustomConnectionFormat_t) sqlite3_column_int(qSinkConnectionFormat, 0); + temp.listSinkFormats.push_back(tempConnectionFormat); + } + + MY_SQLITE_FINALIZE(qSinkConnectionFormat) + + cb(temp); + temp.listSinkFormats.clear(); + temp.listSourceFormats.clear(); + } + + if (eCode != SQLITE_DONE) + { + logError("DatabaseHandler::getListGateways SQLITE error code:", eCode); + MY_SQLITE_FINALIZE(query) + return (E_DATABASE_ERROR); + } + + MY_SQLITE_FINALIZE(query) + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerSQLite::enumerateConverters(std::function<void(const am_Converter_s & element)> cb) const +{ + sqlite3_stmt* query = NULL, *qSinkConnectionFormat = NULL, *qSourceConnectionFormat = NULL; + int eCode = 0; + am_Converter_s temp; + am_CustomConnectionFormat_t tempConnectionFormat; + + std::string command = "SELECT name, sinkID, sourceID, domainID, converterID FROM " + std::string(CONVERTER_TABLE); + MY_SQLITE_PREPARE_V2(mpDatabase, command.c_str(), -1, &query, NULL) + + while ((eCode = sqlite3_step(query)) == SQLITE_ROW) + { + temp.name = std::string((const char*) sqlite3_column_text(query, 0)); + temp.sinkID = sqlite3_column_int(query, 1); + temp.sourceID = sqlite3_column_int(query, 2); + temp.domainID = sqlite3_column_int(query, 3); + temp.converterID = sqlite3_column_int(query, 4); + + //convertionMatrix: + ListConnectionFormat::const_iterator iter = mListConnectionFormat.begin(); + iter = mListConnectionFormat.find(temp.converterID); + if (iter == mListConnectionFormat.end()) + { + logError("DatabaseHandler::getListConverters database error with convertionFormat"); + + return (E_DATABASE_ERROR); + } + temp.convertionMatrix = iter->second; + + //read out the connectionFormats + std::string commandConnectionFormat = "SELECT soundFormat FROM ConverterSourceFormat" + i2s(temp.converterID); + MY_SQLITE_PREPARE_V2(mpDatabase, commandConnectionFormat.c_str(), -1, &qSourceConnectionFormat, NULL) + while ((eCode = sqlite3_step(qSourceConnectionFormat)) == SQLITE_ROW) + { + tempConnectionFormat = (am_CustomConnectionFormat_t) sqlite3_column_int(qSourceConnectionFormat, 0); + temp.listSourceFormats.push_back(tempConnectionFormat); + } + + MY_SQLITE_FINALIZE(qSourceConnectionFormat) + + //read out sound properties + commandConnectionFormat = "SELECT soundFormat FROM ConverterSinkFormat" + i2s(temp.converterID); + MY_SQLITE_PREPARE_V2(mpDatabase, commandConnectionFormat.c_str(), -1, &qSinkConnectionFormat, NULL) + while ((eCode = sqlite3_step(qSinkConnectionFormat)) == SQLITE_ROW) + { + tempConnectionFormat = (am_CustomConnectionFormat_t) sqlite3_column_int(qSinkConnectionFormat, 0); + temp.listSinkFormats.push_back(tempConnectionFormat); + } + + MY_SQLITE_FINALIZE(qSinkConnectionFormat) + + cb(temp); + temp.listSinkFormats.clear(); + temp.listSourceFormats.clear(); + } + + if (eCode != SQLITE_DONE) + { + logError("DatabaseHandler::getListConverters SQLITE error code:", eCode); + MY_SQLITE_FINALIZE(query) + return (E_DATABASE_ERROR); + } + + MY_SQLITE_FINALIZE(query) + + return (E_OK); +} + } diff --git a/AudioManagerDaemon/src/CAmDatabaseObserver.cpp b/AudioManagerDaemon/src/CAmDatabaseObserver.cpp index 506ec01..57a76cc 100644 --- a/AudioManagerDaemon/src/CAmDatabaseObserver.cpp +++ b/AudioManagerDaemon/src/CAmDatabaseObserver.cpp @@ -111,6 +111,12 @@ void CAmDatabaseObserver::newGateway(const am_Gateway_s& gateway) //todo: implement something } +void CAmDatabaseObserver::newConverter(const am_Converter_s& coverter) +{ + (void) coverter; + //todo: implement something +} + void CAmDatabaseObserver::newCrossfader(const am_Crossfader_s& crossfader) { mRoutingSender->addCrossfaderLookup(crossfader); @@ -143,6 +149,12 @@ void CAmDatabaseObserver::removeGateway(const am_gatewayID_t gatewayID) //todo: implement something? } +void CAmDatabaseObserver::removeConverter(const am_converterID_t converterID) +{ + (void) converterID; + //todo: implement something? +} + void CAmDatabaseObserver::removeCrossfader(const am_crossfaderID_t crossfaderID) { mRoutingSender->removeCrossfaderLookup(crossfaderID); diff --git a/AudioManagerDaemon/src/CAmRouter.cpp b/AudioManagerDaemon/src/CAmRouter.cpp index d574e45..6ab0a07 100644 --- a/AudioManagerDaemon/src/CAmRouter.cpp +++ b/AudioManagerDaemon/src/CAmRouter.cpp @@ -13,30 +13,83 @@ * * * \author Christian Mueller, christian.ei.mueller@bmw.de BMW 2011,2012 + * \author Aleksandar Donchev, Aleksander.Donchev@partner.bmw.de BMW 2013,2014 * * \file CAmRouter.cpp * For further information see http://www.genivi.org/. * */ -#include "CAmRouter.h" #include <cassert> #include <algorithm> #include <vector> #include <iterator> +#include "CAmRouter.h" #include "IAmDatabaseHandler.h" #include "CAmControlSender.h" +#include "shared/CAmDltWrapper.h" + + namespace am { + +void getSourceSinkPossibleConnectionFormats(std::vector<CAmNode<am_RoutingNodeData_s>*>::iterator iteratorSource, + std::vector<CAmNode<am_RoutingNodeData_s>*>::iterator iteratorSink, + std::vector<am_CustomConnectionFormat_t> & outConnectionFormats) +{ + CAmNode<am_RoutingNodeData_s> * nodeSink = *iteratorSink; + assert(nodeSink->getData().type==am_RoutingNodeData_s::am_NodeDataType_e::SINK); + + CAmNode<am_RoutingNodeData_s> * nodeSource = *iteratorSource; + assert(nodeSource->getData().type==am_RoutingNodeData_s::am_NodeDataType_e::SOURCE); + + am_Source_s *source = nodeSource->getData().data.source; + am_Sink_s *sink = nodeSink->getData().data.sink; + CAmRouter::listPossibleConnectionFormats(source->listConnectionFormats, sink->listConnectionFormats, outConnectionFormats); +} + +template <class X> void getMergeConnectionFormats(const X * element, + const am_CustomConnectionFormat_t connectionFormat, + const std::vector<am_CustomConnectionFormat_t> & listConnectionFormats, + std::vector<am_CustomConnectionFormat_t> & outListMergeConnectionFormats) +{ + std::vector<am_CustomConnectionFormat_t> listRestrictedConnectionFormats; + CAmRouter::getRestrictedOutputFormats(element->convertionMatrix, + element->listSourceFormats, + element->listSinkFormats, + connectionFormat, + listRestrictedConnectionFormats); + std::sort(listRestrictedConnectionFormats.begin(), listRestrictedConnectionFormats.end()); //todo: this might be not needed if we use strictly sorted input + std::insert_iterator<std::vector<am_CustomConnectionFormat_t> > inserter(outListMergeConnectionFormats, outListMergeConnectionFormats.begin()); + set_intersection(listConnectionFormats.begin(), listConnectionFormats.end(), listRestrictedConnectionFormats.begin(), listRestrictedConnectionFormats.end(), inserter); +} + + CAmRouter::CAmRouter(IAmDatabaseHandler* iDatabaseHandler, CAmControlSender* iSender) : mpDatabaseHandler(iDatabaseHandler), // - mpControlSender(iSender) + mpControlSender(iSender), + mOnlyFreeConversionNodes(false), + mRoutingGraph(), + mNodeListSources(), + mNodeListSinks(), + mNodeListGateways(), + mNodeListConverters(), + mNodeListSourceStatus(), + mNodeListSinkStatus(), + mNodeListConverterStatus(), + mNodeListGatewayStatus(), + mpRootSource(0), + mpRootSink(0) { assert(mpDatabaseHandler); assert(mpControlSender); } +CAmRouter::~CAmRouter() +{ +} + /** * returns the best route between a source and a sink * @param onlyfree if true only free gateways are used @@ -48,213 +101,67 @@ CAmRouter::CAmRouter(IAmDatabaseHandler* iDatabaseHandler, CAmControlSender* iSe am_Error_e CAmRouter::getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s> & returnList) { returnList.clear(); - //first find out in which domains the source and sink are - am_domainID_t sourceDomainID; - am_domainID_t sinkDomainID; - if (mpDatabaseHandler->getDomainOfSource(sourceID, sourceDomainID) != E_OK) - return (E_NON_EXISTENT); - if (mpDatabaseHandler->getDomainOfSink(sinkID, sinkDomainID) != E_OK) - return (E_NON_EXISTENT); - - if (sourceDomainID == sinkDomainID) //shortcut if the domains are the same... - { - //first get the list of possible connection formats - std::vector<am_CustomConnectionFormat_t> listFormats, listPriorityConnectionFormats; - listPossibleConnectionFormats(sourceID, sinkID, listFormats); - - //dummy route - am_Route_s route; - route.sinkID = sinkID; - route.sourceID = sourceID; - route.route.clear(); - - //get the prio of the Controller: - mpControlSender->getConnectionFormatChoice(sourceID, sinkID, route, listFormats, listPriorityConnectionFormats); - - //no possible connection, so no route ! But we report OK since there is no fault ... - if (listPriorityConnectionFormats.empty()) - return (E_OK); - - //return the first item as route: - am_RoutingElement_s routingElement; - routingElement.sourceID = sourceID; - routingElement.sinkID = sinkID; - routingElement.connectionFormat = listPriorityConnectionFormats[0]; - routingElement.domainID = sourceDomainID; - - //Now get a route: - am_Route_s actualRoute; - actualRoute.route.push_back(routingElement); - actualRoute.sourceID = sourceID; - actualRoute.sinkID = sinkID; - - //push it to the return list - we are done here ... - returnList.push_back(actualRoute); - return (E_OK); - - } - CAmRoutingTree routingtree(sourceDomainID); //Build up a Tree from the Source_Domain to every other domain. - std::vector<CAmRoutingTreeItem*> flattree; //This list is the flat tree - std::vector<CAmRoutingTreeItem*> matchtree; - std::vector<am_gatewayID_t> listGatewayID; //holds all gateway ids of the route - am_RoutingElement_s routingElement; - am_Route_s actualRoute; //holds the actual Route - am_sourceID_t lastSource = 0; - - mpDatabaseHandler->getRoutingTree(onlyfree, routingtree, flattree); //Build up the tree out of the database as - - //we go through the returned flattree and look for our sink, after that flattree holds only treeItems that match - std::vector<CAmRoutingTreeItem*>::iterator iterator = flattree.begin(); - for (; iterator != flattree.end(); ++iterator) - { - if ((*iterator)->returnDomainID() == sinkDomainID) - { - matchtree.push_back(*iterator); - } - } - - //No we need to trace back the routes for each entry in matchtree - iterator = matchtree.begin(); - for (; iterator != matchtree.end(); ++iterator) - { - std::vector<am_RoutingElement_s> actualRoutingElement; //intermediate list of current routing pairs - //getting the route for the actual item - routingtree.getRoute(*iterator, listGatewayID); //This gives only the Gateway IDs we need more - - //go throught the gatewayids and get more information - std::vector<am_gatewayID_t>::iterator gatewayIterator = listGatewayID.begin(); - for (; gatewayIterator != listGatewayID.end(); ++gatewayIterator) - { - am_Gateway_s gatewayData; - if (mpDatabaseHandler->getGatewayInfoDB(*gatewayIterator, gatewayData) != E_OK) - return (E_UNKNOWN); - - //at the beginning of the route, we connect first the source to the first gateway - if (gatewayIterator == listGatewayID.begin()) - { - routingElement.sourceID = sourceID; - routingElement.domainID = sourceDomainID; - } - else - { - routingElement.sourceID = lastSource; - routingElement.domainID = gatewayData.domainSinkID; - } - routingElement.sinkID = gatewayData.sinkID; - actualRoutingElement.push_back(routingElement); - lastSource = gatewayData.sourceID; - } - //at the end of the route, connect to the sink ! - routingElement.sourceID = lastSource; - routingElement.sinkID = sinkID; - routingElement.domainID = sinkDomainID; - actualRoutingElement.push_back(routingElement); - - //So now we got the route, what is missing are the connectionFormats... - - //Step through the routes and try to use always the best connectionFormat - std::vector<am_RoutingElement_s>::iterator routingInterator = actualRoutingElement.begin(); - gatewayIterator = listGatewayID.begin(); - if (findBestWay(sinkID, sourceID, actualRoutingElement, routingInterator, gatewayIterator) != E_OK) - { - continue; - } - - //add the route to the list of routes... - actualRoute.sourceID = sourceID; - actualRoute.sinkID = sinkID; - actualRoute.route = actualRoutingElement; - returnList.push_back(actualRoute); - } - return (E_OK); + am_Source_s source; + am_Sink_s sink; + mpDatabaseHandler->getSourceInfoDB(sourceID, source); + mpDatabaseHandler->getSinkInfoDB(sinkID, sink); + return getRoute(onlyfree, source, sink, returnList); } -void CAmRouter::listPossibleConnectionFormats(const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_CustomConnectionFormat_t>& listFormats) const +bool CAmRouter::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) { - std::vector<am_CustomConnectionFormat_t> listSourceFormats; - std::vector<am_CustomConnectionFormat_t> listSinkFormats; - mpDatabaseHandler->getListSinkConnectionFormats(sinkID, listSinkFormats); - mpDatabaseHandler->getListSourceConnectionFormats(sourceID, listSourceFormats); - std::sort(listSinkFormats.begin(), listSinkFormats.end()); //todo: this might be not needed if we use strictly sorted input - std::sort(listSourceFormats.begin(), listSourceFormats.end()); //todo: this might be not needed if we use strictly sorted input - std::insert_iterator<std::vector<am_CustomConnectionFormat_t> > inserter(listFormats, listFormats.begin()); - set_intersection(listSourceFormats.begin(), listSourceFormats.end(), listSinkFormats.begin(), listSinkFormats.end(), inserter); + const size_t sizeSourceFormats = listSourceFormats.size(); + const size_t sizeSinkFormats = listSinkFormats.size(); + const size_t sizeConvertionMatrix = convertionMatrix.size(); + + if(sizeSourceFormats==0||sizeSinkFormats==0||sizeConvertionMatrix==0||sizeConvertionMatrix!=sizeSinkFormats*sizeSourceFormats) + { + return false; + } + + std::vector<bool>::const_iterator iterator = convertionMatrix.begin(); + for (; iterator != convertionMatrix.end(); ++iterator) + { + if( true == *iterator ) + { + const size_t index = iterator-convertionMatrix.begin(); + size_t idx = index%sizeSourceFormats; + sourceFormats.push_back(listSourceFormats.at(idx)); + idx = index/sizeSourceFormats; + sinkFormats.push_back(listSinkFormats.at(idx)); + } + } + return sourceFormats.size()>0; } -am_Error_e CAmRouter::findBestWay(am_sinkID_t sinkID, am_sourceID_t sourceID, std::vector<am_RoutingElement_s> & listRoute, std::vector<am_RoutingElement_s>::iterator routeIterator, std::vector<am_gatewayID_t>::iterator gatewayIterator) +void CAmRouter::listPossibleConnectionFormats(std::vector<am_CustomConnectionFormat_t> & inListSourceFormats, + std::vector<am_CustomConnectionFormat_t> & inListSinkFormats, + std::vector<am_CustomConnectionFormat_t> & outListFormats) { - am_Error_e returnError = E_NOT_POSSIBLE; - std::vector<am_CustomConnectionFormat_t> listConnectionFormats; - std::vector<am_CustomConnectionFormat_t> listMergeConnectionFormats; - std::vector<am_CustomConnectionFormat_t> listPriorityConnectionFormats; - std::vector<am_RoutingElement_s>::iterator nextIterator = routeIterator + 1; - //get best connection format - listPossibleConnectionFormats(routeIterator->sourceID, routeIterator->sinkID, listConnectionFormats); - - //if we have not just started, we need to take care about the gateways... - if (routeIterator != listRoute.begin()) - { - //since we have to deal with Gateways, there are restrictions what connectionFormat we can take. So we need to take the subset of connections that are restricted: - std::vector<am_CustomConnectionFormat_t> listRestrictedConnectionFormats; - std::insert_iterator<std::vector<am_CustomConnectionFormat_t> > inserter(listMergeConnectionFormats, listMergeConnectionFormats.begin()); - std::vector<am_RoutingElement_s>::iterator tempIterator(routeIterator); - tempIterator--; - listRestrictedOutputFormatsGateways(*gatewayIterator, (tempIterator)->connectionFormat, listRestrictedConnectionFormats); - std::sort(listRestrictedConnectionFormats.begin(), listRestrictedConnectionFormats.end()); //todo: this might be not needed if we use strictly sorted input - set_intersection(listConnectionFormats.begin(), listConnectionFormats.end(), listRestrictedConnectionFormats.begin(), listRestrictedConnectionFormats.end(), inserter); - gatewayIterator++; - } - else - { - listMergeConnectionFormats = listConnectionFormats; - } - - am_Route_s route; - route.sinkID = sinkID; - route.sourceID = sourceID; - route.route = listRoute; - - //let the controller decide: - mpControlSender->getConnectionFormatChoice(routeIterator->sourceID, routeIterator->sinkID, route, listMergeConnectionFormats, listPriorityConnectionFormats); - - //we have the list sorted after prios - now we try one after the other with the next part of the route - std::vector<am_CustomConnectionFormat_t>::iterator connectionFormatIterator = listPriorityConnectionFormats.begin(); - - //here we need to check if we are at the end and stop - if (nextIterator == listRoute.end()) - { - if (!listPriorityConnectionFormats.empty()) - { - routeIterator->connectionFormat = listPriorityConnectionFormats.front(); - return (E_OK); - } - else - return (E_NOT_POSSIBLE); - } - - for (; connectionFormatIterator != listPriorityConnectionFormats.end(); ++connectionFormatIterator) - { - routeIterator->connectionFormat = *connectionFormatIterator; - if ((returnError = findBestWay(sinkID, sourceID, listRoute, nextIterator, gatewayIterator)) == E_OK) - { - break; - } - } - - return (returnError); + std::sort(inListSourceFormats.begin(), inListSourceFormats.end()); + std::sort(inListSinkFormats.begin(), inListSinkFormats.end()); + std::insert_iterator<std::vector<am_CustomConnectionFormat_t> > inserter(outListFormats, outListFormats.begin()); + set_intersection(inListSourceFormats.begin(), inListSourceFormats.end(), inListSinkFormats.begin(), inListSinkFormats.end(), inserter); } -void CAmRouter::listRestrictedOutputFormatsGateways(const am_gatewayID_t gatewayID, const am_CustomConnectionFormat_t sinkConnectionFormat, std::vector<am_CustomConnectionFormat_t> & listFormats) const + +bool CAmRouter::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) { listFormats.clear(); - am_Gateway_s gatewayData; - mpDatabaseHandler->getGatewayInfoDB(gatewayID, gatewayData); - std::vector<am_CustomConnectionFormat_t>::const_iterator rowSinkIterator = gatewayData.listSinkFormats.begin(); - std::vector<bool>::const_iterator matrixIterator = gatewayData.convertionMatrix.begin(); + std::vector<am_CustomConnectionFormat_t>::const_iterator rowSinkIterator = listSinkFormats.begin(); + std::vector<bool>::const_iterator matrixIterator = convertionMatrix.begin(); //find the row number of the sink - rowSinkIterator = find(gatewayData.listSinkFormats.begin(), gatewayData.listSinkFormats.end(), sinkConnectionFormat); - int rowNumberSink = rowSinkIterator - gatewayData.listSinkFormats.begin(); + rowSinkIterator = find(listSinkFormats.begin(), listSinkFormats.end(), connectionFormat); + int rowNumberSink = rowSinkIterator - listSinkFormats.begin(); //go through the convertionMatrix and find out if the conversion is possible, if yes, add connectionFormat ... std::advance(matrixIterator, rowNumberSink); @@ -264,96 +171,817 @@ void CAmRouter::listRestrictedOutputFormatsGateways(const am_gatewayID_t gateway { if (*matrixIterator) { - listFormats.push_back(gatewayData.listSourceFormats.at((matrixIterator - gatewayData.convertionMatrix.begin()) / gatewayData.listSinkFormats.size())); + listFormats.push_back(listSourceFormats.at((matrixIterator - convertionMatrix.begin()) / listSinkFormats.size())); } - std::advance(matrixIterator, gatewayData.listSinkFormats.size()); - } while (gatewayData.convertionMatrix.end() - matrixIterator > 0); + std::advance(matrixIterator, listSinkFormats.size()); + } while (convertionMatrix.end() - matrixIterator > 0); + + return listFormats.size(); } -CAmRouter::~CAmRouter() +#ifdef EXTENDED_ROUTING_GRAPH +void appendNodes(CAmGraph<am_RoutingNodeData_s, uint16_t> & routingGraph, + const std::vector<am_CustomConnectionFormat_t> & listConnectionFormats, + am_RoutingNodeData_s & nodeData, + std::vector<CAmNode<am_RoutingNodeData_s>*> & nodeList) { + std::for_each(listConnectionFormats.begin(), listConnectionFormats.end(), [&](const am_CustomConnectionFormat_t cf){ + nodeData.inConnectionFormat = cf; + nodeList.push_back(&routingGraph.addNode(nodeData)); + }); } -CAmRoutingTreeItem::CAmRoutingTreeItem(const am_domainID_t domainID, const am_gatewayID_t gatewayID, CAmRoutingTreeItem *parent) : - mDomainID(domainID), // - mGatewayID(gatewayID), // - mpParentItem(parent) +void appendNodes(CAmGraph<am_RoutingNodeData_s, uint16_t> & routingGraph, + const std::vector<am_CustomConnectionFormat_t> & sourceConnectionFormats, + const std::vector<am_CustomConnectionFormat_t> & sinkConnectionFormats, + const std::vector<bool> & convertionMatrix, + am_RoutingNodeData_s & nodeData, + std::vector<CAmNode<am_RoutingNodeData_s>*> & nodeList) { - assert(mDomainID!=0); + + std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats; + if(CAmRouter::getAllowedFormatsFromConvMatrix(convertionMatrix, sourceConnectionFormats, sinkConnectionFormats, sourceFormats, sinkFormats)) + { + for(size_t i = 0; i < sourceFormats.size(); i++) + { + nodeData.inConnectionFormat = sinkFormats[i]; + nodeData.outConnectionFormat = sourceFormats[i]; + nodeList.push_back(&routingGraph.addNode(nodeData)); + } + } } +#endif -void CAmRoutingTreeItem::appendChild(CAmRoutingTreeItem *newChild) +am_Error_e CAmRouter::getRoute(const bool onlyfree, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes) { - assert(newChild); - mListChildItems.push_back(newChild); + clear(); + mOnlyFreeConversionNodes = onlyfree; + + // We need to copy the sinks, sources, converters, gateways, because we don't know what store is being used (SQLite or Map). + //todo: Don't make copy for map storage. + std::deque<am_Source_s> listSources; + std::deque<am_Sink_s> listSinks; + std::deque<am_Gateway_s> listGateways; + std::deque<am_Converter_s> listConverters; + + am_Error_e error = E_OK; + + am_RoutingNodeData_s nodeDataSrc; + nodeDataSrc.type = NodeDataType::SOURCE; + mpDatabaseHandler->enumerateSources([&](const am_Source_s & obj){ + listSources.push_back(obj); + nodeDataSrc.data.source = &listSources.back(); + mNodeListSourceStatus[obj.sourceID]=false; +#ifdef EXTENDED_ROUTING_GRAPH + appendNodes(mRoutingGraph, obj.listConnectionFormats, nodeDataSrc, mNodeListSources); +#else + mNodeListSources.push_back(&mRoutingGraph.addNode(nodeDataSrc)); +#endif + }); + am_RoutingNodeData_s nodeDataSink; + nodeDataSink.type = NodeDataType::SINK; + mpDatabaseHandler->enumerateSinks([&](const am_Sink_s & obj){ + listSinks.push_back(obj); + nodeDataSink.data.sink = &listSinks.back(); + mNodeListSinkStatus[obj.sinkID]=false; +#ifdef EXTENDED_ROUTING_GRAPH + appendNodes(mRoutingGraph, obj.listConnectionFormats, nodeDataSink, mNodeListSinks); +#else + mNodeListSinks.push_back(&mRoutingGraph.addNode(nodeDataSink)); +#endif + }); + am_RoutingNodeData_s nodeDataGateway; + nodeDataGateway.type = NodeDataType::GATEWAY; + mpDatabaseHandler->enumerateGateways([&](const am_Gateway_s & obj){ + listGateways.push_back(obj); + nodeDataGateway.data.gateway = &listGateways.back(); + mNodeListGatewayStatus[obj.gatewayID]=false; +#ifdef EXTENDED_ROUTING_GRAPH + appendNodes(mRoutingGraph, obj.listSourceFormats, obj.listSinkFormats, obj.convertionMatrix, nodeDataGateway, mNodeListGateways); +#else + mNodeListGateways.push_back(&mRoutingGraph.addNode(nodeDataGateway)); +#endif + }); + am_RoutingNodeData_s nodeDataConverter; + nodeDataConverter.type = NodeDataType::CONVERTER; + mpDatabaseHandler->enumerateConverters([&](const am_Converter_s & obj){ + listConverters.push_back(obj); + nodeDataConverter.data.converter = &listConverters.back(); + mNodeListConverterStatus[obj.converterID]=false; +#ifdef EXTENDED_ROUTING_GRAPH + appendNodes(mRoutingGraph, obj.listSourceFormats, obj.listSinkFormats, obj.convertionMatrix, nodeDataConverter, mNodeListConverters); +#else + mNodeListConverters.push_back(&mRoutingGraph.addNode(nodeDataConverter)); +#endif + }); + + buildGraph(aSource, aSink); + +#ifdef EXTENDED_ROUTING_GRAPH + std::vector<std::vector<CAmNode<am_RoutingNodeData_s>*>> pathNodes; + getShortestPath(listRoutes, pathNodes); +#else + std::vector<std::vector<CAmNode<am_RoutingNodeData_s>*>> pathNodes; + error = getAllPaths(listRoutes, pathNodes); +#endif + return error; } -void CAmRoutingTreeItem::returnChildItems(std::vector<CAmRoutingTreeItem*> listChildItems) +void CAmRouter::buildGraph( const am_Source_s & aSource, const am_Sink_s & aSink) { - listChildItems = mListChildItems; + //build up a topological sorted graph +#ifdef EXTENDED_ROUTING_GRAPH + mpRootSource = (am_Source_s*)&aSource; + mpRootSink = (am_Sink_s*)&aSink; + for(auto it1=aSource.listConnectionFormats.begin(); it1!=aSource.listConnectionFormats.end(); it1++) + { + am::CAmNode<am::am_RoutingNodeData_s>* pRootNodeSource = sourceNodeWithID(aSource.sourceID, *it1); + for(auto it2=aSink.listConnectionFormats.begin(); it2!=aSink.listConnectionFormats.end(); it2++) + { + am::CAmNode<am::am_RoutingNodeData_s>* pRootNodeSink = sinkNodeWithID(aSink.sinkID, *it2); + if(pRootNodeSource && pRootNodeSink) + { + if(aSource.domainID==aSink.domainID) + routeInSameDomain(*pRootNodeSource, *pRootNodeSink); + else + routeInAnotherDomain(*pRootNodeSource, *pRootNodeSink); + } + } + } +#else + mpRootSource = sourceNodeWithID(aSource.sourceID); + mpRootSink = sinkNodeWithID(aSink.sinkID); + + assert(mpRootSource); + assert(mpRootSink); + + if(aSource.domainID==aSink.domainID) + { + routeInSameDomain(*mpRootSource, *mpRootSink); + } + else + { + routeInAnotherDomain(*mpRootSource, *mpRootSink); + } +#endif +#ifdef TRACE_GRAPH + mRoutingGraph.trace([&](const CAmNode<am_RoutingNodeData_s> & node, const std::vector<CAmVertex<am_RoutingNodeData_s,uint16_t>*> & list) { + std::cout << "Node " << node.getIndex() << " :"; + ((CAmNode<am_RoutingNodeData_s> &)node).getData().trace(); + std::cout << "-->"; + std::for_each(list.begin(), list.end(), [&](const CAmVertex<am_RoutingNodeData_s,uint16_t>* refVertex){ + am::CAmNode<am::am_RoutingNodeData_s>* data = refVertex->getNode(); + std::cout << "Node " << data->getIndex() << " :"; + data->getData().trace(); + }); + std::cout << std::endl; + }); +#endif } +#ifdef EXTENDED_ROUTING_GRAPH -am_domainID_t CAmRoutingTreeItem::returnDomainID() const +CAmNode<am_RoutingNodeData_s>* CAmRouter::sinkNodeWithID(const am_sinkID_t sinkID, const am_CustomConnectionFormat_t connectionFormat) { - return (mDomainID); + auto iter = std::find_if(mNodeListSinks.begin(), mNodeListSinks.end(), [sinkID, connectionFormat](CAmNode<am_RoutingNodeData_s>* node){ + return node->getData().data.sink->sinkID==sinkID && node->getData().inConnectionFormat==connectionFormat; + }); + if(iter!=mNodeListSinks.end()) + return *iter; + return NULL; } -am_gatewayID_t CAmRoutingTreeItem::returnGatewayID() const +CAmNode<am_RoutingNodeData_s>* CAmRouter::sourceNodeWithID(const am_sourceID_t sourceID, const am_CustomConnectionFormat_t connectionFormat) +{ + auto iter = std::find_if(mNodeListSources.begin(), mNodeListSources.end(), [sourceID, connectionFormat](CAmNode<am_RoutingNodeData_s>* node){ + return node->getData().data.source->sourceID==sourceID && node->getData().inConnectionFormat==connectionFormat; + }); + if(iter!=mNodeListSources.end()) + return *iter; + return NULL; +} +#else +CAmNode<am_RoutingNodeData_s>* CAmRouter::sinkNodeWithID(const am_sinkID_t sinkID) { - return (mGatewayID); + auto iter = std::find_if(mNodeListSinks.begin(), mNodeListSinks.end(), [sinkID](CAmNode<am_RoutingNodeData_s>* node){ + return node->getData().data.sink->sinkID==sinkID; + }); + if(iter!=mNodeListSinks.end()) + return *iter; + return NULL; } -CAmRoutingTreeItem* CAmRoutingTreeItem::returnParent() const +CAmNode<am_RoutingNodeData_s>* CAmRouter::sourceNodeWithID(const am_sourceID_t sourceID) { - return (mpParentItem); + auto iter = std::find_if(mNodeListSources.begin(), mNodeListSources.end(), [sourceID](CAmNode<am_RoutingNodeData_s>* node){ + return node->getData().data.source->sourceID==sourceID; + }); + if(iter!=mNodeListSources.end()) + return *iter; + return NULL; } +#endif -CAmRoutingTreeItem::~CAmRoutingTreeItem() +void CAmRouter::connectNodes(const CAmNode<am_RoutingNodeData_s> & node1, + const CAmNode<am_RoutingNodeData_s> & node2, + const am_CustomConnectionFormat_t vertexData, + const int16_t weight) { + if( !mRoutingGraph.isAnyVertex(node1, node2) ) + mRoutingGraph.connectNodes(node1, node2, vertexData, weight); } -CAmRoutingTree::CAmRoutingTree(const am_domainID_t rootDomainID) : - mRootItem(CAmRoutingTreeItem(rootDomainID)) +bool CAmRouter::routeInSameDomain(CAmNode<am_RoutingNodeData_s> & aSource, CAmNode<am_RoutingNodeData_s> & aSink) { - assert(rootDomainID!=0); + am_RoutingNodeData_s & sourceData = aSource.getData(); + am_RoutingNodeData_s & sinkData = aSink.getData(); + am_Source_s * source = sourceData.data.source; + //If exists connection return + if( mRoutingGraph.isAnyVertex(aSource, aSink)) + return true; + if( mNodeListSourceStatus[source->sourceID] ) + return false; + bool result = false; + mNodeListSourceStatus[source->sourceID]=true; +#ifdef EXTENDED_ROUTING_GRAPH + if(sourceData.inConnectionFormat!=sinkData.inConnectionFormat) // it is not possible to connect them directly + { +#else + am_Sink_s * sink = sinkData.data.sink; + std::vector<am_CustomConnectionFormat_t> listFormats; + CAmRouter::listPossibleConnectionFormats(source->listConnectionFormats, sink->listConnectionFormats, listFormats); + if(listFormats.size()==0) // it is not possible to connect them directly + { +#endif + bool availableConverter = false; + for(auto iter = mNodeListConverters.begin(); iter!=mNodeListConverters.end(); iter++) + { + CAmNode<am_RoutingNodeData_s>* converterNode = *iter; + am_RoutingNodeData_s & converterNodeData = converterNode->getData(); + am_Converter_s * converter = converterNodeData.data.converter; + //Get only converters with end point in current source domain + if( !mNodeListConverterStatus[converter->converterID] && converter->domainID==source->domainID && (!mOnlyFreeConversionNodes || !isComponentConnected(*converter))) + { + //Get the sink connected to the converter... + mNodeListConverterStatus[converter->converterID]=true; +#ifdef EXTENDED_ROUTING_GRAPH + CAmNode<am_RoutingNodeData_s> *converterSinkNode = this->sinkNodeWithID(converter->sinkID, converterNodeData.inConnectionFormat); +#else + CAmNode<am_RoutingNodeData_s> *converterSinkNode = this->sinkNodeWithID(converter->sinkID); +#endif + if(converterSinkNode) + { + am_RoutingNodeData_s & converterSinkData = converterSinkNode->getData(); + //Check whether the hidden sink formats match the source formats... +#ifdef EXTENDED_ROUTING_GRAPH + if(sourceData.inConnectionFormat==converterSinkData.inConnectionFormat) + { + CAmNode<am_RoutingNodeData_s> *converterSourceNode = this->sourceNodeWithID(converter->sourceID, converterNodeData.outConnectionFormat); + if(converterSourceNode) + { + am_RoutingNodeData_s & converterSourceData = converterSourceNode->getData(); + if(converterSourceData.inConnectionFormat==converterSinkData.outConnectionFormat) + { + availableConverter=true; + // Connection source->conv_sink->converter->conv_source + this->connectNodes(aSource, *converterSinkNode, converterNodeData.inConnectionFormat, 1); + this->connectNodes(*converterSinkNode, *converterNode, converterNodeData.inConnectionFormat, 1); + this->connectNodes(*converterNode, *converterSourceNode, converterNodeData.outConnectionFormat, 1); + result|=this->routeInSameDomain(*converterSourceNode, aSink); + } + } + } + else + { + //the converter is not suitable, lets try to find paths through another domains + bool alternResult = this->routeInAnotherDomain(aSource, *converterSinkNode); + if(alternResult) + { + CAmNode<am_RoutingNodeData_s> *converterSourceNode = this->sourceNodeWithID(converter->sourceID, converterNodeData.outConnectionFormat); + if(converterSourceNode) + { + am_RoutingNodeData_s & converterSourceData = converterSourceNode->getData(); + if(converterSourceData.inConnectionFormat==converterSinkData.outConnectionFormat) + { + // Connection source->conv_sink->converter->conv_source + this->connectNodes(*converterSinkNode, *converterNode, converterNodeData.inConnectionFormat, 1); + this->connectNodes(*converterNode, *converterSourceNode, converterNodeData.outConnectionFormat, 1); + result|=this->routeInSameDomain(*converterSourceNode, aSink); + } + } + } + } +#else + am_Sink_s * nextSink = converterSinkData.data.sink; + std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats, intersection; + //Check whether the hidden sink formats match the source formats... + CAmRouter::listPossibleConnectionFormats(source->listConnectionFormats, nextSink->listConnectionFormats, intersection); + if(intersection.size()>0)//OK match source -> conv_sink + { + //Are there convertible formats or not + if(CAmRouter::getAllowedFormatsFromConvMatrix(converter->convertionMatrix, converter->listSourceFormats, converter->listSinkFormats, sourceFormats, sinkFormats)) + { + availableConverter=true; + CAmNode<am_RoutingNodeData_s> *nextSourceNode = this->sourceNodeWithID(converter->sourceID); + assert(nextSourceNode); + //Connections source->hidden_sink->converter->hidden_source + this->connectNodes(aSource, *converterSinkNode, CF_UNKNOWN, 1); + this->connectNodes(*converterSinkNode, *converterNode, CF_UNKNOWN, 1); + this->connectNodes(*converterNode, *nextSourceNode, CF_UNKNOWN, 1); + //Go ahead with hidden_source and sink + result|=this->routeInSameDomain(*nextSourceNode, aSink); + } + } + else + { + //the converter is not suitable, lets try to find paths through another domains + bool alternResult = this->routeInAnotherDomain(aSource, *converterSinkNode); + if(alternResult) + { + if(CAmRouter::getAllowedFormatsFromConvMatrix(converter->convertionMatrix, converter->listSourceFormats, converter->listSinkFormats, sourceFormats, sinkFormats)) + { + CAmNode<am_RoutingNodeData_s> *nextSourceNode = this->sourceNodeWithID(converter->sourceID); + assert(nextSourceNode); + //Connections source->hidden_sink->converter->hidden_source + this->connectNodes(*converterSinkNode, *converterNode, CF_UNKNOWN, 1); + this->connectNodes(*converterNode, *nextSourceNode, CF_UNKNOWN, 1); + //Go ahead with hidden_source and sink + result|=this->routeInSameDomain(*nextSourceNode, aSink); + } + } + } +#endif + } + mNodeListConverterStatus[converter->converterID]=false; + } + } + if(!availableConverter) + { + mNodeListSourceStatus[source->sourceID]=false; + result|=this->routeInAnotherDomain(aSource, aSink); + } + } + else + { + //success only if the source can be connected with the sink +#ifdef EXTENDED_ROUTING_GRAPH + this->connectNodes(aSource, aSink, sourceData.inConnectionFormat, 1); +#else + this->connectNodes(aSource, aSink, CF_UNKNOWN, 1); +#endif + result=true; + } + mNodeListSourceStatus[source->sourceID]=false; + return result; } -CAmRoutingTreeItem *CAmRoutingTree::insertItem(const am_domainID_t domainID, const am_gatewayID_t gatewayID, CAmRoutingTreeItem *parent) +bool CAmRouter::routeInAnotherDomain(CAmNode<am_RoutingNodeData_s> & aSource, CAmNode<am_RoutingNodeData_s> & aSink) { - CAmRoutingTreeItem *newTree = new CAmRoutingTreeItem(domainID, gatewayID, parent); - parent->appendChild(newTree); - mListChild.push_back(newTree); - return (newTree); + am_RoutingNodeData_s & sourceData = aSource.getData(); + am_RoutingNodeData_s & sinkData = aSink.getData(); + am_Source_s * source = sourceData.data.source; + am_Sink_s * sink = sinkData.data.sink; + + if(mRoutingGraph.isAnyVertex(aSource, aSink)) + return true; + if( mNodeListSourceStatus[source->sourceID] ) + return false; + mNodeListSourceStatus[source->sourceID]=true; +#ifndef EXTENDED_ROUTING_GRAPH + std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats, intersection; +#endif + bool result = false; + for(auto iter = mNodeListGateways.begin(); iter!=mNodeListGateways.end(); iter++) + { + CAmNode<am_RoutingNodeData_s>* gatewayNode = *iter; + am_RoutingNodeData_s & gatewayNodeData = gatewayNode->getData(); + am_Gateway_s * gateway = gatewayNodeData.data.gateway; + //Get only gateways with end point in current source domain + if( + !mNodeListGatewayStatus[gateway->gatewayID] && + gateway->domainSinkID==source->domainID && + (!mOnlyFreeConversionNodes || !isComponentConnected(*gateway)) ) + { + //Get the sink connected to the gateway... + mNodeListGatewayStatus[gateway->gatewayID]=true; +#ifdef EXTENDED_ROUTING_GRAPH + CAmNode<am_RoutingNodeData_s> *gatewaySinkNode = this->sinkNodeWithID(gateway->sinkID, gatewayNodeData.inConnectionFormat); +#else + CAmNode<am_RoutingNodeData_s> *gatewaySinkNode = this->sinkNodeWithID(gateway->sinkID); +#endif + + if(gatewaySinkNode) + { + am_RoutingNodeData_s & gatewaySinkData = gatewaySinkNode->getData(); + //Check whether the hidden sink formats match the source formats... + +#ifdef EXTENDED_ROUTING_GRAPH + if(sourceData.inConnectionFormat==gatewaySinkData.inConnectionFormat) + { + //Check if the gateway is able to convert any formats... + CAmNode<am_RoutingNodeData_s> *gatewaySourceNode = this->sourceNodeWithID(gateway->sourceID, gatewayNodeData.outConnectionFormat); + if(gatewaySourceNode) + { + am_RoutingNodeData_s & gatewaySourceData = gatewaySourceNode->getData(); + if(gatewaySourceData.inConnectionFormat==gatewayNodeData.outConnectionFormat) + { + am_Source_s * gatewaySource = gatewaySourceData.data.source; + //Connections source->hidden_sink->gateway->hidden_source + this->connectNodes(aSource, *gatewaySinkNode, gatewayNodeData.inConnectionFormat, 1); + this->connectNodes(*gatewaySinkNode, *gatewayNode, gatewayNodeData.inConnectionFormat, 1); + this->connectNodes(*gatewayNode, *gatewaySourceNode, gatewayNodeData.outConnectionFormat, 1); + //Go ahead with hidden_source and sink + if(gatewaySource->domainID==sink->domainID) + result|=this->routeInSameDomain(*gatewaySourceNode, aSink); + else + result|=this->routeInAnotherDomain(*gatewaySourceNode, aSink); + } + } + } + else + { + //the gateway is not suitable, lets try to find paths within this domains + bool alternResult = this->routeInSameDomain(aSource, *gatewaySinkNode); + if(alternResult) + { + CAmNode<am_RoutingNodeData_s> *gatewaySourceNode = this->sourceNodeWithID(gateway->sourceID, gatewayNodeData.outConnectionFormat); + if(gatewaySourceNode) + { + am_RoutingNodeData_s & gatewaySourceData = gatewaySourceNode->getData(); + if(gatewaySourceData.inConnectionFormat==gatewayNodeData.outConnectionFormat) + { + am_Source_s * gatewaySource = gatewaySourceData.data.source; + //Connections source->hidden_sink->gateway->hidden_source + this->connectNodes(aSource, *gatewaySinkNode, gatewayNodeData.inConnectionFormat, 1); + this->connectNodes(*gatewaySinkNode, *gatewayNode, gatewayNodeData.inConnectionFormat, 1); + this->connectNodes(*gatewayNode, *gatewaySourceNode, gatewayNodeData.outConnectionFormat, 1); + //Go ahead with hidden_source and sink + if(gatewaySource->domainID==sink->domainID) + result|=this->routeInSameDomain(*gatewaySourceNode, aSink); + else + result|=this->routeInAnotherDomain(*gatewaySourceNode, aSink); + } + } + } + } +#else + am_Sink_s * nextSink = gatewaySinkData.data.sink; + std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats, intersection; + CAmRouter::listPossibleConnectionFormats(source->listConnectionFormats, nextSink->listConnectionFormats, intersection); + if(intersection.size()>0)//OK match source -> conv_sink + { + //Check if the gateway is able to convert any formats... + if(CAmRouter::getAllowedFormatsFromConvMatrix(gateway->convertionMatrix, gateway->listSourceFormats, gateway->listSinkFormats, sourceFormats, sinkFormats)) + { + CAmNode<am_RoutingNodeData_s> *nextSourceNode = this->sourceNodeWithID(gateway->sourceID); + assert(nextSourceNode); + am_Source_s * nextSource = nextSourceNode->getData().data.source; + //Connections source->hidden_sink->gateway->hidden_source + this->connectNodes(aSource, *gatewaySinkNode, CF_UNKNOWN, 1); + this->connectNodes(*gatewaySinkNode, *gatewayNode, CF_UNKNOWN, 1); + this->connectNodes(*gatewayNode, *nextSourceNode, CF_UNKNOWN, 1); + //Go ahead with hidden_source and sink + if(nextSource->domainID==sink->domainID) + result|=this->routeInSameDomain(*nextSourceNode, aSink); + else + result|=this->routeInAnotherDomain(*nextSourceNode, aSink); + } + } + else + { + //the gateway is not suitable, lets try to find paths within this domains + mNodeListSourceStatus[source->sourceID]=false; + bool alternResult = this->routeInSameDomain(aSource, *gatewaySinkNode); + if(alternResult) + { + if(CAmRouter::getAllowedFormatsFromConvMatrix(gateway->convertionMatrix, gateway->listSourceFormats, gateway->listSinkFormats, sourceFormats, sinkFormats)) + { + CAmNode<am_RoutingNodeData_s> *nextSourceNode = this->sourceNodeWithID(gateway->sourceID); + assert(nextSourceNode); + am_Source_s * nextSource = nextSourceNode->getData().data.source; + //Connections source->hidden_sink->gateway->hidden_source + this->connectNodes(*gatewaySinkNode, *gatewayNode, CF_UNKNOWN, 1); + this->connectNodes(*gatewayNode, *nextSourceNode, CF_UNKNOWN, 1); + //Go ahead with hidden_source and sink + if(nextSource->domainID==sink->domainID) + result|=this->routeInSameDomain(*nextSourceNode, aSink); + else + result|=this->routeInAnotherDomain(*nextSourceNode, aSink); + } + } + } +#endif + } + mNodeListGatewayStatus[gateway->gatewayID]=false; + } + } + mNodeListSourceStatus[source->sourceID]=false; + return result; } -void CAmRoutingTree::getRoute(CAmRoutingTreeItem *targetItem, std::vector<am_gatewayID_t>& listGateways) +#ifdef EXTENDED_ROUTING_GRAPH +void CAmRouter::getShortestPath(const am_Source_s & aSource, + const am_Sink_s & aSink, + std::vector<am_Route_s> & resultPath, + std::vector<std::vector<CAmNode<am_RoutingNodeData_s>*>> & resultNodesPath) { - listGateways.clear(); - CAmRoutingTreeItem *parentItem = targetItem; - while (parentItem != &mRootItem) - { - listGateways.push_back(parentItem->returnGatewayID()); - parentItem = parentItem->returnParent(); - } - std::reverse(listGateways.begin(), listGateways.end()); + std::vector<CAmNode<am_RoutingNodeData_s>*> listTargets; + std::vector<CAmNode<am_RoutingNodeData_s>*> * pathNodes; + am_Route_s *path; + am_RoutingElement_s * element; + std::function<void(const am_GraphPathPosition_e, CAmNode<am_RoutingNodeData_s> &)> cb = [&](const am_GraphPathPosition_e pos, CAmNode<am_RoutingNodeData_s> & object) + { + if(pos==GRAPH_PATH_START) + { + resultNodesPath.emplace_back(); + pathNodes=&resultNodesPath.back(); + resultPath.emplace_back(); + path= &resultPath.back(); + path->sinkID = aSink.sinkID; + path->sourceID = aSource.sourceID; + } + pathNodes->insert(pathNodes->begin(), (CAmNode<am_RoutingNodeData_s>*)&object); + + am_RoutingNodeData_s & routingData = object.getData(); + + if(routingData.type==am_RoutingNodeData_s::am_NodeDataType_e::SINK) + { + auto iter = path->route.emplace(path->route.begin()); + element = &(*iter); + + element->domainID = routingData.data.sink->domainID; + element->sinkID = routingData.data.sink->sinkID; + element->connectionFormat = routingData.inConnectionFormat; + + } + else if(routingData.type==am_RoutingNodeData_s::am_NodeDataType_e::SOURCE) + { + element->domainID = routingData.data.source->domainID; + element->sourceID = routingData.data.source->sourceID; + element->connectionFormat = routingData.inConnectionFormat; + } + }; + + + for(auto it2=aSink.listConnectionFormats.begin(); it2!=aSink.listConnectionFormats.end(); it2++) + { + am::CAmNode<am::am_RoutingNodeData_s>* pRootNodeSink = sinkNodeWithID(aSink.sinkID, *it2); + if(pRootNodeSink) + listTargets.push_back(pRootNodeSink); + } + if(listTargets.size()) + { + for(auto it1=aSource.listConnectionFormats.begin(); it1!=aSource.listConnectionFormats.end(); it1++) + { + am::CAmNode<am::am_RoutingNodeData_s>* pRootNodeSource = sourceNodeWithID(aSource.sourceID, *it1); + if(pRootNodeSource) + { + mRoutingGraph.getShortestPath(*pRootNodeSource, listTargets, cb); + } + } + } +} + +void CAmRouter::getShortestPath(std::vector<am_Route_s> & routes, std::vector<std::vector<CAmNode<am_RoutingNodeData_s>*>> & nodes) +{ + getShortestPath(*mpRootSource, *mpRootSink, routes, nodes); } -am_domainID_t CAmRoutingTree::returnRootDomainID() const +void CAmRouter::getShortestPath(const am_Source_s & aSource, const am_Sink_s & aSink, + std::vector<std::vector<CAmNode<am_RoutingNodeData_s>*>> & resultPath) { - return (mRootItem.returnDomainID()); + std::vector<CAmNode<am_RoutingNodeData_s>*> listTargets; + for(auto it2=aSink.listConnectionFormats.begin(); it2!=aSink.listConnectionFormats.end(); it2++) + { + am::CAmNode<am::am_RoutingNodeData_s>* pRootNodeSink = sinkNodeWithID(aSink.sinkID, *it2); + if(pRootNodeSink) + listTargets.push_back(pRootNodeSink); + } + if(listTargets.size()) + { + for(auto it1=aSource.listConnectionFormats.begin(); it1!=aSource.listConnectionFormats.end(); it1++) + { + am::CAmNode<am::am_RoutingNodeData_s>* pRootNodeSource = sourceNodeWithID(aSource.sourceID, *it1); + if(pRootNodeSource) + { + mRoutingGraph.getShortestPath(*pRootNodeSource, listTargets, resultPath); + } + } + } } +#else -CAmRoutingTreeItem *CAmRoutingTree::returnRootItem() +am_Error_e CAmRouter::determineConnectionFormatsForPath(am_Route_s & routeObjects, std::vector<CAmNode<am_RoutingNodeData_s>*> & nodes) { - return (&mRootItem); + std::vector<am_RoutingElement_s>::iterator routingElementIterator = routeObjects.route.begin(); + std::vector<CAmNode<am_RoutingNodeData_s>*>::iterator nodeIterator = nodes.begin(); + if( routingElementIterator!= routeObjects.route.end() && nodeIterator!=nodes.end() ) + return doConnectionFormatsForPath(routeObjects, nodes, routingElementIterator, nodeIterator); + return E_OK; } -CAmRoutingTree::~CAmRoutingTree() +am_Error_e CAmRouter::doConnectionFormatsForPath(am_Route_s & routeObjects, + std::vector<CAmNode<am_RoutingNodeData_s>*> & nodes, + std::vector<am_RoutingElement_s>::iterator routingElementIterator, + std::vector<CAmNode<am_RoutingNodeData_s>*>::iterator nodeIterator) { - std::vector<CAmRoutingTreeItem*>::iterator it = mListChild.begin(); - for (; it != mListChild.end(); ++it) + am_Error_e returnError = E_NOT_POSSIBLE; + std::vector<am_CustomConnectionFormat_t> listConnectionFormats; + std::vector<am_CustomConnectionFormat_t> listMergeConnectionFormats; + + std::vector<CAmNode<am_RoutingNodeData_s>*>::iterator currentNodeIterator = nodeIterator; + std::vector<am_RoutingElement_s>::iterator currentRoutingElementIterator = routingElementIterator; + + if (currentRoutingElementIterator!=routeObjects.route.begin()) { - delete *it; + std::vector<am_CustomConnectionFormat_t> listConnectionFormats; + std::vector<am_RoutingElement_s>::iterator tempIterator = (currentRoutingElementIterator-1); + CAmNode<am_RoutingNodeData_s> * currentNode = *currentNodeIterator; + getSourceSinkPossibleConnectionFormats(currentNodeIterator+1, currentNodeIterator+2, listConnectionFormats); + + if(currentNode->getData().type==am_RoutingNodeData_s::am_NodeDataType_e::GATEWAY) + { + am_Gateway_s *gateway = currentNode->getData().data.gateway; + getMergeConnectionFormats(gateway, tempIterator->connectionFormat, listConnectionFormats, listMergeConnectionFormats); + } + else if(currentNode->getData().type==am_RoutingNodeData_s::am_NodeDataType_e::CONVERTER) + { + am_Converter_s *converter = currentNode->getData().data.converter; + getMergeConnectionFormats(converter, tempIterator->connectionFormat, listConnectionFormats, listMergeConnectionFormats); + } + currentNodeIterator+=3; } + else + { + CAmNode<am_RoutingNodeData_s> * currentNode = *currentNodeIterator; + assert(currentNode->getData().type==am_RoutingNodeData_s::am_NodeDataType_e::SOURCE); + + currentNodeIterator++; + assert(currentNodeIterator!=nodes.end()); + + CAmNode<am_RoutingNodeData_s> * nodeSink = *currentNodeIterator; + assert(nodeSink->getData().type==am_RoutingNodeData_s::am_NodeDataType_e::SINK); + + am_Source_s *source = currentNode->getData().data.source; + am_Sink_s *sink = nodeSink->getData().data.sink; + CAmRouter::listPossibleConnectionFormats(source->listConnectionFormats, sink->listConnectionFormats, listMergeConnectionFormats); + currentNodeIterator+=1; //now we are on the next converter/gateway + } + + //let the controller decide: + std::vector<am_CustomConnectionFormat_t> listPriorityConnectionFormats; + mpControlSender->getConnectionFormatChoice(currentRoutingElementIterator->sourceID, currentRoutingElementIterator->sinkID, routeObjects, + listMergeConnectionFormats, listPriorityConnectionFormats); + + //we have the list sorted after priors - now we try one after the other with the next part of the route + std::vector<am_CustomConnectionFormat_t>::iterator connectionFormatIterator = listPriorityConnectionFormats.begin(); + //here we need to check if we are at the end and stop + std::vector<am_RoutingElement_s>::iterator nextIterator = currentRoutingElementIterator + 1;//next pair source and sink + if (nextIterator == routeObjects.route.end()) + { + if (!listPriorityConnectionFormats.empty()) + { + currentRoutingElementIterator->connectionFormat = listPriorityConnectionFormats.front(); + return (E_OK); + } + else + return (E_NOT_POSSIBLE); + } + + for (; connectionFormatIterator != listPriorityConnectionFormats.end(); ++connectionFormatIterator) + { + currentRoutingElementIterator->connectionFormat = *connectionFormatIterator; + if ((returnError = doConnectionFormatsForPath(routeObjects, nodes, nextIterator, currentNodeIterator)) == E_OK) + { + break; + } + } + return (returnError); +} + +void CAmRouter::getShortestPath(const CAmNode<am_RoutingNodeData_s> & source, + const CAmNode<am_RoutingNodeData_s> & destination, + std::vector<CAmNode<am_RoutingNodeData_s>*> & resultPath) +{ + mRoutingGraph.getShortestPath(source, destination, resultPath); +} + +void CAmRouter::getShortestPath(std::vector<CAmNode<am_RoutingNodeData_s>*> & resultPath) +{ + getShortestPath(*mpRootSource, *mpRootSink, resultPath); } + +void CAmRouter::getShortestPath(CAmNode<am_RoutingNodeData_s> & aSource, CAmNode<am_RoutingNodeData_s> & aSink, + am_Route_s & resultPath, std::vector<CAmNode<am_RoutingNodeData_s>*> & resultNodesPath) +{ + am_RoutingElement_s * element; + am_RoutingNodeData_s & sinkNodeData = aSink.getData(); + am_RoutingNodeData_s & sourceNodeData = aSource.getData(); + resultPath.sinkID = sinkNodeData.data.sink->sinkID; + resultPath.sourceID = sourceNodeData.data.source->sourceID; + + std::function<void(const am_GraphPathPosition_e, CAmNode<am_RoutingNodeData_s> &)> cb = [&](const am_GraphPathPosition_e, CAmNode<am_RoutingNodeData_s> & object) + { + resultNodesPath.insert(resultNodesPath.begin(), (CAmNode<am_RoutingNodeData_s>*)&object); + am_RoutingNodeData_s & routingData = object.getData(); + if(routingData.type==am_RoutingNodeData_s::am_NodeDataType_e::SINK) + { + auto iter = resultPath.route.emplace(resultPath.route.begin()); + element = &(*iter); + element->domainID = routingData.data.sink->domainID; + element->sinkID = routingData.data.sink->sinkID; + element->connectionFormat = CF_UNKNOWN; + } + else if(routingData.type==am_RoutingNodeData_s::am_NodeDataType_e::SOURCE) + { + element->domainID = routingData.data.source->domainID; + element->sourceID = routingData.data.source->sourceID; + element->connectionFormat = CF_UNKNOWN; + } + }; + mRoutingGraph.getShortestPath(aSource, aSink, cb); +} + +void CAmRouter::getShortestPath(am_Route_s & resultPath, std::vector<CAmNode<am_RoutingNodeData_s>*> & resultNodesPath) +{ + getShortestPath(*mpRootSource, *mpRootSink, resultPath, resultNodesPath); +} + +am_Error_e CAmRouter::getAllPaths(CAmNode<am_RoutingNodeData_s> & aSource, CAmNode<am_RoutingNodeData_s> & aSink, + std::vector<am_Route_s> & resultPath, std::vector<std::vector<CAmNode<am_RoutingNodeData_s>*>> & resultNodesPath) +{ + uint8_t errorsCount = 0, successCount = 0; + mRoutingGraph.getAllPaths(aSource, aSink, [&](const std::vector<CAmNode<am_RoutingNodeData_s>*> & path) { + resultNodesPath.push_back(path); + resultPath.emplace_back(); + am_Route_s & nextRoute = resultPath.back(); + nextRoute.sinkID = aSink.getData().data.sink->sinkID; + nextRoute.sourceID = aSource.getData().data.source->sourceID; + am_RoutingElement_s * element; + for(auto it = path.begin(); it!=path.end(); it++) + { + am_RoutingNodeData_s & routingData = (*it)->getData(); + if(routingData.type==am_RoutingNodeData_s::am_NodeDataType_e::SOURCE) + { + auto iter = nextRoute.route.emplace(nextRoute.route.end()); + element = &(*iter); + element->domainID = routingData.data.source->domainID; + element->sourceID = routingData.data.source->sourceID; + element->connectionFormat = CF_UNKNOWN; + } + else if(routingData.type==am_RoutingNodeData_s::am_NodeDataType_e::SINK) + { + element->domainID = routingData.data.sink->domainID; + element->sinkID = routingData.data.sink->sinkID; + element->connectionFormat = CF_UNKNOWN; + } + } + am_Error_e err = determineConnectionFormatsForPath(nextRoute, (std::vector<CAmNode<am_RoutingNodeData_s>*> &)path); + if(err!=E_OK) + { + errorsCount++; + auto last = resultPath.end()-1; + resultPath.erase(last); +#ifdef TRACE_GRAPH + std::cout<<"Error by determining connection formats for path from source:"<<nextRoute.sourceID<<" to sink:"<<nextRoute.sinkID<<"\n"; +#endif + } + else + { +#ifdef TRACE_GRAPH + std::cout<<"Successfully determined connection formats for path from source:"<<nextRoute.sourceID<<" to sink:"<<nextRoute.sinkID<<"\n"; +#endif + successCount++; + } + }); + if(successCount) + return E_OK; + if(errorsCount) + return E_NOT_POSSIBLE; + return E_OK; +} + +am_Error_e CAmRouter::getAllPaths(std::vector<am_Route_s> & resultPath, std::vector<std::vector<CAmNode<am_RoutingNodeData_s>*>> & resultNodesPath) +{ + return getAllPaths(*mpRootSource, *mpRootSink, resultPath, resultNodesPath); +} + +#endif + +void CAmRouter::clear() +{ + mNodeListSourceStatus.clear(); + mNodeListSinkStatus.clear(); + mNodeListConverterStatus.clear(); + mNodeListGatewayStatus.clear(); + + mRoutingGraph.clear(); + mNodeListSources.clear(); + mNodeListSinks.clear(); + mNodeListGateways.clear(); + mNodeListConverters.clear(); + mpRootSource=NULL; + mpRootSink=NULL; +} + + } diff --git a/AudioManagerDaemon/src/CAmRoutingReceiver.cpp b/AudioManagerDaemon/src/CAmRoutingReceiver.cpp index eaa38e1..67bc911 100644 --- a/AudioManagerDaemon/src/CAmRoutingReceiver.cpp +++ b/AudioManagerDaemon/src/CAmRoutingReceiver.cpp @@ -238,11 +238,21 @@ am_Error_e CAmRoutingReceiver::registerGateway(const am_Gateway_s & gatewayData, return (mpControlSender->hookSystemRegisterGateway(gatewayData, gatewayID)); } +am_Error_e CAmRoutingReceiver::registerConverter(const am_Converter_s& converterData, am_converterID_t& converterID) +{ + return (mpControlSender->hookSystemRegisterConverter(converterData, converterID)); +} + am_Error_e CAmRoutingReceiver::deregisterGateway(const am_gatewayID_t gatewayID) { return (mpControlSender->hookSystemDeregisterGateway(gatewayID)); } +am_Error_e CAmRoutingReceiver::deregisterConverter(const am_converterID_t converterID) +{ + return (mpControlSender->hookSystemDeregisterConverter(converterID)); +} + am_Error_e CAmRoutingReceiver::peekSink(const std::string& name, am_sinkID_t & sinkID) { return (mpDatabaseHandler->peekSink(name, sinkID)); @@ -418,6 +428,11 @@ am_Error_e CAmRoutingReceiver::updateGateway(const am_gatewayID_t gatewayID, con return (mpControlSender->hookSystemUpdateGateway(gatewayID,listSourceFormats,listSinkFormats,convertionMatrix)); } +am_Error_e CAmRoutingReceiver::updateConverter(const am_converterID_t converterID, const std::vector<am_CustomConnectionFormat_t>& listSourceFormats, const std::vector<am_CustomConnectionFormat_t>& listSinkFormats, const std::vector<bool>& convertionMatrix) +{ + return (mpControlSender->hookSystemUpdateConverter(converterID,listSourceFormats,listSinkFormats,convertionMatrix)); +} + am_Error_e CAmRoutingReceiver::updateSink(const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector<am_SoundProperty_s>& listSoundProperties, const std::vector<am_CustomConnectionFormat_t>& listConnectionFormats, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties) { return (mpControlSender->hookSystemUpdateSink(sinkID,sinkClassID,listSoundProperties,listConnectionFormats,listMainSoundProperties)); diff --git a/AudioManagerDaemon/src/CAmRoutingSender.cpp b/AudioManagerDaemon/src/CAmRoutingSender.cpp index 1606761..cd9c3d7 100644 --- a/AudioManagerDaemon/src/CAmRoutingSender.cpp +++ b/AudioManagerDaemon/src/CAmRoutingSender.cpp @@ -525,7 +525,11 @@ am_Error_e CAmRoutingSender::removeCrossfaderLookup(const am_crossfaderID_t cros am_Error_e CAmRoutingSender::removeHandle(const am_Handle_s& handle) { if (mlistActiveHandles.erase(handle)) + { + logInfo(__PRETTY_FUNCTION__,handle.handle,handle.handleType); return (E_OK); + } + logError(__PRETTY_FUNCTION__,"Could not remove handle",handle.handle); return (E_UNKNOWN); } @@ -556,6 +560,7 @@ am_Handle_s CAmRoutingSender::createHandle(const am_handleData_c& handleData, co mlistActiveHandles.insert(std::make_pair(handle, handleData)); if ((mlistActiveHandles.size()%100) == 0) logInfo("CAmRoutingSender::createHandle warning: too many open handles, number of handles: ", mlistActiveHandles.size()); + logInfo(__PRETTY_FUNCTION__,handle.handle, handle.handleType); return (handle); } @@ -570,9 +575,18 @@ CAmRoutingSender::am_handleData_c CAmRoutingSender::returnHandleData(const am_Ha HandlesMap::const_iterator it = mlistActiveHandles.begin(); it = mlistActiveHandles.find(handle); if (it!=mlistActiveHandles.end()) - return (it->second); + { + const am_handleData_c & result = it->second; + logInfo(__PRETTY_FUNCTION__, handle.handle, handle.handleType, + "connectionID", result.connectionID, + "sinkID", result.sinkID, + "sourceID",result.sourceID, + "sourceState", result.sourceState); + return result; + } am_handleData_c handleData; handleData.sinkID=0; + logError(__PRETTY_FUNCTION__,"could not find handle data for handle",handle.handle,handle.handleType); return (handleData); } |