diff options
Diffstat (limited to 'AudioManagerCore/src')
-rw-r--r-- | AudioManagerCore/src/CAmCommandReceiver.cpp | 264 | ||||
-rw-r--r-- | AudioManagerCore/src/CAmCommandSender.cpp | 367 | ||||
-rw-r--r-- | AudioManagerCore/src/CAmControlReceiver.cpp | 606 | ||||
-rw-r--r-- | AudioManagerCore/src/CAmControlSender.cpp | 571 | ||||
-rw-r--r-- | AudioManagerCore/src/CAmDatabaseHandlerMap.cpp | 3079 | ||||
-rw-r--r-- | AudioManagerCore/src/CAmDatabaseObserver.cpp | 242 | ||||
-rw-r--r-- | AudioManagerCore/src/CAmLog.cpp | 101 | ||||
-rw-r--r-- | AudioManagerCore/src/CAmRouter.cpp | 884 | ||||
-rw-r--r-- | AudioManagerCore/src/CAmRoutingReceiver.cpp | 620 | ||||
-rw-r--r-- | AudioManagerCore/src/CAmRoutingSender.cpp | 838 | ||||
-rw-r--r-- | AudioManagerCore/src/CAmTelnetMenuHelper.cpp | 1438 | ||||
-rwxr-xr-x | AudioManagerCore/src/CAmTelnetServer.cpp | 257 |
12 files changed, 9267 insertions, 0 deletions
diff --git a/AudioManagerCore/src/CAmCommandReceiver.cpp b/AudioManagerCore/src/CAmCommandReceiver.cpp new file mode 100644 index 0000000..d903384 --- /dev/null +++ b/AudioManagerCore/src/CAmCommandReceiver.cpp @@ -0,0 +1,264 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2012, BMW AG + * + * This file is part of GENIVI Project AudioManager. + * + * Contributions are licensed to the GENIVI Alliance under one or more + * Contribution License Agreements. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012 + * + * \file CAmCommandReceiver.cpp + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmCommandReceiver.h" +#include <cassert> +#include <algorithm> +#include "IAmDatabaseHandler.h" +#include "CAmControlSender.h" +#include "CAmDltWrapper.h" +#include "CAmSocketHandler.h" + +namespace am +{ + +CAmCommandReceiver::CAmCommandReceiver(IAmDatabaseHandler *iDatabaseHandler, CAmControlSender *iControlSender, CAmSocketHandler *iSocketHandler) : + mDatabaseHandler(iDatabaseHandler), // + mControlSender(iControlSender), // + mDBusWrapper(NULL), // + mSocketHandler(iSocketHandler), // + handleCount(0),// + mListStartupHandles(), // + mListRundownHandles(), // + mWaitStartup(false), // + mWaitRundown(false), + mLastErrorStartup(E_OK), // + mLastErrorRundown(E_OK) // + +{ + assert(mDatabaseHandler!=NULL); + assert(mSocketHandler!=NULL); + assert(mControlSender!=NULL); +} + +CAmCommandReceiver::CAmCommandReceiver(IAmDatabaseHandler *iDatabaseHandler, CAmControlSender *iControlSender, CAmSocketHandler *iSocketHandler, CAmDbusWrapper *iDBusWrapper) : + mDatabaseHandler(iDatabaseHandler), // + mControlSender(iControlSender), // + mDBusWrapper(iDBusWrapper), // + mSocketHandler(iSocketHandler), // + handleCount(0),// + mListStartupHandles(), // + mListRundownHandles(), // + mWaitStartup(false), // + mWaitRundown(false), // + mLastErrorStartup(E_UNKNOWN), // + mLastErrorRundown(E_UNKNOWN) +{ + assert(mDatabaseHandler!=NULL); + assert(mSocketHandler!=NULL); + assert(mControlSender!=NULL); + assert(mDBusWrapper!=NULL); +} + +CAmCommandReceiver::~CAmCommandReceiver() +{ +} + +am_Error_e CAmCommandReceiver::connect(const am_sourceID_t sourceID, const am_sinkID_t sinkID, am_mainConnectionID_t & mainConnectionID) +{ + logInfo("CommandReceiver::connect got called, sourceID=", sourceID, "sinkID=", sinkID); + return (mControlSender->hookUserConnectionRequest(sourceID, sinkID, mainConnectionID)); +} + +am_Error_e CAmCommandReceiver::disconnect(const am_mainConnectionID_t mainConnectionID) +{ + logInfo("CommandReceiver::disconnect got called, mainConnectionID=", mainConnectionID); + return (mControlSender->hookUserDisconnectionRequest(mainConnectionID)); +} + +am_Error_e CAmCommandReceiver::setVolume(const am_sinkID_t sinkID, const am_mainVolume_t volume) +{ + logInfo("CommandReceiver::setVolume got called, sinkID=", sinkID, "volume=", volume); + return (mControlSender->hookUserVolumeChange(sinkID, volume)); +} + +am_Error_e CAmCommandReceiver::volumeStep(const am_sinkID_t sinkID, const int16_t volumeStep) +{ + logInfo("CommandReceiver::volumeStep got called, sinkID=", sinkID, "volumeStep=", volumeStep); + return (mControlSender->hookUserVolumeStep(sinkID, volumeStep)); +} + +am_Error_e CAmCommandReceiver::setSinkMuteState(const am_sinkID_t sinkID, const am_MuteState_e muteState) +{ + logInfo("CommandReceiver::setSinkMuteState got called, sinkID=", sinkID, "muteState=", muteState); + return (mControlSender->hookUserSetSinkMuteState(sinkID, muteState)); +} + +am_Error_e CAmCommandReceiver::setMainSinkSoundProperty(const am_MainSoundProperty_s & soundProperty, const am_sinkID_t sinkID) +{ + logInfo("CommandReceiver::setMainSinkSoundProperty got called, sinkID=", sinkID, "soundPropertyType=", soundProperty.type, "soundPropertyValue=", soundProperty.value); + return (mControlSender->hookUserSetMainSinkSoundProperty(sinkID, soundProperty)); +} + +am_Error_e CAmCommandReceiver::setMainSourceSoundProperty(const am_MainSoundProperty_s & soundProperty, const am_sourceID_t sourceID) +{ + logInfo("CommandReceiver::setMainSourceSoundProperty got called, sourceID=", sourceID, "soundPropertyType=", soundProperty.type, "soundPropertyValue=", soundProperty.value); + return (mControlSender->hookUserSetMainSourceSoundProperty(sourceID, soundProperty)); +} + +am_Error_e CAmCommandReceiver::setSystemProperty(const am_SystemProperty_s & property) +{ + logInfo("CommandReceiver::setSystemProperty got called", "type=", property.type, "soundPropertyValue=", property.value); + return (mControlSender->hookUserSetSystemProperty(property)); +} + +am_Error_e CAmCommandReceiver::getVolume(const am_sinkID_t sinkID, am_mainVolume_t& mainVolume) const +{ + return (mDatabaseHandler->getSinkMainVolume(sinkID, mainVolume)); +} + +am_Error_e CAmCommandReceiver::getListMainConnections(std::vector<am_MainConnectionType_s> & listConnections) const +{ + return (mDatabaseHandler->getListVisibleMainConnections(listConnections)); + +} + +am_Error_e CAmCommandReceiver::getListMainSinks(std::vector<am_SinkType_s>& listMainSinks) const +{ + return (mDatabaseHandler->getListMainSinks(listMainSinks)); +} + +am_Error_e CAmCommandReceiver::getListMainSources(std::vector<am_SourceType_s>& listMainSources) const +{ + return (mDatabaseHandler->getListMainSources(listMainSources)); +} + +am_Error_e CAmCommandReceiver::getListMainSinkSoundProperties(const am_sinkID_t sinkID, std::vector<am_MainSoundProperty_s> & listSoundProperties) const +{ + return (mDatabaseHandler->getListMainSinkSoundProperties(sinkID, listSoundProperties)); +} + +am_Error_e CAmCommandReceiver::getListMainSourceSoundProperties(const am_sourceID_t sourceID, std::vector<am_MainSoundProperty_s> & listSourceProperties) const +{ + return (mDatabaseHandler->getListMainSourceSoundProperties(sourceID, listSourceProperties)); +} + +am_Error_e CAmCommandReceiver::getListSourceClasses(std::vector<am_SourceClass_s> & listSourceClasses) const +{ + return (mDatabaseHandler->getListSourceClasses(listSourceClasses)); +} + +am_Error_e CAmCommandReceiver::getListSinkClasses(std::vector<am_SinkClass_s> & listSinkClasses) const +{ + return (mDatabaseHandler->getListSinkClasses(listSinkClasses)); +} + +am_Error_e CAmCommandReceiver::getListSystemProperties(std::vector<am_SystemProperty_s> & listSystemProperties) const +{ + return (mDatabaseHandler->getListSystemProperties(listSystemProperties)); +} + +am_Error_e CAmCommandReceiver::getTimingInformation(const am_mainConnectionID_t mainConnectionID, am_timeSync_t & delay) const +{ + return (mDatabaseHandler->getTimingInformation(mainConnectionID, delay)); +} + +am_Error_e CAmCommandReceiver::getDBusConnectionWrapper(CAmDbusWrapper*& dbusConnectionWrapper) const +{ +#ifdef WITH_DBUS_WRAPPER + dbusConnectionWrapper = mDBusWrapper; + return (E_OK); +#else + dbusConnectionWrapper = NULL; + return (E_UNKNOWN); +#endif /*WITH_DBUS_WRAPPER*/ +} + +am_Error_e CAmCommandReceiver::getSocketHandler(CAmSocketHandler *& socketHandler) const +{ + socketHandler = mSocketHandler; + return (E_OK); +} + +void CAmCommandReceiver::getInterfaceVersion(std::string & version) const +{ + version = CommandVersion; +} + +void CAmCommandReceiver::confirmCommandReady(const uint16_t handle, const am_Error_e error) +{ + if (error !=E_OK) + mLastErrorStartup=error; + mListStartupHandles.erase(std::remove(mListStartupHandles.begin(), mListStartupHandles.end(), handle), mListStartupHandles.end()); + if (mWaitStartup && mListStartupHandles.empty()) + mControlSender->confirmCommandReady(mLastErrorStartup); +} + +void CAmCommandReceiver::confirmCommandRundown(const uint16_t handle, const am_Error_e error) +{ + if (error !=E_OK) + mLastErrorRundown=error; + mListRundownHandles.erase(std::remove(mListRundownHandles.begin(), mListRundownHandles.end(), handle), mListRundownHandles.end()); + if (mWaitRundown && mListRundownHandles.empty()) + mControlSender->confirmCommandRundown(mLastErrorRundown); +} + +uint16_t CAmCommandReceiver::getStartupHandle() +{ + uint16_t handle = ++handleCount; //todo: handle overflow + mListStartupHandles.push_back(handle); + return (handle); +} + +uint16_t CAmCommandReceiver::getRundownHandle() +{ + uint16_t handle = ++handleCount; //todo: handle overflow + mListRundownHandles.push_back(handle); + return (handle); +} + +void CAmCommandReceiver::waitOnStartup(bool startup) +{ + mWaitStartup = startup; + mLastErrorStartup=E_OK; +} + +am_Error_e CAmCommandReceiver::getListMainSinkNotificationConfigurations(const am_sinkID_t sinkID, std::vector<am_NotificationConfiguration_s>& listMainNotificationConfigurations) const +{ + return (mDatabaseHandler->getListMainSinkNotificationConfigurations(sinkID,listMainNotificationConfigurations)); +} + +am_Error_e CAmCommandReceiver::getListMainSourceNotificationConfigurations(const am_sourceID_t sourceID, std::vector<am_NotificationConfiguration_s>& listMainNotificationConfigurations) const +{ + return (mDatabaseHandler->getListMainSourceNotificationConfigurations(sourceID,listMainNotificationConfigurations)); +} + +am_Error_e CAmCommandReceiver::setMainSinkNotificationConfiguration(const am_sinkID_t sinkID, const am_NotificationConfiguration_s& mainNotificationConfiguration) +{ + logInfo("CommandReceiver::setMainSinkNotificationConfiguration got called, sinkID=", sinkID, " type=",mainNotificationConfiguration.type, " parameter=", mainNotificationConfiguration.parameter, "status=",mainNotificationConfiguration.status); + return (mControlSender->hookUserSetMainSinkNotificationConfiguration(sinkID,mainNotificationConfiguration)); +} + +am_Error_e CAmCommandReceiver::setMainSourceNotificationConfiguration(const am_sourceID_t sourceID, const am_NotificationConfiguration_s& mainNotificationConfiguration) +{ + logInfo("CommandReceiver::setMainSourceNotificationConfiguration got called, sourceID=", sourceID, " type=",mainNotificationConfiguration.type, " parameter=", mainNotificationConfiguration.parameter, "status=",mainNotificationConfiguration.status); + return (mControlSender->hookUserSetMainSourceNotificationConfiguration(sourceID,mainNotificationConfiguration)); +} + +void CAmCommandReceiver::waitOnRundown(bool rundown) +{ + mWaitRundown = rundown; + mLastErrorStartup=E_OK; +} + +} diff --git a/AudioManagerCore/src/CAmCommandSender.cpp b/AudioManagerCore/src/CAmCommandSender.cpp new file mode 100644 index 0000000..da064cc --- /dev/null +++ b/AudioManagerCore/src/CAmCommandSender.cpp @@ -0,0 +1,367 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2012, BMW AG + * + * This file is part of GENIVI Project AudioManager. + * + * Contributions are licensed to the GENIVI Alliance under one or more + * Contribution License Agreements. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012 + * + * \file CAmCommandSender.cpp + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmCommandSender.h" +#include <dirent.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sstream> +#include <string> +#include <cstring> +#include <stdexcept> +#include "CAmCommandReceiver.h" +#include "TAmPluginTemplate.h" +#include "CAmDltWrapper.h" +#include "audiomanagerconfig.h" + +namespace am +{ + +/** + * macro to call all interfaces + */ +#define CALL_ALL_INTERFACES(...) \ + std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin(); \ + std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end(); \ + for (; iter<iterEnd;++iter) \ + { \ + (*iter)->__VA_ARGS__; \ + } + +CAmCommandSender::CAmCommandSender(const std::vector<std::string>& listOfPluginDirectories) : + mListInterfaces(), // + mListLibraryHandles(), // + mListLibraryNames(), // + mCommandReceiver() +{ + if (listOfPluginDirectories.empty()) + { + logError("CAmCommandSender::CAmCommandSender: List of commandplugins is empty"); + } + + std::vector<std::string> sharedLibraryNameList; + std::vector<std::string>::const_iterator dirIter = listOfPluginDirectories.begin(); + std::vector<std::string>::const_iterator dirIterEnd = listOfPluginDirectories.end(); + + // search communicator plugins in configured directories + for (; dirIter < dirIterEnd; ++dirIter) + { + const char* directoryName = dirIter->c_str(); + logInfo("Searching for CommandPlugins in", *dirIter); + DIR *directory = opendir(directoryName); + + if (!directory) + { + logError("Error opening directory ", *dirIter); + continue; + } + + // iterate content of directory + struct dirent *itemInDirectory = 0; + while ((itemInDirectory = readdir(directory))) + { + unsigned char entryType = itemInDirectory->d_type; + std::string entryName = itemInDirectory->d_name; + std::string fullName = *dirIter + "/" + entryName; + + bool regularFile = (entryType == DT_REG || entryType == DT_LNK); + bool sharedLibExtension = ("so" == entryName.substr(entryName.find_last_of(".") + 1)); + + // Handle cases where readdir() could not determine the file type + if (entryType == DT_UNKNOWN) { + struct stat buf; + + if (stat(fullName.c_str(), &buf)) { + logInfo(__PRETTY_FUNCTION__,"Failed to stat file: ", entryName, errno); + continue; + } + + regularFile = S_ISREG(buf.st_mode); + } + + if (regularFile && sharedLibExtension) + { + std::string name(directoryName); + sharedLibraryNameList.push_back(name + "/" + entryName); + } + } + closedir(directory); + } + + // iterate all communicator plugins and start them + std::vector<std::string>::iterator iter = sharedLibraryNameList.begin(); + std::vector<std::string>::iterator iterEnd = sharedLibraryNameList.end(); + + for (; iter < iterEnd; ++iter) + { + logInfo("Loading CommandSender plugin", *iter); + IAmCommandSend* (*createFunc)(); + void* tempLibHandle = NULL; + createFunc = getCreateFunction<IAmCommandSend*()>(*iter, tempLibHandle); + + if (!createFunc) + { + logInfo("Entry point of CommandPlugin not found", *iter); + continue; + } + + IAmCommandSend* commander = createFunc(); + + if (!commander) + { + logInfo("CommandPlugin initialization failed. Entry Function not callable"); + dlclose(tempLibHandle); + continue; + } + + //check libversion + std::string version, cVersion(CommandVersion); + commander->getInterfaceVersion(version); + uint16_t minorVersion, majorVersion, cMinorVersion, cMajorVersion; + std::istringstream(version.substr(0, 1)) >> majorVersion; + std::istringstream(version.substr(2, 1)) >> minorVersion; + std::istringstream(cVersion.substr(0, 1)) >> cMajorVersion; + std::istringstream(cVersion.substr(2, 1)) >> cMinorVersion; + + + + if (majorVersion < cMajorVersion || ((majorVersion == cMajorVersion) && (minorVersion > cMinorVersion))) + { + logError("CommandInterface initialization failed. Version of Interface to old"); + dlclose(tempLibHandle); + continue; + } + + mListInterfaces.push_back(commander); + mListLibraryHandles.push_back(tempLibHandle); + mListLibraryNames.push_back(iter->c_str()); + } +} + +CAmCommandSender::~CAmCommandSender() +{ + //unloadLibraries(); +} + +am_Error_e CAmCommandSender::startupInterfaces(CAmCommandReceiver *iCommandReceiver) +{ + mCommandReceiver = iCommandReceiver; + am_Error_e returnError = E_OK; + + std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin(); + std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end(); + for (; iter < iterEnd; ++iter) + { + am_Error_e error = (*iter)->startupInterface(iCommandReceiver); + if (error != E_OK) + { + returnError = error; + } + } + return (returnError); +} + +void CAmCommandSender::cbNumberOfSinkClassesChanged() +{ + CALL_ALL_INTERFACES(cbNumberOfSinkClassesChanged()) +} + +void CAmCommandSender::cbNumberOfSourceClassesChanged() +{ + CALL_ALL_INTERFACES(cbNumberOfSourceClassesChanged()) +} + +void CAmCommandSender::cbMainConnectionStateChanged(const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState) +{ + CALL_ALL_INTERFACES(cbMainConnectionStateChanged(connectionID,connectionState)) +} + +void CAmCommandSender::cbMainSinkSoundPropertyChanged(const am_sinkID_t sinkID, const am_MainSoundProperty_s& SoundProperty) +{ + CALL_ALL_INTERFACES(cbMainSinkSoundPropertyChanged(sinkID,SoundProperty)) +} + +void CAmCommandSender::cbMainSourceSoundPropertyChanged(const am_sourceID_t sourceID, const am_MainSoundProperty_s& SoundProperty) +{ + CALL_ALL_INTERFACES(cbMainSourceSoundPropertyChanged(sourceID,SoundProperty)) +} + +void CAmCommandSender::cbSinkAvailabilityChanged(const am_sinkID_t sinkID, const am_Availability_s & availability) +{ + CALL_ALL_INTERFACES(cbSinkAvailabilityChanged(sinkID,availability)) +} + +void CAmCommandSender::cbSourceAvailabilityChanged(const am_sourceID_t sourceID, const am_Availability_s & availability) +{ + CALL_ALL_INTERFACES(cbSourceAvailabilityChanged(sourceID,availability)) +} + +void CAmCommandSender::cbVolumeChanged(const am_sinkID_t sinkID, const am_mainVolume_t volume) +{ + CALL_ALL_INTERFACES(cbVolumeChanged(sinkID,volume)) +} + +void CAmCommandSender::cbSinkMuteStateChanged(const am_sinkID_t sinkID, const am_MuteState_e muteState) +{ + CALL_ALL_INTERFACES(cbSinkMuteStateChanged(sinkID,muteState)) +} + +void CAmCommandSender::cbSystemPropertyChanged(const am_SystemProperty_s & SystemProperty) +{ + CALL_ALL_INTERFACES(cbSystemPropertyChanged(SystemProperty)) +} + +void CAmCommandSender::cbTimingInformationChanged(const am_mainConnectionID_t mainConnection, const am_timeSync_t time) +{ + CALL_ALL_INTERFACES(cbTimingInformationChanged(mainConnection,time)) +} + +void CAmCommandSender::cbNewMainConnection(const am_MainConnectionType_s mainConnection) +{ + CALL_ALL_INTERFACES(cbNewMainConnection(mainConnection)) +} + +void CAmCommandSender::cbRemovedMainConnection(const am_mainConnectionID_t mainConnection) +{ + CALL_ALL_INTERFACES(cbRemovedMainConnection(mainConnection)) +} + +void CAmCommandSender::cbNewSink(const am_SinkType_s sink) +{ + CALL_ALL_INTERFACES(cbNewSink(sink)) +} + +void CAmCommandSender::cbRemovedSink(const am_sinkID_t sink) +{ + CALL_ALL_INTERFACES(cbRemovedSink(sink)) +} + +void CAmCommandSender::cbNewSource(const am_SourceType_s source) +{ + CALL_ALL_INTERFACES(cbNewSource(source)) +} + +void CAmCommandSender::cbRemovedSource(const am_sourceID_t source) +{ + CALL_ALL_INTERFACES(cbRemovedSource(source)) +} + +void CAmCommandSender::setCommandReady() +{ + mCommandReceiver->waitOnStartup(false); + + //create a list of handles + std::vector<uint16_t> listStartupHandles; + for (size_t i = 0; i < mListInterfaces.size(); i++) + { + listStartupHandles.push_back(mCommandReceiver->getStartupHandle()); + } + + //set the receiver ready to wait for replies + mCommandReceiver->waitOnStartup(true); + + //now do the calls + std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin(); + std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end(); + std::vector<uint16_t>::const_iterator handleIter(listStartupHandles.begin()); + for (; iter < iterEnd; ++iter) + { + (*iter)->setCommandReady(*(handleIter++)); + } +} + +void CAmCommandSender::setCommandRundown() +{ + mCommandReceiver->waitOnRundown(false); + //create a list of handles + std::vector<uint16_t> listStartupHandles; + for (size_t i = 0; i < mListInterfaces.size(); i++) + { + listStartupHandles.push_back(mCommandReceiver->getRundownHandle()); + } + + //set the receiver ready to wait for replies + mCommandReceiver->waitOnRundown(true); + + //now do the calls + std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin(); + std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end(); + std::vector<uint16_t>::const_iterator handleIter(listStartupHandles.begin()); + for (; iter < iterEnd; ++iter) + { + (*iter)->setCommandRundown(*(handleIter++)); + } +} + +void CAmCommandSender::getInterfaceVersion(std::string & version) const +{ + version = CommandVersion; +} + +am_Error_e am::CAmCommandSender::getListPlugins(std::vector<std::string> & interfaces) const +{ + interfaces = mListLibraryNames; + return (E_OK); +} + +void CAmCommandSender::cbSinkUpdated(const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties) +{ + CALL_ALL_INTERFACES(cbSinkUpdated(sinkID,sinkClassID,listMainSoundProperties)); +} + +void CAmCommandSender::cbSourceUpdated(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties) +{ + CALL_ALL_INTERFACES(cbSourceUpdated(sourceID,sourceClassID,listMainSoundProperties)); +} + +void CAmCommandSender::cbSinkNotification(const am_sinkID_t sinkID, const am_NotificationPayload_s& notification) +{ + CALL_ALL_INTERFACES(cbSinkNotification(sinkID,notification)); +} + +void CAmCommandSender::cbSourceNotification(const am_sourceID_t sourceID, const am_NotificationPayload_s& notification) +{ + CALL_ALL_INTERFACES(cbSourceNotification(sourceID,notification)); +} + +void CAmCommandSender::cbSinkMainNotificationConfigurationChanged(const am_sinkID_t sinkID, const am_NotificationConfiguration_s& mainNotificationConfiguration) +{ + CALL_ALL_INTERFACES(cbMainSinkNotificationConfigurationChanged(sinkID,mainNotificationConfiguration)); +} + +void CAmCommandSender::cbSourceMainNotificationConfigurationChanged(const am_sourceID_t sourceID, const am_NotificationConfiguration_s& mainNotificationConfiguration) +{ + CALL_ALL_INTERFACES(cbMainSourceNotificationConfigurationChanged(sourceID,mainNotificationConfiguration)); +} + +void CAmCommandSender::unloadLibraries(void) +{ + std::vector<void*>::iterator iterator = mListLibraryHandles.begin(); + for (; iterator < mListLibraryHandles.end(); ++iterator) + { + dlclose(*iterator); + } + mListLibraryHandles.clear(); +} +} diff --git a/AudioManagerCore/src/CAmControlReceiver.cpp b/AudioManagerCore/src/CAmControlReceiver.cpp new file mode 100644 index 0000000..c1c161e --- /dev/null +++ b/AudioManagerCore/src/CAmControlReceiver.cpp @@ -0,0 +1,606 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2012, BMW AG + * + * This file is part of GENIVI Project AudioManager. + * + * Contributions are licensed to the GENIVI Alliance under one or more + * Contribution License Agreements. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012 + * + * \file CAmControlReceiver.cpp + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmControlReceiver.h" +#include <cassert> +#include <stdlib.h> +#include <stdexcept> +#include "audiomanagerconfig.h" +#include "IAmDatabaseHandler.h" +#include "CAmRoutingSender.h" +#include "CAmCommandSender.h" +#include "CAmRouter.h" +#include "CAmDltWrapper.h" +#include "CAmSocketHandler.h" + +namespace am { + +CAmControlReceiver::CAmControlReceiver(IAmDatabaseHandler *iDatabaseHandler, CAmRoutingSender *iRoutingSender, CAmCommandSender *iCommandSender, CAmSocketHandler *iSocketHandler, CAmRouter* iRouter) : + mDatabaseHandler(iDatabaseHandler), // + mRoutingSender(iRoutingSender), // + mCommandSender(iCommandSender), // + mSocketHandler(iSocketHandler), // + mRouter(iRouter), // + mNodeStateCommunicator(NULL) +{ + assert(mDatabaseHandler!=NULL); + assert(mRoutingSender!=NULL); + assert(mCommandSender!=NULL); + assert(mSocketHandler!=NULL); + assert(mRouter!=NULL); +} + +CAmControlReceiver::~CAmControlReceiver() +{ +} + +am_Error_e CAmControlReceiver::getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s> & returnList) +{ + return (mRouter->getRoute(onlyfree, sourceID, sinkID, returnList)); +} + +am_Error_e CAmControlReceiver::connect(am_Handle_s & handle, am_connectionID_t & connectionID, const am_CustomConnectionFormat_t format, const am_sourceID_t sourceID, const am_sinkID_t sinkID) +{ + logInfo("CAmControlReceiver::connect got called, connectionFormat=", format, "sourceID=", sourceID, "sinkID=", sinkID); + + am_Connection_s tempConnection; + tempConnection.sinkID = sinkID; + tempConnection.sourceID = sourceID; + tempConnection.connectionFormat = format; + tempConnection.connectionID = 0; + tempConnection.delay=-1; + + mDatabaseHandler->enterConnectionDB(tempConnection, connectionID); + am_Error_e syncError(mRoutingSender->asyncConnect(handle, connectionID, sourceID, sinkID, format)); + if (syncError) + { + mDatabaseHandler->removeConnection(connectionID); + } + return(syncError); +} + +am_Error_e CAmControlReceiver::disconnect(am_Handle_s & handle, const am_connectionID_t connectionID) +{ + logInfo("CAmControlReceiver::disconnect got called, connectionID=", connectionID); + return (mRoutingSender->asyncDisconnect(handle, connectionID)); +} + +am_Error_e CAmControlReceiver::crossfade(am_Handle_s & handle, const am_HotSink_e hotSource, const am_crossfaderID_t crossfaderID, const am_CustomRampType_t rampType, const am_time_t rampTime) +{ + logInfo("CAmControlReceiver::crossfade got called, hotSource=", hotSource, "crossfaderID=", crossfaderID, "rampType=", rampType, "rampTime=", rampTime); + return (mRoutingSender->asyncCrossFade(handle, crossfaderID, hotSource, rampType, rampTime)); +} + +am_Error_e CAmControlReceiver::setSourceState(am_Handle_s & handle, const am_sourceID_t sourceID, const am_SourceState_e state) +{ + logInfo("CAmControlReceiver::setSourceState got called, sourceID=", sourceID, "state=", state); + return (mRoutingSender->asyncSetSourceState(handle, sourceID, state)); +} + +am_Error_e CAmControlReceiver::setSinkVolume(am_Handle_s & handle, const am_sinkID_t sinkID, const am_volume_t volume, const am_CustomRampType_t ramp, const am_time_t time) +{ + logInfo("CAmControlReceiver::setSinkVolume got called, sinkID=", sinkID, "volume=", volume, "ramp=", ramp, "time=", time); + return (mRoutingSender->asyncSetSinkVolume(handle, sinkID, volume, ramp, time)); +} + +am_Error_e CAmControlReceiver::setSourceVolume(am_Handle_s & handle, const am_sourceID_t sourceID, const am_volume_t volume, const am_CustomRampType_t rampType, const am_time_t time) +{ + logInfo("CAmControlReceiver::setSourceVolume got called, sourceID=", sourceID, "volume=", volume, "ramp=", rampType, "time=", time); + return (mRoutingSender->asyncSetSourceVolume(handle, sourceID, volume, rampType, time)); +} + +am_Error_e CAmControlReceiver::setSinkSoundProperty(am_Handle_s & handle, const am_sinkID_t sinkID, const am_SoundProperty_s & soundProperty) +{ + logInfo("CAmControlReceiver::setSinkSoundProperty got called, sinkID=", sinkID, "soundProperty.Type=", soundProperty.type, "soundProperty.value=", soundProperty.value); + return (mRoutingSender->asyncSetSinkSoundProperty(handle, sinkID, soundProperty)); +} + +am_Error_e CAmControlReceiver::setSinkSoundProperties(am_Handle_s & handle, const am_sinkID_t sinkID, const std::vector<am_SoundProperty_s> & listSoundProperties) +{ + logInfo("CAmControlReceiver::setSinkSoundProperties got called, sinkID=", sinkID); + return (mRoutingSender->asyncSetSinkSoundProperties(handle, listSoundProperties, sinkID)); +} + +am_Error_e CAmControlReceiver::setSourceSoundProperty(am_Handle_s & handle, const am_sourceID_t sourceID, const am_SoundProperty_s & soundProperty) +{ + logInfo("CAmControlReceiver::setSourceSoundProperty got called, sourceID=", sourceID, "soundProperty.Type=", soundProperty.type, "soundProperty.value=", soundProperty.value); + return (mRoutingSender->asyncSetSourceSoundProperty(handle, sourceID, soundProperty)); +} + +am_Error_e CAmControlReceiver::setSourceSoundProperties(am_Handle_s & handle, const am_sourceID_t sourceID, const std::vector<am_SoundProperty_s> & listSoundProperties) +{ + logInfo("CAmControlReceiver::setSourceSoundProperties got called, sourceID=", sourceID); + return (mRoutingSender->asyncSetSourceSoundProperties(handle, listSoundProperties, sourceID)); +} + +am_Error_e CAmControlReceiver::setDomainState(const am_domainID_t domainID, const am_DomainState_e domainState) +{ + logInfo("CAmControlReceiver::setDomainState got called, domainID=", domainID, "domainState=", domainState); + return (mRoutingSender->setDomainState(domainID, domainState)); +} + +am_Error_e CAmControlReceiver::abortAction(const am_Handle_s handle) +{ + logInfo("CAmControlReceiver::abortAction got called, handle.type=", handle.handle, "handle.handleType=", handle.handleType); + return (mRoutingSender->asyncAbort(handle)); +} + +am_Error_e CAmControlReceiver::enterDomainDB(const am_Domain_s & domainData, am_domainID_t & domainID) +{ + return (mDatabaseHandler->enterDomainDB(domainData, domainID)); +} + +am_Error_e CAmControlReceiver::enterMainConnectionDB(const am_MainConnection_s & mainConnectionData, am_mainConnectionID_t & connectionID) +{ + return (mDatabaseHandler->enterMainConnectionDB(mainConnectionData, connectionID)); +} + +am_Error_e CAmControlReceiver::enterSinkDB(const am_Sink_s & sinkData, am_sinkID_t & sinkID) +{ + return (mDatabaseHandler->enterSinkDB(sinkData, sinkID)); +} + +am_Error_e CAmControlReceiver::enterCrossfaderDB(const am_Crossfader_s & crossfaderData, am_crossfaderID_t & crossfaderID) +{ + return (mDatabaseHandler->enterCrossfaderDB(crossfaderData, crossfaderID)); +} + +am_Error_e CAmControlReceiver::enterGatewayDB(const am_Gateway_s & gatewayData, am_gatewayID_t & gatewayID) +{ + 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)); +} + +am_Error_e CAmControlReceiver::enterSinkClassDB(const am_SinkClass_s & sinkClass, am_sinkClass_t & sinkClassID) +{ + return (mDatabaseHandler->enterSinkClassDB(sinkClass, sinkClassID)); +} + +am_Error_e CAmControlReceiver::enterSourceClassDB(am_sourceClass_t & sourceClassID, const am_SourceClass_s & sourceClass) +{ + return (mDatabaseHandler->enterSourceClassDB(sourceClassID, sourceClass)); +} + +am_Error_e CAmControlReceiver::enterSystemPropertiesListDB(const std::vector<am_SystemProperty_s> & listSystemProperties) +{ + return (mDatabaseHandler->enterSystemProperties(listSystemProperties)); +} + +am_Error_e CAmControlReceiver::changeMainConnectionRouteDB(const am_mainConnectionID_t mainconnectionID, const std::vector<am_connectionID_t>& listConnectionID) +{ + return (mDatabaseHandler->changeMainConnectionRouteDB(mainconnectionID, listConnectionID)); +} + +am_Error_e CAmControlReceiver::changeMainConnectionStateDB(const am_mainConnectionID_t mainconnectionID, const am_ConnectionState_e connectionState) +{ + return (mDatabaseHandler->changeMainConnectionStateDB(mainconnectionID, connectionState)); +} + +am_Error_e CAmControlReceiver::changeSinkMainVolumeDB(const am_mainVolume_t mainVolume, const am_sinkID_t sinkID) +{ + return (mDatabaseHandler->changeSinkMainVolumeDB(mainVolume, sinkID)); +} + +am_Error_e CAmControlReceiver::changeSinkAvailabilityDB(const am_Availability_s & availability, const am_sinkID_t sinkID) +{ + return (mDatabaseHandler->changeSinkAvailabilityDB(availability, sinkID)); +} + +am_Error_e CAmControlReceiver::changDomainStateDB(const am_DomainState_e domainState, const am_domainID_t domainID) +{ + return (mDatabaseHandler->changDomainStateDB(domainState, domainID)); +} + +am_Error_e CAmControlReceiver::changeSinkMuteStateDB(const am_MuteState_e muteState, const am_sinkID_t sinkID) +{ + return (mDatabaseHandler->changeSinkMuteStateDB(muteState, sinkID)); +} + +am_Error_e CAmControlReceiver::changeMainSinkSoundPropertyDB(const am_MainSoundProperty_s & soundProperty, const am_sinkID_t sinkID) +{ + return (mDatabaseHandler->changeMainSinkSoundPropertyDB(soundProperty, sinkID)); +} + +am_Error_e CAmControlReceiver::changeMainSourceSoundPropertyDB(const am_MainSoundProperty_s & soundProperty, const am_sourceID_t sourceID) +{ + return (mDatabaseHandler->changeMainSourceSoundPropertyDB(soundProperty, sourceID)); +} + +am_Error_e CAmControlReceiver::changeSourceAvailabilityDB(const am_Availability_s & availability, const am_sourceID_t sourceID) +{ + return (mDatabaseHandler->changeSourceAvailabilityDB(availability, sourceID)); +} + +am_Error_e CAmControlReceiver::changeSystemPropertyDB(const am_SystemProperty_s & property) +{ + return (mDatabaseHandler->changeSystemPropertyDB(property)); +} + +am_Error_e CAmControlReceiver::removeMainConnectionDB(const am_mainConnectionID_t mainConnectionID) +{ + return (mDatabaseHandler->removeMainConnectionDB(mainConnectionID)); +} + +am_Error_e CAmControlReceiver::removeSinkDB(const am_sinkID_t sinkID) +{ + return (mDatabaseHandler->removeSinkDB(sinkID)); +} + +am_Error_e CAmControlReceiver::removeSourceDB(const am_sourceID_t sourceID) +{ + return (mDatabaseHandler->removeSourceDB(sourceID)); +} + +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)); +} + +am_Error_e CAmControlReceiver::removeDomainDB(const am_domainID_t domainID) +{ + return (mDatabaseHandler->removeDomainDB(domainID)); +} + +am_Error_e CAmControlReceiver::getSourceClassInfoDB(const am_sourceID_t sourceID, am_SourceClass_s & classInfo) const +{ + return (mDatabaseHandler->getSourceClassInfoDB(sourceID, classInfo)); +} + +am_Error_e CAmControlReceiver::getSinkClassInfoDB(const am_sinkID_t sinkID, am_SinkClass_s & sinkClass) const +{ + return (mDatabaseHandler->getSinkClassInfoDB(sinkID, sinkClass)); +} + +am_Error_e CAmControlReceiver::getSinkInfoDB(const am_sinkID_t sinkID, am_Sink_s & sinkData) const +{ + return (mDatabaseHandler->getSinkInfoDB(sinkID, sinkData)); +} + +am_Error_e CAmControlReceiver::getSourceInfoDB(const am_sourceID_t sourceID, am_Source_s & sourceData) const +{ + return (mDatabaseHandler->getSourceInfoDB(sourceID, sourceData)); +} + +am_Error_e CAmControlReceiver::getMainConnectionInfoDB(const am_mainConnectionID_t mainConnectionID, am_MainConnection_s & mainConnectionData) const +{ + return (mDatabaseHandler->getMainConnectionInfoDB(mainConnectionID, mainConnectionData)); +} + +am_Error_e CAmControlReceiver::getGatewayInfoDB(const am_gatewayID_t gatewayID, am_Gateway_s & gatewayData) const +{ + 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)); +} + +am_Error_e CAmControlReceiver::getListSinksOfDomain(const am_domainID_t domainID, std::vector<am_sinkID_t> & listSinkID) const +{ + return (mDatabaseHandler->getListSinksOfDomain(domainID, listSinkID)); +} + +am_Error_e CAmControlReceiver::getListSourcesOfDomain(const am_domainID_t domainID, std::vector<am_sourceID_t> & listSourceID) const +{ + return (mDatabaseHandler->getListSourcesOfDomain(domainID, listSourceID)); +} + +am_Error_e CAmControlReceiver::getListCrossfadersOfDomain(const am_domainID_t domainID, std::vector<am_crossfaderID_t> & listGatewaysID) const +{ + return (mDatabaseHandler->getListCrossfadersOfDomain(domainID, listGatewaysID)); +} + +am_Error_e CAmControlReceiver::getListGatewaysOfDomain(const am_domainID_t domainID, std::vector<am_gatewayID_t> & listGatewaysID) const +{ + 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)); +} + +am_Error_e CAmControlReceiver::getListDomains(std::vector<am_Domain_s> & listDomains) const +{ + return (mDatabaseHandler->getListDomains(listDomains)); +} + +am_Error_e CAmControlReceiver::getListConnections(std::vector<am_Connection_s> & listConnections) const +{ + return (mDatabaseHandler->getListConnections(listConnections)); +} + +am_Error_e CAmControlReceiver::getListSinks(std::vector<am_Sink_s> & listSinks) const +{ + return (mDatabaseHandler->getListSinks(listSinks)); +} + +am_Error_e CAmControlReceiver::getListSources(std::vector<am_Source_s> & listSources) const +{ + return (mDatabaseHandler->getListSources(listSources)); +} + +am_Error_e CAmControlReceiver::getListSourceClasses(std::vector<am_SourceClass_s> & listSourceClasses) const +{ + return (mDatabaseHandler->getListSourceClasses(listSourceClasses)); +} + +am_Error_e CAmControlReceiver::getListHandles(std::vector<am_Handle_s> & listHandles) const +{ + return (mRoutingSender->getListHandles(listHandles)); +} + +am_Error_e CAmControlReceiver::getListCrossfaders(std::vector<am_Crossfader_s> & listCrossfaders) const +{ + return (mDatabaseHandler->getListCrossfaders(listCrossfaders)); +} + +am_Error_e CAmControlReceiver::getListGateways(std::vector<am_Gateway_s> & listGateways) const +{ + 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)); +} + +am_Error_e CAmControlReceiver::getListSystemProperties(std::vector<am_SystemProperty_s> & listSystemProperties) const +{ + return (mDatabaseHandler->getListSystemProperties(listSystemProperties)); +} + +am_Error_e CAmControlReceiver::changeSinkClassInfoDB(const am_SinkClass_s & classInfo) +{ + return (mDatabaseHandler->changeSinkClassInfoDB(classInfo)); +} + +am_Error_e CAmControlReceiver::changeSourceClassInfoDB(const am_SourceClass_s & classInfo) +{ + return(mDatabaseHandler->changeSourceClassInfoDB(classInfo)); +} + +am_Error_e CAmControlReceiver::removeSinkClassDB(const am_sinkClass_t sinkClassID) +{ + return (mDatabaseHandler->removeSinkClassDB(sinkClassID)); +} + +am_Error_e CAmControlReceiver::removeSourceClassDB(const am_sourceClass_t sourceClassID) +{ + return (mDatabaseHandler->removeSourceClassDB(sourceClassID)); +} + +void CAmControlReceiver::setCommandReady() +{ + logInfo("CAmControlReceiver::setCommandReady got called"); + mCommandSender->setCommandReady(); +} + +void CAmControlReceiver::setRoutingReady() +{ + logInfo("CAmControlReceiver::setRoutingReady got called"); + mRoutingSender->setRoutingReady(); +} + +void CAmControlReceiver::confirmControllerReady(const am_Error_e error) +{ + if (error!=E_OK) + logError("CAmControlReceiver::confirmControllerReady controller reported error", error); +} + +void CAmControlReceiver::confirmControllerRundown(const am_Error_e error) +{ + if (error!=E_OK) + { + logError("CAmControlReceiver::confirmControllerRundown() exited with error ",error); + //we might be blocked here -> so lets better exit right away + throw std::runtime_error("controller Confirmed with error"); + } + + logInfo ("CAmControlReceiver::confirmControllerRundown(), will exit now"); + + //end the mainloop here... + mSocketHandler->exit_mainloop(); +} + +am_Error_e CAmControlReceiver::getSocketHandler(CAmSocketHandler *& socketHandler) +{ + socketHandler = mSocketHandler; + return (E_OK); +} + +void CAmControlReceiver::setCommandRundown() +{ + logInfo("CAmControlReceiver::setCommandRundown got called"); + mCommandSender->setCommandRundown(); +} + +void CAmControlReceiver::setRoutingRundown() +{ + logInfo("CAmControlReceiver::setRoutingRundown got called"); + mRoutingSender->setRoutingRundown(); +} + +void CAmControlReceiver::getInterfaceVersion(std::string & version) const +{ + version = ControlVersion; +} + +am_Error_e CAmControlReceiver::changeSourceDB(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_SoundProperty_s>& listSoundProperties, const std::vector<am_CustomConnectionFormat_t>& listConnectionFormats, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties) +{ + logInfo("CAmControlReceiver::changeSourceDB was called, sourceID", sourceID); + return (mDatabaseHandler->changeSourceDB(sourceID,sourceClassID,listSoundProperties,listConnectionFormats,listMainSoundProperties)); +} + +am_Error_e CAmControlReceiver::changeSinkDB(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) +{ + logInfo("CAmControlReceiver::changeSinkDB was called with sinkID", sinkID); + return (mDatabaseHandler->changeSinkDB(sinkID,sinkClassID,listSoundProperties,listConnectionFormats,listMainSoundProperties)); +} + +am_Error_e CAmControlReceiver::changeGatewayDB(const am_gatewayID_t gatewayID, const std::vector<am_CustomConnectionFormat_t>& listSourceConnectionFormats, const std::vector<am_CustomConnectionFormat_t>& listSinkConnectionFormats, const std::vector<bool>& convertionMatrix) +{ + logInfo("CAmControlReceiver::changeGatewayDB was called with gatewayID", gatewayID); + 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"); + return (mRoutingSender->asyncSetVolumes(handle,listVolumes)); +} + +am_Error_e CAmControlReceiver::setSinkNotificationConfiguration(am_Handle_s& handle, const am_sinkID_t sinkID, const am_NotificationConfiguration_s& notificationConfiguration) +{ + logInfo("CAmControlReceiver::setSinkNotificationConfiguration called, sinkID=",sinkID,"notificationConfiguration.type=",notificationConfiguration.type,"notificationConfiguration.status",notificationConfiguration.status,"notificationConfiguration.parameter",notificationConfiguration.parameter); + return (mRoutingSender->asyncSetSinkNotificationConfiguration(handle,sinkID,notificationConfiguration)); +} + +am_Error_e CAmControlReceiver::setSourceNotificationConfiguration(am_Handle_s& handle, const am_sourceID_t sourceID, const am_NotificationConfiguration_s& notificationConfiguration) +{ + logInfo("CAmControlReceiver::setSourceNotificationConfiguration called, sourceID=",sourceID,"notificationConfiguration.type=",notificationConfiguration.type,"notificationConfiguration.status",notificationConfiguration.status,"notificationConfiguration.parameter",notificationConfiguration.parameter); + return (mRoutingSender->asyncSetSourceNotificationConfiguration(handle,sourceID,notificationConfiguration)); +} + +void CAmControlReceiver::sendMainSinkNotificationPayload(const am_sinkID_t sinkID, const am_NotificationPayload_s& notificationPayload) +{ + logInfo("CAmControlReceiver::sendSinkMainNotificationPayload called, sinkID=",sinkID,"type=",notificationPayload.type,"value=",notificationPayload.value); + mCommandSender->cbSinkNotification(sinkID,notificationPayload); +} + +void CAmControlReceiver::sendMainSourceNotificationPayload(const am_sourceID_t sourceID, const am_NotificationPayload_s& notificationPayload) +{ + logInfo("CAmControlReceiver::sendSourceMainNotificationPayload called, sourceID=",sourceID,"type=",notificationPayload.type,"value=",notificationPayload.value); + mCommandSender->cbSourceNotification(sourceID,notificationPayload); +} + +am_Error_e CAmControlReceiver::changeMainSinkNotificationConfigurationDB(const am_sinkID_t sinkID, const am_NotificationConfiguration_s& mainNotificationConfiguration) +{ + logInfo("CAmControlReceiver::changeMainSinkNotificationConfigurationDB was called with sinkID", sinkID); + return (mDatabaseHandler->changeMainSinkNotificationConfigurationDB(sinkID,mainNotificationConfiguration)); +} + +am_Error_e CAmControlReceiver::changeMainSourceNotificationConfigurationDB(const am_sourceID_t sourceID, const am_NotificationConfiguration_s& mainNotificationConfiguration) +{ + logInfo("CAmControlReceiver::changeMainSourceNotificationConfigurationDB was called with sourceID", sourceID); + return (mDatabaseHandler->changeMainSourceNotificationConfigurationDB(sourceID,mainNotificationConfiguration)); +} + +am_Error_e CAmControlReceiver::getListMainSinkSoundProperties(const am_sinkID_t sinkID, std::vector<am_MainSoundProperty_s>& listSoundproperties) const +{ + logInfo("CAmControlReceiver::getListMainSinkSoundProperties was called, sinkID", sinkID); + return (mDatabaseHandler->getListMainSinkSoundProperties(sinkID,listSoundproperties)); +} + +am_Error_e CAmControlReceiver::getListMainSourceSoundProperties(const am_sourceID_t sourceID, std::vector<am_MainSoundProperty_s>& listSoundproperties) const +{ + logInfo("CAmControlReceiver::getListMainSourceSoundProperties was called, sourceID", sourceID); + return (mDatabaseHandler->getListMainSourceSoundProperties(sourceID, listSoundproperties)); +} + +am_Error_e CAmControlReceiver::getListSinkSoundProperties(const am_sinkID_t sinkID, std::vector<am_SoundProperty_s>& listSoundproperties) const +{ + logInfo("CAmControlReceiver::getListSinkSoundProperties was called, sinkID", sinkID); + return (mDatabaseHandler->getListSinkSoundProperties(sinkID,listSoundproperties)); +} + +am_Error_e CAmControlReceiver::getListSourceSoundProperties(const am_sourceID_t sourceID, std::vector<am_SoundProperty_s>& listSoundproperties) const +{ + logInfo("CAmControlReceiver::getListSourceSoundProperties was called, sourceID", sourceID); + return (mDatabaseHandler->getListSourceSoundProperties(sourceID, listSoundproperties)); +} + +am_Error_e CAmControlReceiver::getMainSinkSoundPropertyValue(const am_sinkID_t sinkID, const am_CustomMainSoundPropertyType_t propertyType, int16_t& value) const +{ + logInfo("CAmControlReceiver::getMainSinkSoundPropertyValue was called, sinkID", sinkID); + return (mDatabaseHandler->getMainSinkSoundPropertyValue(sinkID,propertyType,value)); +} + +am_Error_e CAmControlReceiver::getSinkSoundPropertyValue(const am_sinkID_t sinkID, const am_CustomSoundPropertyType_t propertyType, int16_t& value) const +{ + logInfo("CAmControlReceiver::getSinkSoundPropertyValue was called, sinkID", sinkID); + return (mDatabaseHandler->getSinkSoundPropertyValue(sinkID,propertyType,value)); +} + +am_Error_e CAmControlReceiver::getMainSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomMainSoundPropertyType_t propertyType, int16_t& value) const +{ + logInfo("CAmControlReceiver::getMainSourceSoundPropertyValue was called, sourceID", sourceID); + return (mDatabaseHandler->getMainSourceSoundPropertyValue(sourceID,propertyType,value)); +} + +am_Error_e CAmControlReceiver::getSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomSoundPropertyType_t propertyType, int16_t& value) const +{ + logInfo("CAmControlReceiver::getSourceSoundPropertyValue was called, sourceID", sourceID); + return (mDatabaseHandler->getSourceSoundPropertyValue(sourceID,propertyType,value)); +} + +am_Error_e CAmControlReceiver::resyncConnectionState(const am_domainID_t domainID,std::vector<am_Connection_s>& listOfExistingConnections) +{ + logInfo("CAmControlReceiver::resyncConnectionState was called, domainID", domainID); + return (mRoutingSender->resyncConnectionState(domainID,listOfExistingConnections)); +} + +} + diff --git a/AudioManagerCore/src/CAmControlSender.cpp b/AudioManagerCore/src/CAmControlSender.cpp new file mode 100644 index 0000000..10125d5 --- /dev/null +++ b/AudioManagerCore/src/CAmControlSender.cpp @@ -0,0 +1,571 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2012, BMW AG + * + * This file is part of GENIVI Project AudioManager. + * + * Contributions are licensed to the GENIVI Alliance under one or more + * Contribution License Agreements. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012 + * + * \file CAmControlSender.cpp + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmControlSender.h" +#include <cassert> +#include <fstream> +#include <iostream> +#include <sstream> +#include <stdexcept> +#include <sys/stat.h> +#include <sys/types.h> +#include <dirent.h> +#include "TAmPluginTemplate.h" +#include "CAmDltWrapper.h" + +namespace am +{ + +#define REQUIRED_INTERFACE_VERSION_MAJOR 1 //!< major interface version. All versions smaller than this will be rejected +#define REQUIRED_INTERFACE_VERSION_MINOR 0 //!< minor interface version. All versions smaller than this will be rejected + +CAmControlSender* CAmControlSender::mInstance=NULL; + +CAmControlSender::CAmControlSender(std::string controlPluginFile,CAmSocketHandler* sockethandler) : + receiverCallbackT(this, &CAmControlSender::receiverCallback),// + checkerCallbackT(this, &CAmControlSender::checkerCallback),// + dispatcherCallbackT(this, &CAmControlSender::dispatcherCallback), // + mPipe(), // + mlibHandle(NULL), // + mController(NULL), // + mSignal(0) +{ + assert(sockethandler); + + //Check if a folder is given, then select the first plugin + struct stat buf; + const char* conFile(controlPluginFile.c_str()); + stat(conFile, &buf); + if (S_ISDIR(buf.st_mode)) + { + std::string directoryName(controlPluginFile); + logInfo("Searching for ControlPlugin in", directoryName); + DIR *directory = opendir(directoryName.c_str()); + + if (!directory) + { + logError("Error opening directory ", directoryName); + throw std::runtime_error("Controller directory could not be openend"); + } + + // iterate content of directory + struct dirent *itemInDirectory = 0; + while ((itemInDirectory = readdir(directory))) + { + unsigned char entryType = itemInDirectory->d_type; + std::string entryName = itemInDirectory->d_name; + std::string fullName = directoryName + "/" + entryName; + + bool regularFile = (entryType == DT_REG || entryType == DT_LNK); + bool sharedLibExtension = ("so" == entryName.substr(entryName.find_last_of(".") + 1)); + + // Handle cases where readdir() could not determine the file type + if (entryType == DT_UNKNOWN) { + struct stat buf; + + if (stat(fullName.c_str(), &buf)) { + logInfo(__PRETTY_FUNCTION__,"Failed to stat file: ", entryName, errno); + continue; + } + + regularFile = S_ISREG(buf.st_mode); + } + + if (regularFile && sharedLibExtension) + { + controlPluginFile=directoryName + "/" + entryName; + logInfo("Found ControlPlugin:", controlPluginFile); + break; + } + } + closedir(directory); + + } + + std::ifstream isfile(controlPluginFile.c_str()); + if (!isfile) + { + logError("ControlSender::ControlSender: Controller plugin not found:", controlPluginFile); + throw std::runtime_error("Could not find controller plugin!"); + } + else if (!controlPluginFile.empty()) + { + mInstance=this; + IAmControlSend* (*createFunc)(); + createFunc = getCreateFunction<IAmControlSend*()>(controlPluginFile, mlibHandle); + assert(createFunc!=NULL); + mController = createFunc(); + + //check libversion + std::string version, cVersion(ControlVersion); + mController->getInterfaceVersion(version); + uint16_t minorVersion, majorVersion, cMinorVersion, cMajorVersion; + std::istringstream(version.substr(0, 1)) >> majorVersion; + std::istringstream(version.substr(2, 1)) >> minorVersion; + std::istringstream(cVersion.substr(0, 1)) >> cMajorVersion; + std::istringstream(cVersion.substr(2, 1)) >> cMinorVersion; + + + + if (majorVersion < cMajorVersion || ((majorVersion == cMajorVersion) && (minorVersion > cMinorVersion))) + { + logError("ControlSender::ControlSender: Interface Version of Controller too old, exiting now"); + throw std::runtime_error("Interface Version of Controller too old"); + } + } + else + { + logError("ControlSender::ControlSender: No controller loaded !"); + } + + //here we need a pipe to be able to call the rundown function out of the mainloop + if (pipe(mPipe) == -1) + { + logError("CAmControlSender could not create pipe!"); + } + + //add the pipe to the poll - nothing needs to be proccessed here we just need the pipe to trigger the ppoll + short event = 0; + sh_pollHandle_t handle; + event |= POLLIN; + sockethandler->addFDPoll(mPipe[0], event, NULL, &receiverCallbackT, &checkerCallbackT, &dispatcherCallbackT, NULL, handle); +} + +CAmControlSender::~CAmControlSender() +{ + //if (mlibHandle) + // dlclose(mlibHandle); +} + +am_Error_e CAmControlSender::hookUserConnectionRequest(const am_sourceID_t sourceID, const am_sinkID_t sinkID, am_mainConnectionID_t & mainConnectionID) +{ + assert(mController); + return (mController->hookUserConnectionRequest(sourceID, sinkID, mainConnectionID)); +} + +am_Error_e CAmControlSender::hookUserDisconnectionRequest(const am_mainConnectionID_t connectionID) +{ + assert(mController); + return (mController->hookUserDisconnectionRequest(connectionID)); +} + +am_Error_e CAmControlSender::hookUserSetMainSinkSoundProperty(const am_sinkID_t sinkID, const am_MainSoundProperty_s & soundProperty) +{ + assert(mController); + return (mController->hookUserSetMainSinkSoundProperty(sinkID, soundProperty)); +} + +am_Error_e CAmControlSender::hookUserSetMainSourceSoundProperty(const am_sourceID_t sourceID, const am_MainSoundProperty_s & soundProperty) +{ + assert(mController); + return (mController->hookUserSetMainSourceSoundProperty(sourceID, soundProperty)); +} + +am_Error_e CAmControlSender::hookUserSetSystemProperty(const am_SystemProperty_s & property) +{ + assert(mController); + return (mController->hookUserSetSystemProperty(property)); +} + +am_Error_e CAmControlSender::hookUserVolumeChange(const am_sinkID_t sinkID, const am_mainVolume_t newVolume) +{ + assert(mController); + return (mController->hookUserVolumeChange(sinkID, newVolume)); +} + +am_Error_e CAmControlSender::hookUserVolumeStep(const am_sinkID_t sinkID, const int16_t increment) +{ + assert(mController); + return (mController->hookUserVolumeStep(sinkID, increment)); +} + +am_Error_e CAmControlSender::hookUserSetSinkMuteState(const am_sinkID_t sinkID, const am_MuteState_e muteState) +{ + assert(mController); + return (mController->hookUserSetSinkMuteState(sinkID, muteState)); +} + +am_Error_e CAmControlSender::hookSystemRegisterDomain(const am_Domain_s & domainData, am_domainID_t & domainID) +{ + assert(mController); + return (mController->hookSystemRegisterDomain(domainData, domainID)); +} + +am_Error_e CAmControlSender::hookSystemDeregisterDomain(const am_domainID_t domainID) +{ + assert(mController); + return (mController->hookSystemDeregisterDomain(domainID)); +} + +void CAmControlSender::hookSystemDomainRegistrationComplete(const am_domainID_t domainID) +{ + assert(mController); + return (mController->hookSystemDomainRegistrationComplete(domainID)); +} + +am_Error_e CAmControlSender::hookSystemRegisterSink(const am_Sink_s & sinkData, am_sinkID_t & sinkID) +{ + assert(mController); + return (mController->hookSystemRegisterSink(sinkData, sinkID)); +} + +am_Error_e CAmControlSender::hookSystemDeregisterSink(const am_sinkID_t sinkID) +{ + assert(mController); + return (mController->hookSystemDeregisterSink(sinkID)); +} + +am_Error_e CAmControlSender::hookSystemRegisterSource(const am_Source_s & sourceData, am_sourceID_t & sourceID) +{ + assert(mController); + return (mController->hookSystemRegisterSource(sourceData, sourceID)); +} + +am_Error_e CAmControlSender::hookSystemDeregisterSource(const am_sourceID_t sourceID) +{ + assert(mController); + return (mController->hookSystemDeregisterSource(sourceID)); +} + +am_Error_e CAmControlSender::hookSystemRegisterGateway(const am_Gateway_s & gatewayData, am_gatewayID_t & gatewayID) +{ + assert(mController); + 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); + return (mController->hookSystemRegisterCrossfader(crossfaderData, crossfaderID)); +} + +am_Error_e CAmControlSender::hookSystemDeregisterCrossfader(const am_crossfaderID_t crossfaderID) +{ + assert(mController); + return (mController->hookSystemDeregisterCrossfader(crossfaderID)); +} + +void CAmControlSender::hookSystemSinkVolumeTick(const am_Handle_s handle, const am_sinkID_t sinkID, const am_volume_t volume) +{ + assert(mController); + mController->hookSystemSinkVolumeTick(handle, sinkID, volume); +} + +void CAmControlSender::hookSystemSourceVolumeTick(const am_Handle_s handle, const am_sourceID_t sourceID, const am_volume_t volume) +{ + assert(mController); + mController->hookSystemSourceVolumeTick(handle, sourceID, volume); +} + +void CAmControlSender::hookSystemInterruptStateChange(const am_sourceID_t sourceID, const am_InterruptState_e interruptState) +{ + assert(mController); + mController->hookSystemInterruptStateChange(sourceID, interruptState); +} + +void CAmControlSender::hookSystemSinkAvailablityStateChange(const am_sinkID_t sinkID, const am_Availability_s & availability) +{ + assert(mController); + mController->hookSystemSinkAvailablityStateChange(sinkID, availability); +} + +void CAmControlSender::hookSystemSourceAvailablityStateChange(const am_sourceID_t sourceID, const am_Availability_s & availability) +{ + assert(mController); + mController->hookSystemSourceAvailablityStateChange(sourceID, availability); +} + +void CAmControlSender::hookSystemDomainStateChange(const am_domainID_t domainID, const am_DomainState_e state) +{ + assert(mController); + mController->hookSystemDomainStateChange(domainID, state); +} + +void CAmControlSender::hookSystemReceiveEarlyData(const std::vector<am_EarlyData_s> & data) +{ + assert(mController); + mController->hookSystemReceiveEarlyData(data); +} + +void CAmControlSender::hookSystemSpeedChange(const am_speed_t speed) +{ + assert(mController); + mController->hookSystemSpeedChange(speed); +} + +void CAmControlSender::hookSystemTimingInformationChanged(const am_mainConnectionID_t mainConnectionID, const am_timeSync_t time) +{ + assert(mController); + mController->hookSystemTimingInformationChanged(mainConnectionID, time); +} + +void CAmControlSender::cbAckConnect(const am_Handle_s handle, const am_Error_e errorID) +{ + assert(mController); + mController->cbAckConnect(handle, errorID); +} + +void CAmControlSender::cbAckDisconnect(const am_Handle_s handle, const am_Error_e errorID) +{ + assert(mController); + mController->cbAckDisconnect(handle, errorID); +} + +void CAmControlSender::cbAckCrossFade(const am_Handle_s handle, const am_HotSink_e hostsink, const am_Error_e error) +{ + assert(mController); + mController->cbAckCrossFade(handle, hostsink, error); +} + +void CAmControlSender::cbAckSetSinkVolumeChange(const am_Handle_s handle, const am_volume_t volume, const am_Error_e error) +{ + assert(mController); + mController->cbAckSetSinkVolumeChange(handle, volume, error); +} + +void CAmControlSender::cbAckSetSourceVolumeChange(const am_Handle_s handle, const am_volume_t volume, const am_Error_e error) +{ + assert(mController); + mController->cbAckSetSourceVolumeChange(handle, volume, error); +} + +void CAmControlSender::cbAckSetSourceState(const am_Handle_s handle, const am_Error_e error) +{ + assert(mController); + mController->cbAckSetSourceState(handle, error); +} + +void CAmControlSender::cbAckSetSourceSoundProperty(const am_Handle_s handle, const am_Error_e error) +{ + assert(mController); + mController->cbAckSetSourceSoundProperty(handle, error); +} + +am_Error_e CAmControlSender::startupController(IAmControlReceive *controlreceiveinterface) +{ + if (!mController) + { + logError("ControlSender::startupController: no Controller to startup!"); + throw std::runtime_error("ControlSender::startupController: no Controller to startup! Exiting now ..."); + return (E_NON_EXISTENT); + } + return (mController->startupController(controlreceiveinterface)); +} + +void CAmControlSender::cbAckSetSinkSoundProperty(const am_Handle_s handle, const am_Error_e error) +{ + assert(mController); + mController->cbAckSetSinkSoundProperty(handle, error); +} + +void CAmControlSender::cbAckSetSinkSoundProperties(const am_Handle_s handle, const am_Error_e error) +{ + assert(mController); + mController->cbAckSetSinkSoundProperties(handle, error); +} + +void CAmControlSender::cbAckSetSourceSoundProperties(const am_Handle_s handle, const am_Error_e error) +{ + assert(mController); + mController->cbAckSetSourceSoundProperties(handle, error); +} + +void CAmControlSender::setControllerReady() +{ + assert(mController); + mController->setControllerReady(); +} + +void CAmControlSender::setControllerRundown(const int16_t signal) +{ + assert(mController); + logInfo("CAmControlSender::setControllerRundown received, signal=",signal); + mController->setControllerRundown(signal); +} + +am_Error_e am::CAmControlSender::getConnectionFormatChoice(const am_sourceID_t sourceID, const am_sinkID_t sinkID, const am_Route_s listRoute, const std::vector<am_CustomConnectionFormat_t> listPossibleConnectionFormats, std::vector<am_CustomConnectionFormat_t> & listPrioConnectionFormats) +{ + assert(mController); + return (mController->getConnectionFormatChoice(sourceID, sinkID, listRoute, listPossibleConnectionFormats, listPrioConnectionFormats)); +} + +void CAmControlSender::getInterfaceVersion(std::string & version) const +{ + version = ControlVersion; +} + +void CAmControlSender::confirmCommandReady(const am_Error_e error) +{ + assert(mController); + mController->confirmCommandReady(error); +} + +void CAmControlSender::confirmRoutingReady(const am_Error_e error) +{ + assert(mController); + mController->confirmRoutingReady(error); +} + +void CAmControlSender::confirmCommandRundown(const am_Error_e error) +{ + assert(mController); + mController->confirmCommandRundown(error); +} + +void CAmControlSender::confirmRoutingRundown(const am_Error_e error) +{ + assert(mController); + mController->confirmRoutingRundown(error); +} + +am_Error_e CAmControlSender::hookSystemUpdateSink(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) +{ + assert(mController); + return (mController->hookSystemUpdateSink(sinkID,sinkClassID,listSoundProperties,listConnectionFormats,listMainSoundProperties)); +} + +am_Error_e CAmControlSender::hookSystemUpdateSource(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_SoundProperty_s>& listSoundProperties, const std::vector<am_CustomConnectionFormat_t>& listConnectionFormats, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties) +{ + assert(mController); + return (mController->hookSystemUpdateSource(sourceID,sourceClassID,listSoundProperties,listConnectionFormats,listMainSoundProperties)); +} + +am_Error_e CAmControlSender::hookSystemUpdateGateway(const am_gatewayID_t gatewayID, const std::vector<am_CustomConnectionFormat_t>& listSourceConnectionFormats, const std::vector<am_CustomConnectionFormat_t>& listSinkConnectionFromats, const std::vector<bool>& convertionMatrix) +{ + assert(mController); + 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); + mController->cbAckSetVolumes(handle,listVolumes,error); +} + +void CAmControlSender::cbAckSetSinkNotificationConfiguration(const am_Handle_s handle, const am_Error_e error) +{ + assert(mController); + mController->cbAckSetSinkNotificationConfiguration(handle,error); +} + +void CAmControlSender::cbAckSetSourceNotificationConfiguration(const am_Handle_s handle, const am_Error_e error) +{ + assert(mController); + mController->cbAckSetSourceNotificationConfiguration(handle,error); +} + +void CAmControlSender::hookSinkNotificationDataChanged(const am_sinkID_t sinkID, const am_NotificationPayload_s& payload) +{ + assert(mController); + mController->hookSinkNotificationDataChanged(sinkID,payload); +} + +void CAmControlSender::hookSourceNotificationDataChanged(const am_sourceID_t sourceID, const am_NotificationPayload_s& payload) +{ + assert(mController); + mController->hookSourceNotificationDataChanged(sourceID,payload); +} + +am_Error_e CAmControlSender::hookUserSetMainSinkNotificationConfiguration(const am_sinkID_t sinkID, const am_NotificationConfiguration_s& notificationConfiguration) +{ + assert(mController); + return (mController->hookUserSetMainSinkNotificationConfiguration(sinkID,notificationConfiguration)); +} + +am_Error_e CAmControlSender::hookUserSetMainSourceNotificationConfiguration(const am_sourceID_t sourceID, const am_NotificationConfiguration_s& notificationConfiguration) +{ + assert(mController); + return (mController->hookUserSetMainSourceNotificationConfiguration(sourceID,notificationConfiguration)); +} + +void CAmControlSender::receiverCallback(const pollfd pollfd, const sh_pollHandle_t handle, void* userData) +{ + (void) handle; + (void) userData; + //get the signal number from the socket + ssize_t result = read(pollfd.fd, &mSignal, sizeof(mSignal)); +} + +bool CAmControlSender::checkerCallback(const sh_pollHandle_t handle, void* userData) +{ + (void) handle; + (void) userData; + return (true); +} + +void CAmControlSender::hookSystemSingleTimingInformationChanged(const am_connectionID_t connectionID, const am_timeSync_t time) +{ + assert(mController); + mController->hookSystemSingleTimingInformationChanged(connectionID,time); +} + +/**for testing only contructor - do not use ! + * + */ +CAmControlSender::CAmControlSender() : + receiverCallbackT(this, &CAmControlSender::receiverCallback),// + checkerCallbackT(this, &CAmControlSender::checkerCallback),// + dispatcherCallbackT(this, &CAmControlSender::dispatcherCallback), // + mPipe(), // + mlibHandle(NULL), // + mController(NULL), // + mSignal(0) +{ + logInfo("CAmControlSender was loaded in test mode!"); +} + +bool CAmControlSender::dispatcherCallback(const sh_pollHandle_t handle, void* userData) +{ + (void)handle; + (void)userData; + setControllerRundown(mSignal); + return (false); +} + +} + + diff --git a/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp b/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp new file mode 100644 index 0000000..929c8d5 --- /dev/null +++ b/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp @@ -0,0 +1,3079 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2012, BMW AG + * + * This file is part of GENIVI Project AudioManager. + * + * Contributions are licensed to the GENIVI Alliance under one or more + * Contribution License Agreements. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Aleksandar Donchev, aleksander.donchev@partner.bmw.de BMW 2013 + * + * \file CAmDatabaseHandlerMap.cpp + * For further information see http://www.genivi.org/. + * + */ + +#include <iostream> +#include <cassert> +#include <stdexcept> +#include <vector> +#include <fstream> +#include <sstream> +#include <string> +#include <limits> +#include "CAmDatabaseHandlerMap.h" +#include "CAmDatabaseObserver.h" +#include "CAmRouter.h" +#include "CAmDltWrapper.h" + + +#ifdef WITH_DATABASE_CHANGE_CHECK +# define DB_COND_UPDATE_RIE(x,y) \ + if (isDataEqual(x,y)) return (E_NO_CHANGE); else x = y +# define DB_COND_UPDATE_INIT \ + bool modified = false +# define DB_COND_UPDATE(x,y) \ + if (!isDataEqual(x,y)) { x = y; modified = true; } +# define DB_COND_ISMODIFIED \ + (modified == true) +#else +# define DB_COND_UPDATE_RIE(x,y) \ + x = y +# define DB_COND_UPDATE_INIT +# define DB_COND_UPDATE(x,y) \ + x = y +# define DB_COND_ISMODIFIED \ + (true) +#endif + + +namespace am +{ + +/* + * Checks if content of data is equal + */ +template <typename T> bool isDataEqual(const T & left, const T & right) +{ + return static_cast<bool>(!std::memcmp(&left, &right, sizeof(T))); +} + +template <typename T, typename L = std::vector<T> > bool isDataEqual(const L & left, const L & right) +{ + return std::equal(left.begin(), left.end(), right.begin(), isDataEqual); +} + + +/* + * Returns an object for given key + */ +template <typename TMapKeyType, class TMapObjectType> TMapObjectType const * objectForKeyIfExistsInMap(const TMapKeyType & key, const std::unordered_map<TMapKeyType,TMapObjectType> & map) +{ + typename std::unordered_map<TMapKeyType,TMapObjectType>::const_iterator iter = map.find(key); + if( iter!=map.end() ) + return &iter->second; + return NULL; +} + +/* + * Checks whether any object with key exists in a given map + */ +template <typename TMapKeyType, class TMapObjectType> bool existsObjectWithKeyInMap(const TMapKeyType & key, const std::unordered_map<TMapKeyType,TMapObjectType> & map) +{ + return objectForKeyIfExistsInMap(key, map)!=NULL; +} + +/** + * \brief Returns an object matching predicate. + * + * Convenient method for searching in a given map. + * + * @param map Map reference. + * @param comparator Search predicate. + * @return NULL or pointer to the found object. + */ +template <class TReturn, typename TIdentifier> const TReturn * objectMatchingPredicate(const std::unordered_map<TIdentifier, TReturn> & map, + std::function<bool(const TReturn & refObject)> comparator) +{ + typename std::unordered_map<TIdentifier, TReturn>::const_iterator elementIterator = map.begin(); + for (;elementIterator != map.end(); ++elementIterator) + { + if( comparator(elementIterator->second) ) + return &elementIterator->second; + } + return NULL; +} + + +/* Domain */ + +void CAmDatabaseHandlerMap::CAmDomain::getDescription (std::string & outString) const +{ + std::ostringstream fmt; + fmt << "Domain(" << name.c_str() << ") id(" << domainID << ")" << std::endl << + "bus name(" << busname.c_str() << + ") node name(" << nodename.c_str() << + ") early(" << early << + ") domainID(" << domainID << + ") complete(" << complete << + ") state(" << state << + ") reserved(" << reserved << ")" << std::endl; + outString = fmt.str(); +} + +/* Source */ + +void CAmDatabaseHandlerMap::CAmSource::getSourceType(am_SourceType_s & sourceType) const +{ + sourceType.name = name; + sourceType.sourceClassID = sourceClassID; + sourceType.availability = available; + sourceType.sourceID = sourceID; +} + +void CAmDatabaseHandlerMap::CAmSource::getDescription (std::string & outString) const +{ + std::ostringstream fmt; + fmt << "Source(" << name.c_str() << ") id(" << sourceID << ")" << std::endl << + "sourceClassID(" << sourceClassID << + ") domainID(" << domainID << + ") visible(" << visible << + ") volume(" << volume << + ") interruptState(" << interruptState << + ") sourceState(" << sourceState << + ") reserved(" << reserved << ")" << + ") available([availability:" << available.availability << " availabilityReason:" << available.availabilityReason << "]" + ") listSoundProperties ("; + std::for_each(listSoundProperties.begin(), listSoundProperties.end(), [&](const am_SoundProperty_s & ref) { + fmt << "[type:" << ref.type << " value:" << ref.value <<"]"; + }); + fmt << ") listConnectionFormats ("; + std::for_each(listConnectionFormats.begin(), listConnectionFormats.end(), [&](const am_CustomConnectionFormat_t & ref) { + fmt << "[" << ref << "]"; + }); + fmt << ") listMainSoundProperties ("; + std::for_each(listMainSoundProperties.begin(), listMainSoundProperties.end(), [&](const am_MainSoundProperty_s & ref) { + fmt << "[type:" << ref.type << " value:" << ref.value <<"]"; + }); + fmt << ") listMainNotificationConfigurations ("; + std::for_each(listMainNotificationConfigurations.begin(), listMainNotificationConfigurations.end(), [&](const am_NotificationConfiguration_s & ref) { + fmt << "[type:" << ref.type << " status:" << ref.status << " parameter:" << ref.parameter <<"]"; + }); + fmt << ") listNotificationConfigurations ("; + std::for_each(listNotificationConfigurations.begin(), listNotificationConfigurations.end(), [&](const am_NotificationConfiguration_s & ref) { + fmt << "[type:" << ref.type << " status:" << ref.status << " parameter:" << ref.parameter <<"]"; + }); + fmt << ")" << std::endl; + outString = fmt.str(); +} + +/* Sink */ + +void CAmDatabaseHandlerMap::CAmSink::getDescription (std::string & outString) const +{ + std::ostringstream fmt; + fmt << "Sink(" << name.c_str() << ") id(" << sinkID << ")" << std::endl << + "sinkClassID(" << sinkClassID << + ") domainID(" << domainID << + ") visible(" << visible << + ") volume(" << volume << + ") muteState(" << muteState << + ") mainVolume(" << mainVolume << + ") reserved(" << reserved << ")" << + ") available([availability:" << available.availability << " availabilityReason:" << available.availabilityReason << "]" + ") listSoundProperties ("; + std::for_each(listSoundProperties.begin(), listSoundProperties.end(), [&](const am_SoundProperty_s & ref) { + fmt << "[type:" << ref.type << " value:" << ref.value <<"]"; + }); + fmt << ") listConnectionFormats ("; + std::for_each(listConnectionFormats.begin(), listConnectionFormats.end(), [&](const am_CustomConnectionFormat_t & ref) { + fmt << "[" << ref << "]"; + }); + fmt << ") listMainSoundProperties ("; + std::for_each(listMainSoundProperties.begin(), listMainSoundProperties.end(), [&](const am_MainSoundProperty_s & ref) { + fmt << "[type:" << ref.type << " value:" << ref.value <<"]"; + }); + fmt << ") listMainNotificationConfigurations ("; + std::for_each(listMainNotificationConfigurations.begin(), listMainNotificationConfigurations.end(), [&](const am_NotificationConfiguration_s & ref) { + fmt << "[type:" << ref.type << " status:" << ref.status << " parameter:" << ref.parameter <<"]"; + }); + fmt << ") listNotificationConfigurations ("; + std::for_each(listNotificationConfigurations.begin(), listNotificationConfigurations.end(), [&](const am_NotificationConfiguration_s & ref) { + fmt << "[type:" << ref.type << " status:" << ref.status << " parameter:" << ref.parameter <<"]"; + }); + fmt << ")" << std::endl; + outString = fmt.str(); +} + +void CAmDatabaseHandlerMap::CAmSink::getSinkType(am_SinkType_s & sinkType) const +{ + sinkType.name = name; + sinkType.sinkID = sinkID; + sinkType.availability = available; + sinkType.muteState = muteState; + sinkType.volume = mainVolume; + sinkType.sinkClassID = sinkClassID; +} + +/* Connection */ + +void CAmDatabaseHandlerMap::CAmConnection::getDescription (std::string & outString) const +{ + std::ostringstream fmt; + fmt << "Connection id(" << connectionID << ") " << std::endl << + "sourceID(" << sourceID << + ") sinkID(" << sinkID << + ") delay(" << delay << + ") connectionFormat(" << connectionFormat << + ") reserved(" << reserved << ")" << std::endl; + outString = fmt.str(); +} + +/* Main Connection */ + +void CAmDatabaseHandlerMap::CAmMainConnection::getDescription (std::string & outString) const +{ + std::ostringstream fmt; + fmt << "MainConnection id(" << mainConnectionID << ") " << std::endl << + "connectionState(" << connectionState << + ") sinkID(" << sinkID << + ") sourceID(" << sourceID << + ") delay(" << delay << + ") listConnectionID ("; + std::for_each(listConnectionID.begin(), listConnectionID.end(), [&](const am_connectionID_t & connID) { + fmt << "["<< connID << "]"; + }); + fmt << ")" << std::endl; + outString = fmt.str(); +} + +void CAmDatabaseHandlerMap::am_MainConnection_Database_s::getMainConnectionType(am_MainConnectionType_s & connectionType) const +{ + connectionType.mainConnectionID = mainConnectionID; + connectionType.sourceID = sourceID; + connectionType.sinkID = sinkID; + connectionType.connectionState = connectionState; + connectionType.delay = delay; +} + +/* Source Class */ + +void CAmDatabaseHandlerMap::CAmSourceClass::getDescription (std::string & outString) const +{ + std::ostringstream fmt; + fmt << "Source class(" << name.c_str() << ") id(" << sourceClassID << ")\n" << + ") listClassProperties ("; + std::for_each(listClassProperties.begin(), listClassProperties.end(), [&](const am_ClassProperty_s & ref) { + fmt << "[classProperty:" << ref.classProperty << " value:" << ref.value << "]"; + }); + fmt << ")" << std::endl; + outString = fmt.str(); +} + +/* Sink Class */ + +void CAmDatabaseHandlerMap::CAmSinkClass::getDescription (std::string & outString) const +{ + std::ostringstream fmt; + fmt << "Sink class(" << name.c_str() << ") id(" << sinkClassID << ")\n" << + ") listClassProperties ("; + std::for_each(listClassProperties.begin(), listClassProperties.end(), [&](const am_ClassProperty_s & ref) { + fmt << "[classProperty:" << ref.classProperty << " value:" << ref.value << "]"; + }); + fmt << ")" << std::endl; + outString = fmt.str(); +} + + +/* Gateway */ + +void CAmDatabaseHandlerMap::CAmGateway::getDescription (std::string & outString) const +{ + std::ostringstream fmt; + fmt << "Gateway(" << name.c_str() << ") id(" << gatewayID << ")\n" << + "sinkID(" << sinkID << + ") sourceID(" << sourceID << + ") domainSinkID(" << domainSinkID << + ") domainSourceID(" << domainSourceID << + ") controlDomainID(" << controlDomainID << + ") listSourceFormats ("; + std::for_each(listSourceFormats.begin(), listSourceFormats.end(), [&](const am_CustomConnectionFormat_t & ref) { + fmt << "[" << ref << "]"; + }); + fmt << ") listSinkFormats ("; + std::for_each(listSinkFormats.begin(), listSinkFormats.end(), [&](const am_CustomConnectionFormat_t & ref) { + fmt << "[" << ref << "]"; + }); + fmt << ") convertionMatrix ("; + std::for_each(convertionMatrix.begin(), convertionMatrix.end(), [&](const bool & ref) { + fmt << "[" << ref << "]"; + }); + fmt << ")" << std::endl; + outString = fmt.str(); +} + +/* Crossfader */ + +void CAmDatabaseHandlerMap::CAmCrossfader::getDescription (std::string & outString) const +{ + std::ostringstream fmt; + fmt << "Crossfader(" << name.c_str() << ") id(" << crossfaderID << ")\n" << + "sinkID_A(" << sinkID_A << + ") sinkID_B(" << sinkID_B << + ") sourceID(" << sourceID << + ") hotSink(" << hotSink << + ")" << std::endl; + outString = fmt.str(); +} + +bool CAmDatabaseHandlerMap::CAmMappedData::increaseID(int16_t & resultID, am_Identifier_s & sourceID, + int16_t const desiredStaticID = 0) +{ + if( desiredStaticID > 0 && desiredStaticID < sourceID.mMin ) + { + resultID = desiredStaticID; + return true; + } + else if( sourceID.mCurrentValue < sourceID.mMax ) //The last used value is 'limit' - 1. e.g. SHRT_MAX - 1, SHRT_MAX is reserved. + { + resultID = sourceID.mCurrentValue++; + return true; + } + else + { + resultID = -1; + return false; + } + } + +template <typename TMapKey,class TMapObject> bool CAmDatabaseHandlerMap::CAmMappedData::getNextConnectionID(int16_t & resultID, am_Identifier_s & sourceID, + const std::unordered_map<TMapKey, TMapObject> & map) +{ + TMapKey nextID; + int16_t const lastID = sourceID.mCurrentValue; + if( sourceID.mCurrentValue < sourceID.mMax ) + nextID = sourceID.mCurrentValue++; + else + nextID = sourceID.mCurrentValue = sourceID.mMin; + + bool notFreeIDs = false; + while( existsObjectWithKeyInMap(nextID, map) ) + { + + if( sourceID.mCurrentValue < sourceID.mMax ) + nextID = sourceID.mCurrentValue++; + else + { + sourceID.mCurrentValue = sourceID.mMin; + nextID = sourceID.mCurrentValue++; + } + + if( sourceID.mCurrentValue == lastID ) + { + notFreeIDs = true; + break; + } + } + if(notFreeIDs) + { + resultID = -1; + return false; + } + resultID = nextID; + return true; +} + +bool CAmDatabaseHandlerMap::CAmMappedData::increaseMainConnectionID(int16_t & resultID) +{ + return getNextConnectionID(resultID, mCurrentMainConnectionID, mMainConnectionMap); +} + +bool CAmDatabaseHandlerMap::CAmMappedData::increaseConnectionID(int16_t & resultID) +{ + return getNextConnectionID(resultID, mCurrentConnectionID, mConnectionMap); +} + + +CAmDatabaseHandlerMap::CAmDatabaseHandlerMap(): mFirstStaticSink(true), // + mFirstStaticSource(true), // + mFirstStaticGateway(true), // + mFirstStaticConverter(true), // + mFirstStaticSinkClass(true), // + mFirstStaticSourceClass(true), // + mFirstStaticCrossfader(true), // + mpDatabaseObserver(NULL), // + mListConnectionFormat(), // + mMappedData() +{ + logInfo(__PRETTY_FUNCTION__,"Init "); +} + +CAmDatabaseHandlerMap::~CAmDatabaseHandlerMap() +{ + logInfo(__PRETTY_FUNCTION__,"Destroy"); + mpDatabaseObserver = NULL; +} + +am_Error_e CAmDatabaseHandlerMap::enterDomainDB(const am_Domain_s & domainData, am_domainID_t & domainID) +{ + assert(!domainData.name.empty()); + assert(!domainData.busname.empty()); + assert(domainData.state>=DS_UNKNOWN && domainData.state<=DS_MAX); + //first check for a reserved domain + am_Domain_s const *reservedDomain = objectMatchingPredicate<CAmDomain, am_domainID_t>(mMappedData.mDomainMap, [&](const CAmDomain & obj){ + return domainData.name.compare(obj.name)==0; + }); + + int16_t nextID = 0; + + if( NULL != reservedDomain ) + { + nextID = reservedDomain->domainID; + domainID = nextID; + mMappedData.mDomainMap[nextID] = domainData; + mMappedData.mDomainMap[nextID].domainID = nextID; + mMappedData.mDomainMap[nextID].reserved = 0; + logInfo("DatabaseHandler::enterDomainDB entered reserved domain with name=", domainData.name, "busname=", domainData.busname, "nodename=", domainData.nodename, "reserved ID:", domainID); + if (mpDatabaseObserver) + mpDatabaseObserver->newDomain(mMappedData.mDomainMap[nextID]); + return (E_OK); + } + else + { + if(mMappedData.increaseID(nextID, mMappedData.mCurrentDomainID, domainData.domainID)) + { + domainID = nextID; + mMappedData.mDomainMap[nextID] = domainData; + mMappedData.mDomainMap[nextID].domainID = nextID; + logInfo("DatabaseHandler::enterDomainDB entered new domain with name=", domainData.name, "busname=", domainData.busname, "nodename=", domainData.nodename, "assigned ID:", domainID); + if (mpDatabaseObserver) + mpDatabaseObserver->newDomain(mMappedData.mDomainMap[nextID]); + return (E_OK); + } + else + { + domainID = 0; + logInfo(__PRETTY_FUNCTION__,"Max limit reached."); + return (E_UNKNOWN); + } + } +} + +int16_t CAmDatabaseHandlerMap::calculateDelayForRoute(const std::vector<am_connectionID_t>& listConnectionID) +{ + int16_t delay = 0; + std::vector<am_connectionID_t>::const_iterator elementIterator = listConnectionID.begin(); + for (; elementIterator < listConnectionID.end(); ++elementIterator) + { + am_connectionID_t key = *elementIterator; + std::unordered_map<am_connectionID_t, am_Connection_Database_s>::const_iterator it = mMappedData.mConnectionMap.find(key); + if (it!=mMappedData.mConnectionMap.end()) + { + int16_t temp_delay = it->second.delay; + if (temp_delay != -1 && delay != -1) + delay += temp_delay; + else + delay = -1; + } + } + return delay; +} + +am_Error_e CAmDatabaseHandlerMap::enterMainConnectionDB(const am_MainConnection_s & mainConnectionData, am_mainConnectionID_t & connectionID) +{ + assert(mainConnectionData.mainConnectionID==0); + assert(mainConnectionData.connectionState>=CS_UNKNOWN && mainConnectionData.connectionState<=CS_MAX); + assert(mainConnectionData.sinkID!=0); + assert(mainConnectionData.sourceID!=0); + + int16_t delay = 0; + int16_t nextID = 0; + if(mMappedData.increaseMainConnectionID(nextID)) + { + connectionID = nextID; + mMappedData.mMainConnectionMap[nextID] = mainConnectionData; + mMappedData.mMainConnectionMap[nextID].mainConnectionID = nextID; + } + else + { + connectionID = 0; + logInfo(__PRETTY_FUNCTION__,"Max limit reached."); + return (E_UNKNOWN); + } + + //now check the connectionTable for all connections in the route. IF connectionID exist + delay = calculateDelayForRoute(mainConnectionData.listConnectionID); + logInfo("DatabaseHandler::enterMainConnectionDB entered new mainConnection with sourceID", mainConnectionData.sourceID, "sinkID:", mainConnectionData.sinkID, "delay:", delay, "assigned ID:", connectionID); + + if (mpDatabaseObserver) + { + am_MainConnectionType_s mainConnection; + mMappedData.mMainConnectionMap[nextID].getMainConnectionType(mainConnection); + mpDatabaseObserver->newMainConnection(mainConnection); + mpDatabaseObserver->mainConnectionStateChanged(connectionID, mMappedData.mMainConnectionMap[nextID].connectionState); + } + + //finally, we update the delay value for the maintable + if (delay == 0) + delay = -1; + (void)changeDelayMainConnection(delay, connectionID); + + return (E_OK); +} + +/** + * Helper method, that inserts a new struct in the map and copies the given into it. + * This method uses the increaseID function to secure the global id is properly increased. + **/ +bool CAmDatabaseHandlerMap::insertSinkDB(const am_Sink_s & sinkData, am_sinkID_t & sinkID) +{ + int16_t nextID = 0; + if( mMappedData.increaseID(nextID, mMappedData.mCurrentSinkID, sinkData.sinkID) ) + { + sinkID = nextID; + mMappedData.mSinkMap[nextID] = sinkData; + mMappedData.mSinkMap[nextID].sinkID = nextID; + filterDuplicateNotificationConfigurationTypes(mMappedData.mSinkMap[nextID].listNotificationConfigurations); + filterDuplicateNotificationConfigurationTypes(mMappedData.mSinkMap[nextID].listMainNotificationConfigurations); + return (true); + } + else + { + sinkID = 0; + logInfo(__PRETTY_FUNCTION__,"Max limit reached!"); + return (false); + } +} + +am_Error_e CAmDatabaseHandlerMap::enterSinkDB(const am_Sink_s & sinkData, am_sinkID_t & sinkID) +{ + assert(sinkData.sinkID<DYNAMIC_ID_BOUNDARY); + assert(sinkData.domainID!=0); + assert(!sinkData.name.empty()); + assert(sinkData.sinkClassID!=0); + assert(sinkData.muteState>=MS_UNKNOWN && sinkData.muteState<=MS_MAX); + + am_sinkID_t temp_SinkID = 0; + am_sinkID_t temp_SinkIndex = 0; + //if sinkID is zero and the first Static Sink was already entered, the ID is created + am_Sink_s const *reservedDomain = objectMatchingPredicate<CAmSink, am_sinkID_t>(mMappedData.mSinkMap, [&](const CAmSink & obj){ + return true==obj.reserved && obj.name.compare(sinkData.name)==0; + }); + if( NULL!=reservedDomain ) + { + am_sinkID_t oldSinkID = reservedDomain->sinkID; + mMappedData.mSinkMap[oldSinkID] = sinkData; + mMappedData.mSinkMap[oldSinkID].reserved = 0; + temp_SinkID = oldSinkID; + temp_SinkIndex = oldSinkID; + } + else + { + bool result; + if ( sinkData.sinkID != 0 || mFirstStaticSink ) + { + //check if the ID already exists + if (existSinkNameOrID(sinkData.sinkID, sinkData.name)) + { + sinkID = sinkData.sinkID; + return (E_ALREADY_EXISTS); + } + } + result = insertSinkDB(sinkData, temp_SinkID); + if( false == result ) + return (E_UNKNOWN); + temp_SinkIndex = temp_SinkID; + } + //if the first static sink is entered, we need to set it onto the boundary + if (sinkData.sinkID == 0 && mFirstStaticSink) + { + mFirstStaticSink = false; + } + mMappedData.mSinkMap[temp_SinkIndex].sinkID = temp_SinkID; + sinkID = temp_SinkID; + + am_Sink_s & sink = mMappedData.mSinkMap[temp_SinkID]; + logInfo("DatabaseHandler::enterSinkDB entered new sink with name", sink.name, "domainID:", sink.domainID, "classID:", sink.sinkClassID, "volume:", sink.volume, "assigned ID:", sink.sinkID); + + if (mpDatabaseObserver != NULL) + { + sink.sinkID=sinkID; + mpDatabaseObserver->newSink(sink); + } + return (E_OK); +} + +bool CAmDatabaseHandlerMap::insertCrossfaderDB(const am_Crossfader_s & crossfaderData, am_crossfaderID_t & crossfaderID) +{ + int16_t nextID = 0; + if(mMappedData.increaseID(nextID, mMappedData.mCurrentCrossfaderID, crossfaderData.crossfaderID)) + { + crossfaderID = nextID; + mMappedData.mCrossfaderMap[nextID] = crossfaderData; + mMappedData.mCrossfaderMap[nextID].crossfaderID = nextID; + return (true); + } + else + { + crossfaderID = 0; + logInfo(__PRETTY_FUNCTION__,"Max limit reached."); + return (false); + } +} + +am_Error_e CAmDatabaseHandlerMap::enterCrossfaderDB(const am_Crossfader_s & crossfaderData, am_crossfaderID_t & crossfaderID) +{ + assert(crossfaderData.crossfaderID<DYNAMIC_ID_BOUNDARY); + assert(crossfaderData.hotSink>=HS_UNKNOWN && crossfaderData.hotSink<=HS_MAX); + assert(!crossfaderData.name.empty()); + assert(existSink(crossfaderData.sinkID_A)); + assert(existSink(crossfaderData.sinkID_B)); + assert(existSource(crossfaderData.sourceID)); + + am_crossfaderID_t temp_CrossfaderID = 0; + am_crossfaderID_t temp_CrossfaderIndex = 0; + + bool result; + //if gatewayData is zero and the first Static Sink was already entered, the ID is created + if (crossfaderData.crossfaderID != 0 || mFirstStaticCrossfader) + { + //check if the ID already exists + if (existCrossFader(crossfaderData.crossfaderID)) + { + crossfaderID = crossfaderData.crossfaderID; + return (E_ALREADY_EXISTS); + } + } + result = insertCrossfaderDB(crossfaderData, temp_CrossfaderID); + if( false == result ) + return (E_UNKNOWN); + temp_CrossfaderIndex = temp_CrossfaderID; + + //if the first static sink is entered, we need to set it onto the boundary + if ( 0==crossfaderData.crossfaderID && mFirstStaticCrossfader) + { + mFirstStaticCrossfader = false; + } + + mMappedData.mCrossfaderMap[temp_CrossfaderIndex].crossfaderID = temp_CrossfaderID; + crossfaderID = temp_CrossfaderID; + logInfo("DatabaseHandler::enterCrossfaderDB entered new crossfader with name=", crossfaderData.name, "sinkA= ", crossfaderData.sinkID_A, "sinkB=", crossfaderData.sinkID_B, "source=", crossfaderData.sourceID, "assigned ID:", crossfaderID); + + if (mpDatabaseObserver) + mpDatabaseObserver->newCrossfader(mMappedData.mCrossfaderMap[temp_CrossfaderIndex]); + return (E_OK); +} + +bool CAmDatabaseHandlerMap::insertGatewayDB(const am_Gateway_s & gatewayData, am_gatewayID_t & gatewayID) +{ + int16_t nextID = 0; + if(mMappedData.increaseID(nextID, mMappedData.mCurrentGatewayID, gatewayData.gatewayID)) + { + gatewayID = nextID; + mMappedData.mGatewayMap[nextID] = gatewayData; + mMappedData.mGatewayMap[nextID].gatewayID = nextID; + return (true); + } + else + { + gatewayID = 0; + logInfo(__PRETTY_FUNCTION__,"Max limit reached."); + return (false); + } +} + +am_Error_e CAmDatabaseHandlerMap::enterGatewayDB(const am_Gateway_s & gatewayData, am_gatewayID_t & gatewayID) +{ + assert(gatewayData.gatewayID<DYNAMIC_ID_BOUNDARY); + assert(gatewayData.sinkID!=0); + assert(gatewayData.sourceID!=0); + assert(gatewayData.controlDomainID!=0); + assert(gatewayData.domainSinkID!=0); + assert(gatewayData.domainSourceID!=0); + assert(!gatewayData.name.empty()); + + //might be that the sinks and sources are not there during registration time + //assert(existSink(gatewayData.sinkID)); + //assert(existSource(gatewayData.sourceID)); + + am_gatewayID_t temp_GatewayID = 0; + am_gatewayID_t temp_GatewayIndex = 0; + //if gatewayData is zero and the first Static Sink was already entered, the ID is created + bool result; + if (gatewayData.gatewayID != 0 || mFirstStaticGateway) + { + //check if the ID already exists + if (existGateway(gatewayData.gatewayID)) + { + gatewayID = gatewayData.gatewayID; + return (E_ALREADY_EXISTS); + } + } + result = insertGatewayDB(gatewayData, temp_GatewayID); + if( false == result ) + return (E_UNKNOWN); + + temp_GatewayIndex = temp_GatewayID; + //if the ID is not created, we add it to the query + if (gatewayData.gatewayID == 0 && mFirstStaticGateway) + { + mFirstStaticGateway = false; + } + mMappedData.mGatewayMap[temp_GatewayIndex].gatewayID = temp_GatewayID; + gatewayID = temp_GatewayID; + + logInfo("DatabaseHandler::enterGatewayDB entered new gateway with name", gatewayData.name, "sourceID:", gatewayData.sourceID, "sinkID:", gatewayData.sinkID, "assigned ID:", gatewayID); + if (mpDatabaseObserver) + mpDatabaseObserver->newGateway(mMappedData.mGatewayMap[temp_GatewayIndex]); + 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()); + + //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 (existConverter(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; + CAmMappedData::printMap(mMappedData.mDomainMap, output); + CAmMappedData::printMap(mMappedData.mSourceMap, output); + CAmMappedData::printMap(mMappedData.mSinkMap, output); + CAmMappedData::printMap(mMappedData.mSourceClassesMap, output); + CAmMappedData::printMap(mMappedData.mSinkClassesMap, output); + CAmMappedData::printMap(mMappedData.mConnectionMap, output); + CAmMappedData::printMap(mMappedData.mMainConnectionMap, output); + CAmMappedData::printMap(mMappedData.mCrossfaderMap, output); + CAmMappedData::printMap(mMappedData.mGatewayMap, output); + CAmVectorSystemProperties::const_iterator iter = mMappedData.mSystemProperties.begin(); + output << "System properties" << "\n"; + for(; iter!=mMappedData.mSystemProperties.end(); iter++) + output << "[type:" << iter->type << " value:" << iter->value << "]"; + output << std::endl << "****************** DUMP END ******************" << std::endl; +} + +bool CAmDatabaseHandlerMap::insertSourceDB(const am_Source_s & sourceData, am_sourceID_t & sourceID) +{ + int16_t nextID = 0; + if(mMappedData.increaseID(nextID, mMappedData.mCurrentSourceID, sourceData.sourceID)) + { + sourceID = nextID; + mMappedData.mSourceMap[nextID] = sourceData; + mMappedData.mSourceMap[nextID].sourceID = nextID; + filterDuplicateNotificationConfigurationTypes(mMappedData.mSourceMap[nextID].listNotificationConfigurations); + filterDuplicateNotificationConfigurationTypes(mMappedData.mSourceMap[nextID].listMainNotificationConfigurations); + return (true); + } + else + { + sourceID = 0; + logInfo(__PRETTY_FUNCTION__,"Max limit reached."); + return (false); + } +} + +am_Error_e CAmDatabaseHandlerMap::enterSourceDB(const am_Source_s & sourceData, am_sourceID_t & sourceID) +{ + assert(sourceData.sourceID<DYNAMIC_ID_BOUNDARY); + assert(sourceData.domainID!=0); + assert(!sourceData.name.empty()); + assert(sourceData.sourceClassID!=0); + assert(sourceData.sourceState>=SS_UNKNNOWN && sourceData.sourceState<=SS_MAX); + + bool isFirstStatic = sourceData.sourceID == 0 && mFirstStaticSource; + am_sourceID_t temp_SourceID = 0; + am_sourceID_t temp_SourceIndex = 0; + CAmSource const *reservedSource = objectMatchingPredicate<CAmSource, am_sourceID_t>(mMappedData.mSourceMap, [&](const CAmSource & obj){ + return true==obj.reserved && obj.name.compare(sourceData.name)==0; + }); + if( NULL != reservedSource ) + { + am_sourceID_t oldSourceID = reservedSource->sourceID; + mMappedData.mSourceMap[oldSourceID] = sourceData; + mMappedData.mSourceMap[oldSourceID].reserved = 0; + temp_SourceID = oldSourceID; + temp_SourceIndex = oldSourceID; + } + else + { + bool result; + if ( !isFirstStatic ) + { + //check if the ID already exists + if (existSourceNameOrID(sourceData.sourceID, sourceData.name)) + { + sourceID = sourceData.sourceID; + return (E_ALREADY_EXISTS); + } + } + result = insertSourceDB(sourceData, temp_SourceID); + if( false == result ) + return (E_UNKNOWN); + temp_SourceIndex = temp_SourceID; + } + + if ( isFirstStatic ) + { + //if the first static sink is entered, we need to set it onto the boundary if needed + mFirstStaticSource = false; + } + mMappedData.mSourceMap[temp_SourceIndex].sourceID = temp_SourceID; + sourceID = temp_SourceID; + + logInfo("DatabaseHandler::enterSourceDB entered new source with name", sourceData.name, "domainID:", sourceData.domainID, "classID:", sourceData.sourceClassID, "visible:", sourceData.visible, "assigned ID:", sourceID); + + if (mpDatabaseObserver) + mpDatabaseObserver->newSource(mMappedData.mSourceMap[temp_SourceIndex]); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::enterConnectionDB(const am_Connection_s& connection, am_connectionID_t& connectionID) +{ + assert(connection.connectionID==0); + assert(connection.sinkID!=0); + assert(connection.sourceID!=0); + //connection format is not checked, because it's project specific + int16_t nextID = 0; + if(mMappedData.increaseConnectionID(nextID)) + { + connectionID = nextID; + mMappedData.mConnectionMap[nextID] = connection; + mMappedData.mConnectionMap[nextID].connectionID = nextID; + mMappedData.mConnectionMap[nextID].reserved = true; + } + else + { + connectionID = 0; + logInfo(__PRETTY_FUNCTION__,"Max limit reached."); + return (E_UNKNOWN); + } + + logInfo("DatabaseHandler::enterConnectionDB entered new connection sourceID=", connection.sourceID, "sinkID=", connection.sinkID, "sourceID=", connection.sourceID, "connectionFormat=", connection.connectionFormat, "assigned ID=", connectionID); + return (E_OK); +} + +bool CAmDatabaseHandlerMap::insertSinkClassDB(const am_SinkClass_s & sinkClass, am_sinkClass_t & sinkClassID) +{ + int16_t nextID = 0; + if(mMappedData.increaseID(nextID, mMappedData.mCurrentSinkClassesID, sinkClass.sinkClassID)) + { + sinkClassID = nextID; + mMappedData.mSinkClassesMap[nextID] = sinkClass; + mMappedData.mSinkClassesMap[nextID].sinkClassID = nextID; + return (true); + } + else + { + sinkClassID = 0; + logInfo(__PRETTY_FUNCTION__,"Max limit reached."); + return (false); + } +} + +am_Error_e CAmDatabaseHandlerMap::enterSinkClassDB(const am_SinkClass_s & sinkClass, am_sinkClass_t & sinkClassID) +{ + assert(sinkClass.sinkClassID<DYNAMIC_ID_BOUNDARY); + assert(!sinkClass.name.empty()); + + am_sinkClass_t temp_SinkClassID = 0; + am_sinkClass_t temp_SinkClassIndex = 0; + + bool result; + if (sinkClass.sinkClassID != 0 || mFirstStaticSinkClass) + { + //check if the ID already exists + if (existSinkClass(sinkClass.sinkClassID)) + { + sinkClassID = sinkClass.sinkClassID; + return (E_ALREADY_EXISTS); + } + } + result = insertSinkClassDB(sinkClass, temp_SinkClassID); + if( false == result ) + return (E_UNKNOWN); + + temp_SinkClassIndex = temp_SinkClassID; + //if the ID is not created, we add it to the query + if (sinkClass.sinkClassID == 0 && mFirstStaticSinkClass) + { + mFirstStaticSinkClass = false; + } + mMappedData.mSinkClassesMap[temp_SinkClassIndex].sinkClassID = temp_SinkClassID; + sinkClassID = temp_SinkClassID; + + //todo:change last_insert implementations for multithreaded usage... + logInfo("DatabaseHandler::enterSinkClassDB entered new sinkClass"); + if (mpDatabaseObserver) + mpDatabaseObserver->numberOfSinkClassesChanged(); + return (E_OK); +} + +bool CAmDatabaseHandlerMap::insertSourceClassDB(am_sourceClass_t & sourceClassID, const am_SourceClass_s & sourceClass) +{ + int16_t nextID = 0; + if(mMappedData.increaseID(nextID, mMappedData.mCurrentSourceClassesID, sourceClass.sourceClassID)) + { + sourceClassID = nextID; + mMappedData.mSourceClassesMap[nextID] = sourceClass; + mMappedData.mSourceClassesMap[nextID].sourceClassID = nextID; + return (true); + } + else + { + sourceClassID = 0; + logInfo(__PRETTY_FUNCTION__,"Max limit reached."); + return (false); + } +} + +am_Error_e CAmDatabaseHandlerMap::enterSourceClassDB(am_sourceClass_t & sourceClassID, const am_SourceClass_s & sourceClass) +{ + assert(sourceClass.sourceClassID<DYNAMIC_ID_BOUNDARY); + assert(!sourceClass.name.empty()); + + am_sourceClass_t temp_SourceClassID = 0; + am_sourceClass_t temp_SourceClassIndex = 0; + + bool result; + if (sourceClass.sourceClassID != 0 || mFirstStaticSourceClass) + { + //check if the ID already exists + if (existSourceClass(sourceClass.sourceClassID)) + { + sourceClassID = sourceClass.sourceClassID; + return (E_ALREADY_EXISTS); + } + } + result = insertSourceClassDB(temp_SourceClassID, sourceClass); + if( false == result ) + return (E_UNKNOWN); + + temp_SourceClassIndex = temp_SourceClassID; + //if the ID is not created, we add it to the query + if (sourceClass.sourceClassID == 0 && mFirstStaticSourceClass) + { + mFirstStaticSinkClass = false; + } + mMappedData.mSourceClassesMap[temp_SourceClassIndex].sourceClassID = temp_SourceClassID; + sourceClassID = temp_SourceClassID; + + //todo:change last_insert implementations for multithread usage... + + logInfo("DatabaseHandler::enterSourceClassDB entered new sourceClass"); + + if (mpDatabaseObserver) + mpDatabaseObserver->numberOfSourceClassesChanged(); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::enterSystemProperties(const std::vector<am_SystemProperty_s> & listSystemProperties) +{ + assert(!listSystemProperties.empty()); + + mMappedData.mSystemProperties = listSystemProperties; + + logInfo("DatabaseHandler::enterSystemProperties entered system properties"); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeMainConnectionRouteDB(const am_mainConnectionID_t mainconnectionID, const std::vector<am_connectionID_t>& listConnectionID) +{ + assert(mainconnectionID!=0); + if (!existMainConnection(mainconnectionID)) + { + return (E_NON_EXISTENT); + } + + int16_t delay = calculateDelayForRoute(listConnectionID); + + //now we replace the data in the main connection object with the new one + mMappedData.mMainConnectionMap[mainconnectionID].listConnectionID = listConnectionID; + + if (changeDelayMainConnection(delay,mainconnectionID) == E_NO_CHANGE) + logError("DatabaseHandler::changeMainConnectionRouteDB error while changing mainConnectionDelay to ", delay); + + logInfo("DatabaseHandler::changeMainConnectionRouteDB entered new route:", mainconnectionID); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeMainConnectionStateDB(const am_mainConnectionID_t mainconnectionID, const am_ConnectionState_e connectionState) +{ + assert(mainconnectionID!=0); + assert(connectionState>=CS_UNKNOWN && connectionState<=CS_MAX); + + if (!existMainConnection(mainconnectionID)) + { + return (E_NON_EXISTENT); + } + + DB_COND_UPDATE_RIE(mMappedData.mMainConnectionMap[mainconnectionID].connectionState, connectionState); + + logInfo("DatabaseHandler::changeMainConnectionStateDB changed mainConnectionState of MainConnection:", mainconnectionID, "to:", connectionState); + if (mpDatabaseObserver) + mpDatabaseObserver->mainConnectionStateChanged(mainconnectionID, connectionState); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeSinkMainVolumeDB(const am_mainVolume_t mainVolume, const am_sinkID_t sinkID) +{ + assert(sinkID!=0); + + if (!existSink(sinkID)) + { + return (E_NON_EXISTENT); + } + + DB_COND_UPDATE_RIE(mMappedData.mSinkMap[sinkID].mainVolume, mainVolume); + + logInfo("DatabaseHandler::changeSinkMainVolumeDB changed mainVolume of sink:", sinkID, "to:", mainVolume); + + if (mpDatabaseObserver) + mpDatabaseObserver->volumeChanged(sinkID, mainVolume); + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeSinkAvailabilityDB(const am_Availability_s & availability, const am_sinkID_t sinkID) +{ + assert(sinkID!=0); + assert(availability.availability>=A_UNKNOWN && availability.availability<=A_MAX); + + if (!existSink(sinkID)) + { + return (E_NON_EXISTENT); + } + + DB_COND_UPDATE_RIE(mMappedData.mSinkMap[sinkID].available, availability); + + logInfo("DatabaseHandler::changeSinkAvailabilityDB changed sinkAvailability of sink:", sinkID, "to:", availability.availability, "Reason:", availability.availabilityReason); + + if (mpDatabaseObserver && sinkVisible(sinkID)) + mpDatabaseObserver->sinkAvailabilityChanged(sinkID, availability); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changDomainStateDB(const am_DomainState_e domainState, const am_domainID_t domainID) +{ + assert(domainID!=0); + assert(domainState>=DS_UNKNOWN && domainState<=DS_MAX); + + if (!existDomain(domainID)) + { + return (E_NON_EXISTENT); + } + + DB_COND_UPDATE_RIE(mMappedData.mDomainMap[domainID].state, domainState); + + logInfo("DatabaseHandler::changDomainStateDB changed domainState of domain:", domainID, "to:", domainState); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeSinkMuteStateDB(const am_MuteState_e muteState, const am_sinkID_t sinkID) +{ + assert(sinkID!=0); + assert(muteState>=MS_UNKNOWN && muteState<=MS_MAX); + + if (!existSink(sinkID)) + { + return (E_NON_EXISTENT); + } + + DB_COND_UPDATE_RIE(mMappedData.mSinkMap[sinkID].muteState, muteState); + + logInfo("DatabaseHandler::changeSinkMuteStateDB changed sinkMuteState of sink:", sinkID, "to:", muteState); + + if (mpDatabaseObserver) + mpDatabaseObserver->sinkMuteStateChanged(sinkID, muteState); + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeMainSinkSoundPropertyDB(const am_MainSoundProperty_s & soundProperty, const am_sinkID_t sinkID) +{ + assert(sinkID!=0); + + if (!existSink(sinkID)) + { + return (E_NON_EXISTENT); + } + am_Sink_Database_s & sink = mMappedData.mSinkMap[sinkID]; + std::vector<am_MainSoundProperty_s>::iterator elementIterator = sink.listMainSoundProperties.begin(); + for (;elementIterator != sink.listMainSoundProperties.end(); ++elementIterator) + { + if (elementIterator->type == soundProperty.type) + { + DB_COND_UPDATE_RIE(elementIterator->value, soundProperty.value); + if(sink.cacheMainSoundProperties.size()) + sink.cacheMainSoundProperties[soundProperty.type] = soundProperty.value; + break; + } + } + + logInfo("DatabaseHandler::changeMainSinkSoundPropertyDB changed MainSinkSoundProperty of sink:", sinkID, "type:", soundProperty.type, "to:", soundProperty.value); + if (mpDatabaseObserver) + mpDatabaseObserver->mainSinkSoundPropertyChanged(sinkID, soundProperty); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeMainSourceSoundPropertyDB(const am_MainSoundProperty_s & soundProperty, const am_sourceID_t sourceID) +{ + assert(sourceID!=0); + + if (!existSource(sourceID)) + { + return (E_NON_EXISTENT); + } + am_Source_Database_s & source = mMappedData.mSourceMap.at(sourceID); + std::vector<am_MainSoundProperty_s>::iterator elementIterator = source.listMainSoundProperties.begin(); + for (;elementIterator != source.listMainSoundProperties.end(); ++elementIterator) + { + if (elementIterator->type == soundProperty.type) + { + DB_COND_UPDATE_RIE(elementIterator->value, soundProperty.value); + if(source.cacheMainSoundProperties.size()) + source.cacheMainSoundProperties[soundProperty.type] = soundProperty.value; + break; + } + } + + logInfo("DatabaseHandler::changeMainSourceSoundPropertyDB changed MainSinkSoundProperty of source:", sourceID, "type:", soundProperty.type, "to:", soundProperty.value); + + if (mpDatabaseObserver) + mpDatabaseObserver->mainSourceSoundPropertyChanged(sourceID, soundProperty); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeSourceAvailabilityDB(const am_Availability_s & availability, const am_sourceID_t sourceID) +{ + assert(sourceID!=0); + assert(availability.availability>=A_UNKNOWN && availability.availability<=A_MAX); + + if (!existSource(sourceID)) + { + return (E_NON_EXISTENT); + } + + DB_COND_UPDATE_RIE(mMappedData.mSourceMap[sourceID].available, availability); + + logInfo("DatabaseHandler::changeSourceAvailabilityDB changed changeSourceAvailabilityDB of source:", sourceID, "to:", availability.availability, "Reason:", availability.availabilityReason); + + if (mpDatabaseObserver && sourceVisible(sourceID)) + mpDatabaseObserver->sourceAvailabilityChanged(sourceID, availability); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeSystemPropertyDB(const am_SystemProperty_s & property) +{ + std::vector<am_SystemProperty_s>::iterator elementIterator = mMappedData.mSystemProperties.begin(); + for (;elementIterator != mMappedData.mSystemProperties.end(); ++elementIterator) + { + if (elementIterator->type == property.type) + DB_COND_UPDATE_RIE(elementIterator->value, property.value); + } + + logInfo("DatabaseHandler::changeSystemPropertyDB changed system property"); + + if (mpDatabaseObserver) + mpDatabaseObserver->systemPropertyChanged(property); + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::removeMainConnectionDB(const am_mainConnectionID_t mainConnectionID) +{ + assert(mainConnectionID!=0); + + if (!existMainConnection(mainConnectionID)) + { + return (E_NON_EXISTENT); + } + + mMappedData.mMainConnectionMap.erase(mainConnectionID); + + logInfo("DatabaseHandler::removeMainConnectionDB removed:", mainConnectionID); + if (mpDatabaseObserver) + { + mpDatabaseObserver->mainConnectionStateChanged(mainConnectionID, CS_DISCONNECTED); + mpDatabaseObserver->removedMainConnection(mainConnectionID); + } + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::removeSinkDB(const am_sinkID_t sinkID) +{ + assert(sinkID!=0); + + if (!existSink(sinkID)) + { + return (E_NON_EXISTENT); + } + + bool visible = sinkVisible(sinkID); + + mMappedData.mSinkMap.erase(sinkID); + // todo: Check the tables SinkMainSoundProperty and SinkMainNotificationConfiguration with 'visible' set to true + //if visible is true then delete SinkMainSoundProperty and SinkMainNotificationConfiguration ???? + logInfo("DatabaseHandler::removeSinkDB removed:", sinkID); + + if (mpDatabaseObserver != NULL) + mpDatabaseObserver->removedSink(sinkID, visible); + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::removeSourceDB(const am_sourceID_t sourceID) +{ + assert(sourceID!=0); + + if (!existSource(sourceID)) + { + return (E_NON_EXISTENT); + } + + bool visible = sourceVisible(sourceID); + + mMappedData.mSourceMap.erase(sourceID); + + // todo: Check the tables SourceMainSoundProperty and SourceMainNotificationConfiguration with 'visible' set to true + //if visible is true then delete SourceMainSoundProperty and SourceMainNotificationConfiguration ???? + + logInfo("DatabaseHandler::removeSourceDB removed:", sourceID); + if (mpDatabaseObserver) + mpDatabaseObserver->removedSource(sourceID, visible); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::removeGatewayDB(const am_gatewayID_t gatewayID) +{ + assert(gatewayID!=0); + + if (!existGateway(gatewayID)) + { + return (E_NON_EXISTENT); + } + + mMappedData.mGatewayMap.erase(gatewayID); + + logInfo("DatabaseHandler::removeGatewayDB removed:", gatewayID); + if (mpDatabaseObserver) + mpDatabaseObserver->removeGateway(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)) + { + return (E_NON_EXISTENT); + } + mMappedData.mCrossfaderMap.erase(crossfaderID); + + logInfo("DatabaseHandler::removeCrossfaderDB removed:", crossfaderID); + if (mpDatabaseObserver) + mpDatabaseObserver->removeCrossfader(crossfaderID); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::removeDomainDB(const am_domainID_t domainID) +{ + assert(domainID!=0); + + if (!existDomain(domainID)) + { + return (E_NON_EXISTENT); + } + mMappedData.mDomainMap.erase(domainID); + + logInfo("DatabaseHandler::removeDomainDB removed:", domainID); + if (mpDatabaseObserver) + mpDatabaseObserver->removeDomain(domainID); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::removeSinkClassDB(const am_sinkClass_t sinkClassID) +{ + assert(sinkClassID!=0); + + if (!existSinkClass(sinkClassID)) + { + return (E_NON_EXISTENT); + } + + mMappedData.mSinkClassesMap.erase(sinkClassID); + + logInfo("DatabaseHandler::removeSinkClassDB removed:", sinkClassID); + if (mpDatabaseObserver) + mpDatabaseObserver->numberOfSinkClassesChanged(); + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::removeSourceClassDB(const am_sourceClass_t sourceClassID) +{ + assert(sourceClassID!=0); + + if (!existSourceClass(sourceClassID)) + { + return (E_NON_EXISTENT); + } + + mMappedData.mSourceClassesMap.erase(sourceClassID); + logInfo("DatabaseHandler::removeSourceClassDB removed:", sourceClassID); + if (mpDatabaseObserver) + mpDatabaseObserver->numberOfSourceClassesChanged(); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::removeConnection(const am_connectionID_t connectionID) +{ + assert(connectionID!=0); + + mMappedData.mConnectionMap.erase(connectionID); + + logInfo("DatabaseHandler::removeConnection removed:", connectionID); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getSourceClassInfoDB(const am_sourceID_t sourceID, am_SourceClass_s & classInfo) const +{ + assert(sourceID!=0); + + if (!existSource(sourceID)) + { + return (E_NON_EXISTENT); + } + am_Source_Database_s source = mMappedData.mSourceMap.at(sourceID); + classInfo.sourceClassID = source.sourceClassID; + + if (!existSourceClass(classInfo.sourceClassID)) + { + return (E_NON_EXISTENT); + } + am_SourceClass_s tmpClass = mMappedData.mSourceClassesMap.at(classInfo.sourceClassID); + classInfo = tmpClass; + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getSinkInfoDB(const am_sinkID_t sinkID, am_Sink_s & sinkData) const +{ + assert(sinkID!=0); + + if (!existSink(sinkID)) + return (E_NON_EXISTENT); + + am_Sink_Database_s mappedSink = mMappedData.mSinkMap.at(sinkID); + if( true == mappedSink.reserved ) + return (E_NON_EXISTENT); + sinkData = mappedSink; + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getSourceInfoDB(const am_sourceID_t sourceID, am_Source_s & sourceData) const +{ + assert(sourceID!=0); + + if (!existSource(sourceID)) + return (E_NON_EXISTENT); + + am_Source_Database_s mappedSource = mMappedData.mSourceMap.at(sourceID); + if( true == mappedSource.reserved ) + return (E_NON_EXISTENT); + + sourceData = mappedSource; + + return (E_OK); +} + +am_Error_e am::CAmDatabaseHandlerMap::getMainConnectionInfoDB(const am_mainConnectionID_t mainConnectionID, am_MainConnection_s & mainConnectionData) const +{ + assert(mainConnectionID!=0); + if (!existMainConnection(mainConnectionID)) + { + return (E_NON_EXISTENT); + } + am_MainConnection_s temp = mMappedData.mMainConnectionMap.at(mainConnectionID); + mainConnectionData = temp; + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeSinkClassInfoDB(const am_SinkClass_s& sinkClass) +{ + assert(sinkClass.sinkClassID!=0); + assert(!sinkClass.listClassProperties.empty()); + + //check if the ID already exists + if (!existSinkClass(sinkClass.sinkClassID)) + return (E_NON_EXISTENT); + + DB_COND_UPDATE_RIE(mMappedData.mSinkClassesMap[sinkClass.sinkClassID].listClassProperties, sinkClass.listClassProperties); + + logInfo("DatabaseHandler::setSinkClassInfoDB set setSinkClassInfo"); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeSourceClassInfoDB(const am_SourceClass_s& sourceClass) +{ + assert(sourceClass.sourceClassID!=0); + assert(!sourceClass.listClassProperties.empty()); + + //check if the ID already exists + if (!existSourceClass(sourceClass.sourceClassID)) + return (E_NON_EXISTENT); + + DB_COND_UPDATE_RIE(mMappedData.mSourceClassesMap[sourceClass.sourceClassID].listClassProperties, sourceClass.listClassProperties); + + logInfo("DatabaseHandler::setSinkClassInfoDB set setSinkClassInfo"); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getSinkClassInfoDB(const am_sinkID_t sinkID, am_SinkClass_s & sinkClass) const +{ + assert(sinkID!=0); + + if (!existSink(sinkID)) + { + return (E_NON_EXISTENT); + } + am_Sink_Database_s sink = mMappedData.mSinkMap.at(sinkID); + sinkClass.sinkClassID = sink.sinkClassID; + + if (!existSinkClass(sinkClass.sinkClassID)) + { + return (E_NON_EXISTENT); + } + am_SinkClass_s tmpSinkClass = mMappedData.mSinkClassesMap.at(sinkClass.sinkClassID); + sinkClass = tmpSinkClass; + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getGatewayInfoDB(const am_gatewayID_t gatewayID, am_Gateway_s & gatewayData) const +{ + assert(gatewayID!=0); + if (!existGateway(gatewayID)) + { + return (E_NON_EXISTENT); + } + + gatewayData = mMappedData.mGatewayMap.at(gatewayID); + + return (E_OK); + +} + +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)) + { + return (E_NON_EXISTENT); + } + + crossfaderData = mMappedData.mCrossfaderMap.at(crossfaderID); + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListSinksOfDomain(const am_domainID_t domainID, std::vector<am_sinkID_t> & listSinkID) const +{ + assert(domainID!=0); + listSinkID.clear(); + if (!existDomain(domainID)) + { + return (E_NON_EXISTENT); + } + + std::unordered_map<am_sinkID_t, am_Sink_Database_s>::const_iterator elementIterator = mMappedData.mSinkMap.begin(); + for (;elementIterator != mMappedData.mSinkMap.end(); ++elementIterator) + { + if (0==elementIterator->second.reserved && domainID==elementIterator->second.domainID) + listSinkID.push_back(elementIterator->second.sinkID); + } + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListSourcesOfDomain(const am_domainID_t domainID, std::vector<am_sourceID_t> & listSourceID) const +{ + assert(domainID!=0); + listSourceID.clear(); + if (!existDomain(domainID)) + { + return (E_NON_EXISTENT); + } + CAmMapSource::const_iterator elementIterator = mMappedData.mSourceMap.begin(); + for (;elementIterator != mMappedData.mSourceMap.end(); ++elementIterator) + { + if (0==elementIterator->second.reserved && domainID==elementIterator->second.domainID) + listSourceID.push_back(elementIterator->second.sourceID); + } + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListCrossfadersOfDomain(const am_domainID_t domainID, std::vector<am_crossfaderID_t> & listCrossfader) const +{ + assert(domainID!=0); + listCrossfader.clear(); + if (!existDomain(domainID)) + { + return (E_NON_EXISTENT); + } + + CAmMapSource::const_iterator sourceIterator = mMappedData.mSourceMap.begin(); + for (;sourceIterator != mMappedData.mSourceMap.end(); ++sourceIterator) + { + if (domainID==sourceIterator->second.domainID) + { + CAmMapCrossfader::const_iterator elementIterator = mMappedData.mCrossfaderMap.begin(); + for (;elementIterator != mMappedData.mCrossfaderMap.end(); ++elementIterator) + { + if ( sourceIterator->second.sourceID==elementIterator->second.sourceID ) + listCrossfader.push_back(elementIterator->second.crossfaderID); + } + } + } + + return (E_OK); + +} + +am_Error_e CAmDatabaseHandlerMap::getListGatewaysOfDomain(const am_domainID_t domainID, std::vector<am_gatewayID_t> & listGatewaysID) const +{ + assert(domainID!=0); + listGatewaysID.clear(); + if (!existDomain(domainID)) + { + return (E_NON_EXISTENT); + } + + CAmMapGateway::const_iterator elementIterator = mMappedData.mGatewayMap.begin(); + for (;elementIterator != mMappedData.mGatewayMap.end(); ++elementIterator) + { + if (domainID==elementIterator->second.controlDomainID) + listGatewaysID.push_back(elementIterator->second.gatewayID); + } + 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(); + + CAmMapMainConnection::const_iterator elementIterator = mMappedData.mMainConnectionMap.begin(); + for (;elementIterator != mMappedData.mMainConnectionMap.end(); ++elementIterator) + { + listMainConnections.push_back(elementIterator->second); + } + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListDomains(std::vector<am_Domain_s> & listDomains) const +{ + listDomains.clear(); + + CAmMapDomain::const_iterator elementIterator = mMappedData.mDomainMap.begin(); + for (;elementIterator != mMappedData.mDomainMap.end(); ++elementIterator) + { + if( 0==elementIterator->second.reserved ) + listDomains.push_back(elementIterator->second); + } + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListConnections(std::vector<am_Connection_s> & listConnections) const +{ + listConnections.clear(); + + CAmMapConnection::const_iterator elementIterator = mMappedData.mConnectionMap.begin(); + for (;elementIterator != mMappedData.mConnectionMap.end(); ++elementIterator) + { + if( 0==elementIterator->second.reserved ) + listConnections.push_back(elementIterator->second); + } + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListSinks(std::vector<am_Sink_s> & listSinks) const +{ + listSinks.clear(); + + std::for_each(mMappedData.mSinkMap.begin(), mMappedData.mSinkMap.end(), [&](const std::pair<am_sinkID_t, am_Sink_Database_s>& ref) { + if( 0==ref.second.reserved ) + listSinks.push_back(ref.second); + }); + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListSources(std::vector<am_Source_s> & listSources) const +{ + listSources.clear(); + + std::for_each(mMappedData.mSourceMap.begin(), mMappedData.mSourceMap.end(), [&](const std::pair<am_sourceID_t, am_Source_Database_s>& ref) { + if( 0==ref.second.reserved ) + { + listSources.push_back(ref.second); + } + }); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListSourceClasses(std::vector<am_SourceClass_s> & listSourceClasses) const +{ + listSourceClasses.clear(); + + std::for_each(mMappedData.mSourceClassesMap.begin(), mMappedData.mSourceClassesMap.end(), [&](const std::pair<am_sourceClass_t, am_SourceClass_s>& ref) { + listSourceClasses.push_back(ref.second); + }); + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListCrossfaders(std::vector<am_Crossfader_s> & listCrossfaders) const +{ + listCrossfaders.clear(); + + std::for_each(mMappedData.mCrossfaderMap.begin(), mMappedData.mCrossfaderMap.end(), [&](const std::pair<am_crossfaderID_t, am_Crossfader_s>& ref) { + listCrossfaders.push_back(ref.second); + }); + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListGateways(std::vector<am_Gateway_s> & listGateways) const +{ + listGateways.clear(); + + std::for_each(mMappedData.mGatewayMap.begin(), mMappedData.mGatewayMap.end(), [&](const std::pair<am_gatewayID_t, am_Gateway_s>& ref) { + listGateways.push_back(ref.second); + }); + + 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(); + + std::for_each(mMappedData.mSinkClassesMap.begin(), mMappedData.mSinkClassesMap.end(), [&](const std::pair<am_gatewayID_t, am_SinkClass_s>& ref) { + listSinkClasses.push_back(ref.second); + }); + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListVisibleMainConnections(std::vector<am_MainConnectionType_s> & listConnections) const +{ + listConnections.clear(); + std::for_each(mMappedData.mMainConnectionMap.begin(), mMappedData.mMainConnectionMap.end(), [&](const std::pair<am_mainConnectionID_t, am_MainConnection_Database_s>& ref) { + listConnections.emplace_back(); + ref.second.getMainConnectionType(listConnections.back()); + }); + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListMainSinks(std::vector<am_SinkType_s> & listMainSinks) const +{ + listMainSinks.clear(); + std::for_each(mMappedData.mSinkMap.begin(), mMappedData.mSinkMap.end(), [&](const std::pair<am_sinkID_t, am_Sink_Database_s>& ref) { + if( 0==ref.second.reserved && 1==ref.second.visible ) + { + listMainSinks.emplace_back(); + ref.second.getSinkType(listMainSinks.back()); + } + }); + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListMainSources(std::vector<am_SourceType_s> & listMainSources) const +{ + listMainSources.clear(); + std::for_each(mMappedData.mSourceMap.begin(), mMappedData.mSourceMap.end(), [&](const std::pair<am_sourceID_t, am_Source_Database_s>& ref) { + if( 0==ref.second.reserved && 1==ref.second.visible ) + { + listMainSources.emplace_back(); + ref.second.getSourceType(listMainSources.back()); + } + }); + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListMainSinkSoundProperties(const am_sinkID_t sinkID, std::vector<am_MainSoundProperty_s> & listSoundProperties) const +{ + assert(sinkID!=0); + if (!existSink(sinkID)) + return E_NON_EXISTENT; + + const am_Sink_s & sink = mMappedData.mSinkMap.at(sinkID); + listSoundProperties = sink.listMainSoundProperties; + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListMainSourceSoundProperties(const am_sourceID_t sourceID, std::vector<am_MainSoundProperty_s> & listSourceProperties) const +{ + assert(sourceID!=0); + if (!existSource(sourceID)) + return E_NON_EXISTENT; + + const am_Source_s & source = mMappedData.mSourceMap.at(sourceID); + listSourceProperties = source.listMainSoundProperties; + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListSinkSoundProperties(const am_sinkID_t sinkID, std::vector<am_SoundProperty_s>& listSoundproperties) const +{ + assert(sinkID!=0); + if (!existSink(sinkID)) + return E_NON_EXISTENT; + + const am_Sink_Database_s & sink = mMappedData.mSinkMap.at(sinkID); + listSoundproperties = sink.listSoundProperties; + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListSourceSoundProperties(const am_sourceID_t sourceID, std::vector<am_SoundProperty_s>& listSoundproperties) const +{ + assert(sourceID!=0); + if (!existSource(sourceID)) + return E_NON_EXISTENT; + + const am_Source_Database_s & source = mMappedData.mSourceMap.at(sourceID); + listSoundproperties = source.listSoundProperties; + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListSystemProperties(std::vector<am_SystemProperty_s> & listSystemProperties) const +{ + listSystemProperties = mMappedData.mSystemProperties; + return (E_OK); +} + +am_Error_e am::CAmDatabaseHandlerMap::getListSinkConnectionFormats(const am_sinkID_t sinkID, std::vector<am_CustomConnectionFormat_t> & listConnectionFormats) const +{ + if (!existSink(sinkID)) + return E_NON_EXISTENT; + const am_Sink_s & sink = mMappedData.mSinkMap.at(sinkID); + listConnectionFormats = sink.listConnectionFormats; + + return (E_OK); +} + +am_Error_e am::CAmDatabaseHandlerMap::getListSourceConnectionFormats(const am_sourceID_t sourceID, std::vector<am_CustomConnectionFormat_t> & listConnectionFormats) const +{ + if (!existSource(sourceID)) + return E_NON_EXISTENT; + const am_Source_s & source = mMappedData.mSourceMap.at(sourceID); + listConnectionFormats = source.listConnectionFormats; + + return (E_OK); +} + +am_Error_e am::CAmDatabaseHandlerMap::getListGatewayConnectionFormats(const am_gatewayID_t gatewayID, std::vector<bool> & listConnectionFormat) const +{ + ListConnectionFormat::const_iterator iter = mListConnectionFormat.begin(); + iter = mListConnectionFormat.find(gatewayID); + if (iter == mListConnectionFormat.end()) + { + logError("DatabaseHandler::getListGatewayConnectionFormats database error with convertionFormat"); + + return E_NON_EXISTENT; + } + listConnectionFormat = iter->second; + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getTimingInformation(const am_mainConnectionID_t mainConnectionID, am_timeSync_t & delay) const +{ + assert(mainConnectionID!=0); + if (!existMainConnection(mainConnectionID)) + return E_NON_EXISTENT; + delay = -1; + + const am_MainConnection_s & mainConnection = mMappedData.mMainConnectionMap.at(mainConnectionID); + delay = mainConnection.delay; + + if (delay == -1) + return (E_NOT_POSSIBLE); + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeDelayMainConnection(const am_timeSync_t & delay, const am_mainConnectionID_t & connectionID) +{ + assert(connectionID!=0); + if (!existMainConnection(connectionID)) + return (E_NON_EXISTENT); + DB_COND_UPDATE_RIE(mMappedData.mMainConnectionMap[connectionID].delay, delay); + if (mpDatabaseObserver) + mpDatabaseObserver->timingInformationChanged(connectionID, delay); + return (E_OK); +} + +/** + * checks for a certain mainConnection + * @param mainConnectionID to be checked for + * @return true if it exists + */ +bool CAmDatabaseHandlerMap::existMainConnection(const am_mainConnectionID_t mainConnectionID) const +{ + return existsObjectWithKeyInMap(mainConnectionID, mMappedData.mMainConnectionMap); +} + +/** + * checks for a certain Source + * @param sourceID to be checked for + * @return true if it exists + */ +bool CAmDatabaseHandlerMap::existSource(const am_sourceID_t sourceID) const +{ + am_Source_Database_s const * source = objectForKeyIfExistsInMap(sourceID, mMappedData.mSourceMap); + if( NULL!=source ) + return (0==source->reserved); + + return false; +} + +/** + * checks if a source name or ID exists + * @param sourceID the sourceID + * @param name the name + * @return true if it exits + */ +bool CAmDatabaseHandlerMap::existSourceNameOrID(const am_sourceID_t sourceID, const std::string & name) const +{ + return sourceWithNameOrID(sourceID, name); +} + +/** + * checks if a name exits + * @param name the name + * @return true if it exits + */ +bool CAmDatabaseHandlerMap::existSourceName(const std::string & name) const +{ + return existSourceNameOrID(mMappedData.mCurrentSourceID.mMax, name); +} + +/** + * checks for a certain Sink + * @param sinkID to be checked for + * @return true if it exists + */ +bool CAmDatabaseHandlerMap::existSink(const am_sinkID_t sinkID) const +{ + bool returnVal = false; + CAmMapSink::const_iterator elementIterator = mMappedData.mSinkMap.begin(); + for (;elementIterator != mMappedData.mSinkMap.end(); ++elementIterator) + { + if( 0==elementIterator->second.reserved && + sinkID==elementIterator->second.sinkID) + { + returnVal = true; + break; + } + } + return (returnVal); +} + +/** + * returns source with given ID or the name if exists + * @param sourceID the ID + * @param name the name + * @return source structure if exists. + */ +const CAmDatabaseHandlerMap::am_Source_Database_s * CAmDatabaseHandlerMap::sourceWithNameOrID(const am_sourceID_t sourceID, const std::string & name) const +{ + std::function<bool(const CAmDatabaseHandlerMap::am_Source_Database_s & refObject)> comparator = [&](const CAmDatabaseHandlerMap::am_Source_Database_s & source)->bool{ + return ( 0==source.reserved && + (sourceID==source.sourceID || name.compare(source.name)==0)); + }; + return objectMatchingPredicate(mMappedData.mSourceMap, comparator); +} + +/** + * returns sink with given ID or the name if exists + * @param sinkID the ID + * @param name the name + * @return sink structure if exists. + */ +const CAmDatabaseHandlerMap::am_Sink_Database_s * CAmDatabaseHandlerMap::sinkWithNameOrID(const am_sinkID_t sinkID, const std::string & name) const +{ + std::function<bool(const CAmDatabaseHandlerMap::am_Sink_Database_s & refObject)> comparator = [&](const CAmDatabaseHandlerMap::am_Sink_Database_s & sink)->bool{ + return ( 0==sink.reserved && + (sinkID==sink.sinkID || name.compare(sink.name)==0)); + }; + return objectMatchingPredicate(mMappedData.mSinkMap, comparator); +} + +/** + * checks if a sink with the ID or the name exists + * @param sinkID the ID + * @param name the name + * @return true if it exists. + */ +bool CAmDatabaseHandlerMap::existSinkNameOrID(const am_sinkID_t sinkID, const std::string & name) const +{ + return sinkWithNameOrID( sinkID, name)!=NULL; +} + +/** + * checks if a sink with the name exists + * @param name the name + * @return true if it exists + */ +bool CAmDatabaseHandlerMap::existSinkName(const std::string & name) const +{ + return existSinkNameOrID(mMappedData.mCurrentSinkID.mMax, name); +} + +/** + * checks for a certain domain + * @param domainID to be checked for + * @return true if it exists + */ +bool CAmDatabaseHandlerMap::existDomain(const am_domainID_t domainID) const +{ + am_Domain_Database_s const * source = objectForKeyIfExistsInMap(domainID, mMappedData.mDomainMap); + if( NULL!=source ) + return (0==source->reserved); + + return false; +} + +/** + * checks for certain gateway + * @param gatewayID to be checked for + * @return true if it exists + */ +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); + domainID=0; + + am_Source_Database_s const * source = objectForKeyIfExistsInMap(sourceID, mMappedData.mSourceMap); + if( NULL!=source ) + { + domainID = source->domainID; + return E_OK; + } + return E_NON_EXISTENT; +} + +am_Error_e am::CAmDatabaseHandlerMap::getDomainOfSink(const am_sinkID_t sinkID, am_domainID_t & domainID) const +{ + assert(sinkID!=0); + domainID=0; + + am_Sink_Database_s const * source = objectForKeyIfExistsInMap(sinkID, mMappedData.mSinkMap); + if( NULL!=source ) + { + domainID = source->domainID; + return E_OK; + } + return E_NON_EXISTENT; +} + +am_Error_e am::CAmDatabaseHandlerMap::getDomainOfCrossfader(const am_converterID_t crossfader, am_domainID_t & domainID) const +{ + assert(crossfader!=0); + domainID=0; + + am_Crossfader_Database_s const * cross = objectForKeyIfExistsInMap(crossfader, mMappedData.mCrossfaderMap); + if( NULL!=cross ) + { + getDomainOfSource(cross->sinkID_A,domainID); + return E_OK; + } + return E_NON_EXISTENT; +} + +/** + * checks for certain SinkClass + * @param sinkClassID + * @return true if it exists + */ +bool CAmDatabaseHandlerMap::existSinkClass(const am_sinkClass_t sinkClassID) const +{ + return existsObjectWithKeyInMap(sinkClassID, mMappedData.mSinkClassesMap); +} + +/** + * checks for certain sourceClass + * @param sourceClassID + * @return true if it exists + */ +bool CAmDatabaseHandlerMap::existSourceClass(const am_sourceClass_t sourceClassID) const +{ + return existsObjectWithKeyInMap(sourceClassID, mMappedData.mSourceClassesMap); +} + +am_Error_e CAmDatabaseHandlerMap::changeConnectionTimingInformation(const am_connectionID_t connectionID, const am_timeSync_t delay) +{ + assert(connectionID!=0); + if(!existConnectionID(connectionID)) + return E_NON_EXISTENT; + + mMappedData.mConnectionMap[connectionID].delay = delay; + + //now we need to find all mainConnections that use the changed connection and update their timing + + //first get all route tables for all mainconnections + am_Error_e error = E_OK; + CAmMapMainConnection::const_iterator iter = mMappedData.mMainConnectionMap.begin(); + for(; iter != mMappedData.mMainConnectionMap.end(); ++iter) + { + const am_MainConnection_s & mainConnection = iter->second; + if (std::find(mainConnection.listConnectionID.begin(), mainConnection.listConnectionID.end(), connectionID) != mainConnection.listConnectionID.end()) + { + // Got it. + error = changeDelayMainConnection(calculateMainConnectionDelay(mainConnection.mainConnectionID), mainConnection.mainConnectionID); + } + } + + return error; +} + +am_Error_e CAmDatabaseHandlerMap::changeConnectionFinal(const am_connectionID_t connectionID) +{ + assert(connectionID!=0); + am_Connection_Database_s const * connection = objectForKeyIfExistsInMap(connectionID, mMappedData.mConnectionMap); + if( NULL!=connection ) + { + mMappedData.mConnectionMap.at(connectionID).reserved = false; + return E_OK; + } + return (E_NON_EXISTENT); +} + +am_timeSync_t CAmDatabaseHandlerMap::calculateMainConnectionDelay(const am_mainConnectionID_t mainConnectionID) const +{ + assert(mainConnectionID!=0); + if (!existMainConnection(mainConnectionID)) + return -1; + const am_MainConnection_s & mainConnection = mMappedData.mMainConnectionMap.at(mainConnectionID); + am_timeSync_t delay = 0; + std::vector<am_connectionID_t>::const_iterator iter = mainConnection.listConnectionID.begin(); + for(;iter<mainConnection.listConnectionID.end(); ++iter) + { + am_Connection_Database_s const * source = objectForKeyIfExistsInMap(*iter, mMappedData.mConnectionMap); + if( NULL!=source ) + { + delay += std::max(source->delay, static_cast<am_timeSync_t>(0)); + } + } + return (delay == 0 ? -1 : std::min(delay, static_cast<am_timeSync_t>(SHRT_MAX))); +} + +/** + * registers the Observer at the Database + * @param iObserver pointer to the observer + */ +void CAmDatabaseHandlerMap::registerObserver(CAmDatabaseObserver *iObserver) +{ + assert(iObserver!=NULL); + mpDatabaseObserver = iObserver; +} + +/** + * gives information about the visibility of a source + * @param sourceID the sourceID + * @return true if source is visible + */ +bool CAmDatabaseHandlerMap::sourceVisible(const am_sourceID_t sourceID) const +{ + assert(sourceID!=0); + if (!existSource(sourceID)) + return false; + am_Source_Database_s source = mMappedData.mSourceMap.at(sourceID); + return source.visible; +} + +/** + * gives information about the visibility of a sink + * @param sinkID the sinkID + * @return true if source is visible + */ +bool CAmDatabaseHandlerMap::sinkVisible(const am_sinkID_t sinkID) const +{ + am_Sink_Database_s const * source = objectForKeyIfExistsInMap(sinkID, mMappedData.mSinkMap); + if( NULL!=source ) + { + if(0==source->reserved) + return source->visible; + } + return false; +} + +/** + * checks if a connection already exists. + * Only takes sink, source and format information for search! + * @param connection the connection to be checked + * @return true if connections exists + */ +bool CAmDatabaseHandlerMap::existConnection(const am_Connection_s & connection) const +{ + am_Connection_Database_s const * connectionObject = objectMatchingPredicate<am_Connection_Database_s, am_connectionID_t>(mMappedData.mConnectionMap, [&](const am_Connection_Database_s & obj){ + return false==obj.reserved && + connection.sinkID == obj.sinkID && + connection.sourceID == obj.sourceID && + connection.connectionFormat == obj.connectionFormat; + }); + return ( NULL!=connectionObject ); +} + +/** + * checks if a connection with the given ID exists + * @param connectionID + * @return true if connection exits + */ +bool CAmDatabaseHandlerMap::existConnectionID(const am_connectionID_t connectionID) const +{ + am_Connection_Database_s const * connection = objectForKeyIfExistsInMap(connectionID, mMappedData.mConnectionMap); + if( NULL!=connection ) + { + return (0==connection->reserved); + } + return false; +} + +/** + * checks if a CrossFader exists + * @param crossfaderID the ID of the crossfader to be checked + * @return true if exists + */ +bool CAmDatabaseHandlerMap::existCrossFader(const am_crossfaderID_t crossfaderID) const +{ + return existsObjectWithKeyInMap(crossfaderID, mMappedData.mCrossfaderMap); +} + +am_Error_e CAmDatabaseHandlerMap::getSoureState(const am_sourceID_t sourceID, am_SourceState_e & sourceState) const +{ + am_Source_Database_s const * source = objectForKeyIfExistsInMap(sourceID, mMappedData.mSourceMap); + if( NULL!=source ) + { + sourceState = source->sourceState; + return (E_OK); + } + else + { + sourceState = SS_UNKNNOWN; + return (E_NON_EXISTENT); + } +} + +am_Error_e CAmDatabaseHandlerMap::changeSourceState(const am_sourceID_t sourceID, const am_SourceState_e sourceState) +{ + assert(sourceID!=0); + assert(sourceState>=SS_UNKNNOWN && sourceState<=SS_MAX); + if(existSource(sourceID)) + { + mMappedData.mSourceMap.at(sourceID).sourceState = sourceState; + return (E_OK); + } + return (E_NON_EXISTENT); +} + +am_Error_e CAmDatabaseHandlerMap::getSinkMainVolume(const am_sinkID_t sinkID, am_mainVolume_t& mainVolume) const { + assert(sinkID!=0); + + am_Sink_Database_s const * source = objectForKeyIfExistsInMap(sinkID, mMappedData.mSinkMap); + if( NULL!=source ) + { + mainVolume = source->mainVolume; + return (E_OK); + } + mainVolume = -1; + return (E_NON_EXISTENT); +} + +am_Error_e CAmDatabaseHandlerMap::getSinkVolume(const am_sinkID_t sinkID, am_volume_t & volume) const +{ + assert(sinkID!=0); + + am_Sink_Database_s const * source = objectForKeyIfExistsInMap(sinkID, mMappedData.mSinkMap); + if( NULL!=source ) + { + volume = source->volume; + return (E_OK); + } + volume = -1; + return (E_NON_EXISTENT); +} + +am_Error_e CAmDatabaseHandlerMap::getSourceVolume(const am_sourceID_t sourceID, am_volume_t & volume) const +{ + assert(sourceID!=0); + am_Source_Database_s const * source = objectForKeyIfExistsInMap(sourceID, mMappedData.mSourceMap); + if( NULL!=source ) + { + volume = source->volume; + return (E_OK); + } + volume = -1; + return (E_NON_EXISTENT); +} + +am_Error_e CAmDatabaseHandlerMap::getSinkSoundPropertyValue(const am_sinkID_t sinkID, const am_CustomSoundPropertyType_t propertyType, int16_t & value) const +{ + assert(sinkID!=0); + + am_Sink_Database_s * pObject = (am_Sink_Database_s *)objectForKeyIfExistsInMap(sinkID, mMappedData.mSinkMap); + if( NULL!=pObject ) + { + if(pObject->listSoundProperties.size()>0 && 0==pObject->cacheSoundProperties.size()) + { + std::vector<am_SoundProperty_s>::const_iterator iter = pObject->listSoundProperties.begin(); + for(; iter<pObject->listSoundProperties.end(); ++iter) + pObject->cacheSoundProperties[iter->type] = iter->value; + } + auto it = pObject->cacheSoundProperties.find(propertyType); + if(it!=pObject->cacheSoundProperties.end()) + { + value = it->second; + return (E_OK); + } + } + value = -1; + return (E_NON_EXISTENT); +} + +am_Error_e CAmDatabaseHandlerMap::getSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomSoundPropertyType_t propertyType, int16_t & value) const +{ + assert(sourceID!=0); + + am_Source_Database_s * pObject = (am_Source_Database_s *)objectForKeyIfExistsInMap(sourceID, mMappedData.mSourceMap); + if( NULL!=pObject ) + { + if(pObject->listSoundProperties.size()>0 && 0==pObject->cacheSoundProperties.size()) + { + std::vector<am_SoundProperty_s>::const_iterator iter = pObject->listSoundProperties.begin(); + for(; iter<pObject->listSoundProperties.end(); ++iter) + pObject->cacheSoundProperties[iter->type] = iter->value; + } + auto it = pObject->cacheSoundProperties.find(propertyType); + if(it!=pObject->cacheSoundProperties.end()) + { + value = it->second; + return (E_OK); + } + } + value = -1; + return (E_NON_EXISTENT); +} + +am_Error_e CAmDatabaseHandlerMap::getMainSinkSoundPropertyValue(const am_sinkID_t sinkID, const am_CustomMainSoundPropertyType_t propertyType, int16_t& value) const +{ + assert(sinkID!=0); + + am_Sink_Database_s * pObject = (am_Sink_Database_s *)objectForKeyIfExistsInMap(sinkID, mMappedData.mSinkMap); + if( NULL!=pObject ) + { + if(pObject->listMainSoundProperties.size()>0 && 0==pObject->cacheMainSoundProperties.size()) + { + std::vector<am_MainSoundProperty_s>::const_iterator iter = pObject->listMainSoundProperties.begin(); + for(; iter<pObject->listMainSoundProperties.end(); ++iter) + pObject->cacheMainSoundProperties[iter->type] = iter->value; + } + auto it = pObject->cacheMainSoundProperties.find(propertyType); + if(it!=pObject->cacheMainSoundProperties.end()) + { + value = it->second; + return (E_OK); + } + } + value = -1; + return (E_NON_EXISTENT); +} + +am_Error_e CAmDatabaseHandlerMap::getMainSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomMainSoundPropertyType_t propertyType, int16_t& value) const +{ + assert(sourceID!=0); + + am_Source_Database_s * pObject = (am_Source_Database_s *)objectForKeyIfExistsInMap(sourceID, mMappedData.mSourceMap); + if( NULL!=pObject ) + { + if(pObject->listMainSoundProperties.size()>0 && 0==pObject->cacheMainSoundProperties.size()) + { + std::vector<am_MainSoundProperty_s>::const_iterator iter = pObject->listMainSoundProperties.begin(); + for(; iter<pObject->listMainSoundProperties.end(); ++iter) + pObject->cacheMainSoundProperties[iter->type] = iter->value; + } + auto it = pObject->cacheMainSoundProperties.find(propertyType); + if(it!=pObject->cacheMainSoundProperties.end()) + { + value = it->second; + return (E_OK); + } + } + + value = -1; + return (E_NON_EXISTENT); +} + +am_Error_e CAmDatabaseHandlerMap::getDomainState(const am_domainID_t domainID, am_DomainState_e& state) const +{ + assert(domainID!=0); + + am_Domain_Database_s const * source = objectForKeyIfExistsInMap(domainID, mMappedData.mDomainMap); + if( NULL!=source ) + { + state = source->state; + return (E_OK); + } + state = DS_UNKNOWN; + return (E_NON_EXISTENT); +} + +am_Error_e CAmDatabaseHandlerMap::peekDomain(const std::string & name, am_domainID_t & domainID) +{ + domainID=0; + + am_Domain_Database_s const *reservedDomain = objectMatchingPredicate<am_Domain_Database_s, am_domainID_t>(mMappedData.mDomainMap, [&](const am_Domain_Database_s & obj){ + return name.compare(obj.name)==0; + }); + + if( NULL != reservedDomain ) + { + domainID = reservedDomain->domainID; + return E_OK; + } + else + { + int16_t nextID = 0; + if( mMappedData.increaseID( nextID, mMappedData.mCurrentDomainID) ) + { + domainID = nextID; + am_Domain_Database_s domain; + domain.domainID = nextID; + domain.name = name; + domain.reserved = 1; + mMappedData.mDomainMap[nextID] = domain; + return E_OK; + } + return E_UNKNOWN; + } + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::peekSink(const std::string & name, am_sinkID_t & sinkID) +{ + am_Sink_Database_s const *reservedSink = objectMatchingPredicate<am_Sink_Database_s, am_sinkID_t>(mMappedData.mSinkMap, [&](const am_Sink_Database_s & obj){ + return name.compare(obj.name)==0; + }); + if( NULL!=reservedSink ) + { + sinkID = reservedSink->sinkID; + return E_OK; + } + else + { + int16_t nextID = 0; + if(mMappedData.increaseID(nextID, mMappedData.mCurrentSinkID)) + { + if(mFirstStaticSink) + { + nextID = DYNAMIC_ID_BOUNDARY; + mFirstStaticSink = false; + } + sinkID = nextID; + am_Sink_Database_s object; + object.sinkID = nextID; + object.name = name; + object.reserved = 1; + mMappedData.mSinkMap[nextID] = object; + return E_OK; + } + return E_UNKNOWN; + } +} + +am_Error_e CAmDatabaseHandlerMap::peekSource(const std::string & name, am_sourceID_t & sourceID) +{ + am_Source_Database_s const *reservedSrc = objectMatchingPredicate<am_Source_Database_s, am_sourceID_t>(mMappedData.mSourceMap, [&](const am_Source_Database_s & obj){ + return name.compare(obj.name)==0; + }); + if( NULL!=reservedSrc ) + { + sourceID = reservedSrc->sourceID; + return E_OK; + } + else + { + int16_t nextID = 0; + if(mMappedData.increaseID(nextID, mMappedData.mCurrentSourceID)) + { + if(mFirstStaticSource) + { +// nextID = DYNAMIC_ID_BOUNDARY; + mFirstStaticSource = false; + } + sourceID = nextID; + am_Source_Database_s object; + object.sourceID = nextID; + object.name = name; + object.reserved = 1; + mMappedData.mSourceMap[nextID] = object; + return E_OK; + } + else + return E_UNKNOWN; + } +} + +am_Error_e CAmDatabaseHandlerMap::changeSinkVolume(const am_sinkID_t sinkID, const am_volume_t volume) +{ + assert(sinkID!=0); + + if (!existSink(sinkID)) + { + return (E_NON_EXISTENT); + } + + mMappedData.mSinkMap[sinkID].volume = volume; + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeSourceVolume(const am_sourceID_t sourceID, const am_volume_t volume) +{ + assert(sourceID!=0); + if (!existSource(sourceID)) + { + return (E_NON_EXISTENT); + } + mMappedData.mSourceMap[sourceID].volume = volume; + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeSourceSoundPropertyDB(const am_SoundProperty_s & soundProperty, const am_sourceID_t sourceID) +{ + assert(sourceID!=0); + + if (!existSource(sourceID)) + { + return (E_NON_EXISTENT); + } + + am_Source_Database_s & source = mMappedData.mSourceMap[sourceID]; + std::vector<am_SoundProperty_s>::iterator iter = source.listSoundProperties.begin(); + for(; iter<source.listSoundProperties.end(); ++iter) + { + if( soundProperty.type == iter->type ) + { + iter->value = soundProperty.value; + if(source.cacheSoundProperties.size()) + source.cacheSoundProperties[soundProperty.type] = soundProperty.value; + return (E_OK); + } + } + return (E_NON_EXISTENT); +} + +am_Error_e CAmDatabaseHandlerMap::changeSinkSoundPropertyDB(const am_SoundProperty_s & soundProperty, const am_sinkID_t sinkID) +{ + assert(sinkID!=0); + + if (!existSink(sinkID)) + { + return (E_NON_EXISTENT); + } + am_Sink_Database_s & sink = mMappedData.mSinkMap[sinkID]; + std::vector<am_SoundProperty_s>::iterator iter = sink.listSoundProperties.begin(); + for(; iter<sink.listSoundProperties.end(); ++iter) + { + if( soundProperty.type == iter->type ) + { + iter->value = soundProperty.value; + if(sink.cacheSoundProperties.size()) + sink.cacheSoundProperties[soundProperty.type] = soundProperty.value; + return (E_OK); + } + } + return (E_NON_EXISTENT); +} + +am_Error_e CAmDatabaseHandlerMap::changeCrossFaderHotSink(const am_crossfaderID_t crossfaderID, const am_HotSink_e hotsink) +{ + assert(crossfaderID!=0); + assert(hotsink!=HS_UNKNOWN); + + if (!existCrossFader(crossfaderID)) + { + return (E_NON_EXISTENT); + } + + mMappedData.mCrossfaderMap[crossfaderID].hotSink = hotsink; + return (E_OK); +} + +bool CAmDatabaseHandlerMap::isComponentConnected(const am_Gateway_s & gateway) const +{ + bool ret = isConnected(gateway); + return ret; +} + +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) +{ + if (name.empty()) + return (E_NON_EXISTENT); + am_SinkClass_Database_s const *reserved = objectMatchingPredicate<am_SinkClass_Database_s, am_sinkClass_t>(mMappedData.mSinkClassesMap, [&](const am_SinkClass_Database_s & obj){ + return name.compare(obj.name)==0; + }); + if( NULL!=reserved ) + { + sinkClassID = reserved->sinkClassID; + return E_OK; + } + return (E_NON_EXISTENT); +} + +am_Error_e am::CAmDatabaseHandlerMap::peekSourceClassID(const std::string & name, am_sourceClass_t & sourceClassID) +{ + if (name.empty()) + return (E_NON_EXISTENT); + am_SourceClass_Database_s const *ptrSource = objectMatchingPredicate<am_SourceClass_Database_s, am_sourceClass_t>(mMappedData.mSourceClassesMap, [&](const am_SourceClass_Database_s & obj){ + return name.compare(obj.name)==0; + }); + if( NULL!=ptrSource ) + { + sourceClassID = ptrSource->sourceClassID; + return E_OK; + } + return (E_NON_EXISTENT); +} + + +am_Error_e CAmDatabaseHandlerMap::changeSourceDB(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_SoundProperty_s>& listSoundProperties, const std::vector<am_CustomConnectionFormat_t>& listConnectionFormats, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties) +{ + assert(sourceID!=0); + + if (!existSource(sourceID)) + { + return (E_NON_EXISTENT); + } + + DB_COND_UPDATE_INIT; + am_sourceClass_t sourceClassOut(sourceClassID); + std::vector<am_MainSoundProperty_s> listMainSoundPropertiesOut(listMainSoundProperties); + //check if sinkClass needs to be changed + + std::unordered_map<am_sourceID_t, am_Source_Database_s>::iterator iter = mMappedData.mSourceMap.begin(); + for(; iter!=mMappedData.mSourceMap.end(); ++iter) + { + if( iter->second.sourceID == sourceID ) + { + if (sourceClassID != 0) + { + DB_COND_UPDATE(iter->second.sourceClassID, sourceClassID); + } + else if (0 == iter->second.reserved) + { + sourceClassOut = iter->second.sourceClassID; + } + break; + } + } + + //check if soundProperties need to be updated + if (!listSoundProperties.empty()) + { + mMappedData.mSourceMap.at(sourceID).listSoundProperties = listSoundProperties; + mMappedData.mSourceMap.at(sourceID).cacheSoundProperties.clear(); + } + + //check if we have to update the list of connectionformats + if (!listConnectionFormats.empty()) + { + mMappedData.mSourceMap.at(sourceID).listConnectionFormats = listConnectionFormats; + } + + //then we need to check if we need to update the listMainSoundProperties + if (sourceVisible(sourceID)) + { + if (!listMainSoundProperties.empty()) + { + DB_COND_UPDATE(mMappedData.mSourceMap.at(sourceID).listMainSoundProperties, listMainSoundProperties); + mMappedData.mSourceMap.at(sourceID).cacheMainSoundProperties.clear(); + } + else + { + getListMainSourceSoundProperties(sourceID,listMainSoundPropertiesOut); + } + } + + if (DB_COND_ISMODIFIED) + { + logInfo("DatabaseHandler::changeSource changed changeSource of source:", sourceID); + + if (mpDatabaseObserver != NULL) + { + mpDatabaseObserver->sourceUpdated(sourceID,sourceClassOut,listMainSoundPropertiesOut,sourceVisible(sourceID)); + } + } + + return (E_OK); + +} + +am_Error_e CAmDatabaseHandlerMap::changeSinkDB(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) +{ + assert(sinkID!=0); + + DB_COND_UPDATE_INIT; + am_sinkClass_t sinkClassOut(sinkClassID); + std::vector<am_MainSoundProperty_s> listMainSoundPropertiesOut(listMainSoundProperties); + + if (!existSink(sinkID)) + { + return (E_NON_EXISTENT); + } + + std::unordered_map<am_sinkID_t, am_Sink_Database_s>::iterator iter = mMappedData.mSinkMap.begin(); + for(; iter!=mMappedData.mSinkMap.end(); ++iter) + { + if (iter->second.sinkID == sinkID) + { + if (sinkClassID != 0) + { + DB_COND_UPDATE(iter->second.sinkClassID, sinkClassID); + } + else if (0 == iter->second.reserved) + { + sinkClassOut = iter->second.sinkClassID; + } + break; + } + } + + //check if soundProperties need to be updated + if (!listSoundProperties.empty()) + { + mMappedData.mSinkMap.at(sinkID).listSoundProperties = listSoundProperties; + mMappedData.mSinkMap.at(sinkID).cacheSoundProperties.clear(); + } + + //check if we have to update the list of connectionformats + if (!listConnectionFormats.empty()) + { + mMappedData.mSinkMap.at(sinkID).listConnectionFormats = listConnectionFormats; + } + + //then we need to check if we need to update the listMainSoundProperties + if (sinkVisible(sinkID)) + { + if (!listMainSoundProperties.empty()) + { + DB_COND_UPDATE(mMappedData.mSinkMap.at(sinkID).listMainSoundProperties, listMainSoundProperties); + mMappedData.mSinkMap.at(sinkID).cacheMainSoundProperties.clear(); + } + else //read out the properties + { + getListMainSinkSoundProperties(sinkID,listMainSoundPropertiesOut); + } + } + + if (DB_COND_ISMODIFIED) + { + logInfo("DatabaseHandler::changeSink changed changeSink of sink:", sinkID); + + if (mpDatabaseObserver != NULL) + { + mpDatabaseObserver->sinkUpdated(sinkID,sinkClassOut,listMainSoundPropertiesOut,sinkVisible(sinkID)); + } + } + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListMainSinkNotificationConfigurations(const am_sinkID_t sinkID, std::vector<am_NotificationConfiguration_s>& listMainNotificationConfigurations) +{ + assert(sinkID!=0); + if (!existSink(sinkID)) + return (E_DATABASE_ERROR); // todo: here we could change to non existen, but not shown in sequences + listMainNotificationConfigurations.clear(); + + listMainNotificationConfigurations = mMappedData.mSinkMap.at(sinkID).listMainNotificationConfigurations; + + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::getListMainSourceNotificationConfigurations(const am_sourceID_t sourceID, std::vector<am_NotificationConfiguration_s>& listMainNotificationConfigurations) +{ + assert(sourceID!=0); + if (!existSource(sourceID)) + return (E_DATABASE_ERROR); // todo: here we could change to non existen, but not shown in sequences + + listMainNotificationConfigurations = mMappedData.mSourceMap.at(sourceID).listMainNotificationConfigurations; + + return (E_OK); +} + +bool changeMainNotificationConfiguration(std::vector<am_NotificationConfiguration_s> & listMainNotificationConfigurations, + const am_NotificationConfiguration_s & mainNotificationConfiguration) +{ + std::vector<am_NotificationConfiguration_s>::iterator iter = listMainNotificationConfigurations.begin(); + for(; iter<listMainNotificationConfigurations.end(); ++iter) + { + if( mainNotificationConfiguration.type == iter->type ) + { +#ifdef WITH_DATABASE_CHANGE_CHECK + if( iter->status == mainNotificationConfiguration.status && iter->parameter == mainNotificationConfiguration.parameter ) + return false; +#endif + *iter = mainNotificationConfiguration; + return true; + } + } + return false; +} + +am_Error_e CAmDatabaseHandlerMap::changeMainSinkNotificationConfigurationDB(const am_sinkID_t sinkID, const am_NotificationConfiguration_s mainNotificationConfiguration) +{ + assert(sinkID!=0); + + if (!existSink(sinkID)) + { + return (E_NON_EXISTENT); + } + if(!changeMainNotificationConfiguration(mMappedData.mSinkMap.at(sinkID).listMainNotificationConfigurations, mainNotificationConfiguration)) + return (E_NO_CHANGE); + + logInfo("DatabaseHandler::changeMainSinkNotificationConfigurationDB changed MainNotificationConfiguration of source:", sinkID, "type:", mainNotificationConfiguration.type, "to status=", mainNotificationConfiguration.status, "and parameter=",mainNotificationConfiguration.parameter); + + if (mpDatabaseObserver) + mpDatabaseObserver->sinkMainNotificationConfigurationChanged(sinkID, mainNotificationConfiguration); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeMainSourceNotificationConfigurationDB(const am_sourceID_t sourceID, const am_NotificationConfiguration_s mainNotificationConfiguration) +{ + assert(sourceID!=0); + + if (!existSource(sourceID)) + { + return (E_NON_EXISTENT); + } + + if(!changeMainNotificationConfiguration(mMappedData.mSourceMap.at(sourceID).listMainNotificationConfigurations, mainNotificationConfiguration)) + return (E_NO_CHANGE); + + logInfo("DatabaseHandler::changeMainSourceNotificationConfigurationDB changed MainNotificationConfiguration of source:", sourceID, "type:", mainNotificationConfiguration.type, "to status=", mainNotificationConfiguration.status, "and parameter=",mainNotificationConfiguration.parameter); + + if (mpDatabaseObserver) + mpDatabaseObserver->sourceMainNotificationConfigurationChanged(sourceID, mainNotificationConfiguration); + return (E_OK); +} + +am_Error_e CAmDatabaseHandlerMap::changeGatewayDB(const am_gatewayID_t gatewayID, const std::vector<am_CustomConnectionFormat_t>& listSourceConnectionFormats, const std::vector<am_CustomConnectionFormat_t>& listSinkConnectionFormats, const std::vector<bool>& convertionMatrix) +{ + assert(gatewayID!=0); + + if (!existGateway(gatewayID)) + { + return (E_NON_EXISTENT); + } + + if (!listSourceConnectionFormats.empty()) + { + mMappedData.mGatewayMap.at(gatewayID).listSourceFormats = listSourceConnectionFormats; + } + + if (!listSinkConnectionFormats.empty()) + { + mMappedData.mGatewayMap.at(gatewayID).listSinkFormats = listSinkConnectionFormats; + } + + if (!convertionMatrix.empty()) + { + mListConnectionFormat.clear(); + mListConnectionFormat.insert(std::make_pair(gatewayID, convertionMatrix)); + } + + logInfo("DatabaseHandler::changeGatewayDB changed Gateway with ID", gatewayID); + + //todo: check if observer needs to be adopted. + 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; + std::vector<am_NotificationConfiguration_s>::iterator iter = listNotificationConfigurations.begin(); + for(; iter<listNotificationConfigurations.end(); ++iter) + { + if( notificationConfiguration.type == iter->type ) + { + iter->status = notificationConfiguration.status; + iter->parameter = notificationConfiguration.parameter; + changed |= true; + } + } + return changed; +} + +am_Error_e CAmDatabaseHandlerMap::changeSinkNotificationConfigurationDB(const am_sinkID_t sinkID, const am_NotificationConfiguration_s notificationConfiguration) +{ + assert(sinkID!=0); + + if (!existSink(sinkID)) + { + return (E_NON_EXISTENT); + } + if(!changeNotificationConfiguration(mMappedData.mSinkMap.at(sinkID).listNotificationConfigurations, notificationConfiguration)) + return (E_NO_CHANGE); + + logInfo("DatabaseHandler::changeMainSinkNotificationConfigurationDB changed MainNotificationConfiguration of source:", sinkID, "type:", notificationConfiguration.type, "to status=", notificationConfiguration.status, "and parameter=",notificationConfiguration.parameter); + + //todo:: inform obsever here... + return (E_NON_EXISTENT); +} + +am_Error_e CAmDatabaseHandlerMap::changeSourceNotificationConfigurationDB(const am_sourceID_t sourceID, const am_NotificationConfiguration_s notificationConfiguration) +{ + assert(sourceID!=0); + + if (!existSource(sourceID)) + { + return (E_NON_EXISTENT); + } + + if(!changeNotificationConfiguration(mMappedData.mSourceMap.at(sourceID).listNotificationConfigurations, notificationConfiguration)) + return (E_NO_CHANGE); + + logInfo("DatabaseHandler::changeSourceNotificationConfigurationDB changed MainNotificationConfiguration of source:", sourceID, "type:", notificationConfiguration.type, "to status=", notificationConfiguration.status, "and parameter=",notificationConfiguration.parameter); + + //todo:: implement observer function + 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/AudioManagerCore/src/CAmDatabaseObserver.cpp b/AudioManagerCore/src/CAmDatabaseObserver.cpp new file mode 100644 index 0000000..acac639 --- /dev/null +++ b/AudioManagerCore/src/CAmDatabaseObserver.cpp @@ -0,0 +1,242 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2012, BMW AG + * + * This file is part of GENIVI Project AudioManager. + * + * Contributions are licensed to the GENIVI Alliance under one or more + * Contribution License Agreements. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012 + * + * \file CAmDatabaseObserver.cpp + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmDatabaseObserver.h" +#include <string.h> +#include <cassert> +#include <errno.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include "CAmCommandSender.h" +#include "CAmRoutingSender.h" +#include "CAmTelnetServer.h" +#include "CAmDltWrapper.h" +#include "CAmSerializer.h" + +namespace am { + +CAmDatabaseObserver::CAmDatabaseObserver(CAmCommandSender *iCommandSender, CAmRoutingSender *iRoutingSender, CAmSocketHandler *iSocketHandler) : + mCommandSender(iCommandSender), // + mRoutingSender(iRoutingSender), // + mTelnetServer(NULL), // + mSerializer(iSocketHandler) // +{ + assert(mCommandSender!=0); + assert(mRoutingSender!=0); + assert(iSocketHandler!=0); +} + +CAmDatabaseObserver::CAmDatabaseObserver(CAmCommandSender *iCommandSender, CAmRoutingSender *iRoutingSender, CAmSocketHandler *iSocketHandler, CAmTelnetServer *iTelnetServer) : + mCommandSender(iCommandSender), // + mRoutingSender(iRoutingSender), // + mTelnetServer(iTelnetServer), // + mSerializer(iSocketHandler) // +{ + assert(mTelnetServer!=0); + assert(mCommandSender!=0); + assert(mRoutingSender!=0); + assert(iSocketHandler!=0); +} + +CAmDatabaseObserver::~CAmDatabaseObserver() +{ +} + +void CAmDatabaseObserver::newMainConnection(const am_MainConnectionType_s& mainConnection) +{ + mSerializer.asyncCall<CAmCommandSender, const am_MainConnectionType_s>(mCommandSender, &CAmCommandSender::cbNewMainConnection, mainConnection); +} + +void CAmDatabaseObserver::removedMainConnection(const am_mainConnectionID_t mainConnection) +{ + mSerializer.asyncCall<CAmCommandSender, const am_mainConnectionID_t>(mCommandSender, &CAmCommandSender::cbRemovedMainConnection, mainConnection); +} + +void CAmDatabaseObserver::newSink(const am_Sink_s& sink) +{ + mRoutingSender->addSinkLookup(sink); + if (sink.visible) + { + am_SinkType_s s; + s.availability = sink.available; + s.muteState = sink.muteState; + s.name = sink.name; + s.sinkClassID = sink.sinkClassID; + s.sinkID = sink.sinkID; + s.volume = sink.mainVolume; + mSerializer.asyncCall<CAmCommandSender, const am_SinkType_s>(mCommandSender, &CAmCommandSender::cbNewSink, s); + } +} + +void CAmDatabaseObserver::newSource(const am_Source_s& source) +{ + mRoutingSender->addSourceLookup(source); + if (source.visible) + { + am_SourceType_s s; + s.availability = source.available; + s.name = source.name; + s.sourceClassID = source.sourceClassID; + s.sourceID = source.sourceID; + mSerializer.asyncCall<CAmCommandSender, const am_SourceType_s>(mCommandSender, &CAmCommandSender::cbNewSource, s); + } +} + +void CAmDatabaseObserver::newDomain(const am_Domain_s& domain) +{ + mRoutingSender->addDomainLookup(domain); +} + +void CAmDatabaseObserver::newGateway(const am_Gateway_s& gateway) +{ + (void) 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); +} + +void CAmDatabaseObserver::removedSink(const am_sinkID_t sinkID, const bool visible) +{ + mRoutingSender->removeSinkLookup(sinkID); + + if (visible) + mSerializer.asyncCall<CAmCommandSender, const am_sinkID_t>(mCommandSender, &CAmCommandSender::cbRemovedSink, sinkID); +} + +void CAmDatabaseObserver::removedSource(const am_sourceID_t sourceID, const bool visible) +{ + mRoutingSender->removeSourceLookup(sourceID); + + if (visible) + mSerializer.asyncCall<CAmCommandSender, const am_sourceID_t>(mCommandSender, &CAmCommandSender::cbRemovedSource, sourceID); +} + +void CAmDatabaseObserver::removeDomain(const am_domainID_t domainID) +{ + mRoutingSender->removeDomainLookup(domainID); +} + +void CAmDatabaseObserver::removeGateway(const am_gatewayID_t gatewayID) +{ + (void) 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); +} + +void CAmDatabaseObserver::numberOfSinkClassesChanged() +{ + mSerializer.asyncCall<CAmCommandSender>(mCommandSender, &CAmCommandSender::cbNumberOfSinkClassesChanged); +} + +void CAmDatabaseObserver::numberOfSourceClassesChanged() +{ + mSerializer.asyncCall<CAmCommandSender>(mCommandSender, &CAmCommandSender::cbNumberOfSourceClassesChanged); +} + +void CAmDatabaseObserver::mainConnectionStateChanged(const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState) +{ + mSerializer.asyncCall<CAmCommandSender, const am_connectionID_t, const am_ConnectionState_e>(mCommandSender, &CAmCommandSender::cbMainConnectionStateChanged, connectionID, connectionState); +} + +void CAmDatabaseObserver::mainSinkSoundPropertyChanged(const am_sinkID_t sinkID, const am_MainSoundProperty_s& SoundProperty) +{ + mSerializer.asyncCall<CAmCommandSender, const am_sinkID_t, const am_MainSoundProperty_s>(mCommandSender, &CAmCommandSender::cbMainSinkSoundPropertyChanged, sinkID, SoundProperty); +} + +void CAmDatabaseObserver::mainSourceSoundPropertyChanged(const am_sourceID_t sourceID, const am_MainSoundProperty_s & SoundProperty) +{ + mSerializer.asyncCall<CAmCommandSender, const am_sourceID_t, const am_MainSoundProperty_s>(mCommandSender, &CAmCommandSender::cbMainSourceSoundPropertyChanged, sourceID, SoundProperty); +} + +void CAmDatabaseObserver::sinkAvailabilityChanged(const am_sinkID_t sinkID, const am_Availability_s & availability) +{ + mSerializer.asyncCall<CAmCommandSender, const am_sinkID_t, const am_Availability_s>(mCommandSender, &CAmCommandSender::cbSinkAvailabilityChanged, sinkID, availability); +} + +void CAmDatabaseObserver::sourceAvailabilityChanged(const am_sourceID_t sourceID, const am_Availability_s & availability) +{ + mSerializer.asyncCall<CAmCommandSender, const am_sourceID_t, const am_Availability_s>(mCommandSender, &CAmCommandSender::cbSourceAvailabilityChanged, sourceID, availability); +} + +void CAmDatabaseObserver::volumeChanged(const am_sinkID_t sinkID, const am_mainVolume_t volume) +{ + mSerializer.asyncCall<CAmCommandSender, const am_sinkID_t, const am_mainVolume_t>(mCommandSender, &CAmCommandSender::cbVolumeChanged, sinkID, volume); +} + +void CAmDatabaseObserver::sinkMuteStateChanged(const am_sinkID_t sinkID, const am_MuteState_e muteState) +{ + mSerializer.asyncCall<CAmCommandSender, const am_sinkID_t, const am_MuteState_e>(mCommandSender, &CAmCommandSender::cbSinkMuteStateChanged, sinkID, muteState); +} + +void CAmDatabaseObserver::systemPropertyChanged(const am_SystemProperty_s& SystemProperty) +{ + mSerializer.asyncCall<CAmCommandSender, const am_SystemProperty_s>(mCommandSender, &CAmCommandSender::cbSystemPropertyChanged, SystemProperty); +} + +void CAmDatabaseObserver::timingInformationChanged(const am_mainConnectionID_t mainConnection, const am_timeSync_t time) +{ + mSerializer.asyncCall<CAmCommandSender, const am_mainConnectionID_t, const am_timeSync_t>(mCommandSender, &CAmCommandSender::cbTimingInformationChanged, mainConnection, time); +} + +void CAmDatabaseObserver::sinkUpdated(const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible) +{ + if (visible) + mSerializer.asyncCall<CAmCommandSender, const am_sinkID_t, const am_sinkClass_t, const std::vector<am_MainSoundProperty_s> >(mCommandSender, &CAmCommandSender::cbSinkUpdated, sinkID, sinkClassID, listMainSoundProperties); +} + +void CAmDatabaseObserver::sourceUpdated(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible) +{ + if (visible) + mSerializer.asyncCall<CAmCommandSender, const am_sourceID_t, const am_sourceClass_t, const std::vector<am_MainSoundProperty_s> >(mCommandSender, &CAmCommandSender::cbSinkUpdated, sourceID, sourceClassID, listMainSoundProperties); +} + +void CAmDatabaseObserver::sinkMainNotificationConfigurationChanged(const am_sinkID_t sinkID, const am_NotificationConfiguration_s mainNotificationConfiguration) +{ + mSerializer.asyncCall<CAmCommandSender, const am_sinkID_t, const am_NotificationConfiguration_s> (mCommandSender, &CAmCommandSender::cbSinkMainNotificationConfigurationChanged, sinkID, mainNotificationConfiguration); +} + +void CAmDatabaseObserver::sourceMainNotificationConfigurationChanged(const am_sourceID_t sourceID, const am_NotificationConfiguration_s mainNotificationConfiguration) +{ + mSerializer.asyncCall<CAmCommandSender, const am_sourceID_t, const am_NotificationConfiguration_s>(mCommandSender, &CAmCommandSender::cbSourceMainNotificationConfigurationChanged, sourceID, mainNotificationConfiguration); +} + +} diff --git a/AudioManagerCore/src/CAmLog.cpp b/AudioManagerCore/src/CAmLog.cpp new file mode 100644 index 0000000..f68f660 --- /dev/null +++ b/AudioManagerCore/src/CAmLog.cpp @@ -0,0 +1,101 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2012, BMW AG + * + * This file is part of GENIVI Project AudioManager. + * + * Contributions are licensed to the GENIVI Alliance under one or more + * Contribution License Agreements. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Aleksandar Donchev, aleksander.donchev@partner.bmw.de BMW 2013 + * + * \file CAmLog.cpp + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmLog.h" + + +void CAmLog::CAmFileLogger::generateLogFilename(std::string &result) +{ + static uint32_t logFileID = 1; + time_t rawtime; + time (&rawtime); + + std::ostringstream stream; + stream << DEFAULT_LOG_FOLDER << DEFAULT_LOGFILE_PREFIX << logFileID << "_" << rawtime << DEFAULT_LOGFILE_EXT; + logFileID++; + result = stream.str(); +} + +CAmLog::CAmFileLogger::~CAmFileLogger() +{ + if (mOutputStream) + { + std::ofstream* of = static_cast<std::ofstream*>(mOutputStream); + of->close(); + DEL(mOutputStream) + } +} + +CAmLog::CAmLog(const eCAmLogType type ):mLogType(type) +{ + instantiateLogger(type); +} + +CAmLog::CAmLog():mLogType(eCAmLogStdout) +{ + instantiateLogger((const eCAmLogType)eCAmLogStdout); +} + +CAmLog::~CAmLog() +{ + releaseLogger(); +} + +void CAmLog::releaseLogger() +{ + if(mLogger) + DEL(mLogger) +} + +void CAmLog::instantiateLogger( const eCAmLogType type) +{ + if( eCAmLogStdout == type ) + mLogger = new CAmStdOutLogger(); + else if( eCAmLogFile == type ) + { + std::string filename(""); + CAmLog::CAmFileLogger::generateLogFilename(filename); + mLogger = new CAmFileLogger(filename); + } +} + +CAmLog *CAmLog::getDefaultLog() +{ + static CAmLog theInstance; + return &theInstance; +} + +void CAmLog::setLogType( const eCAmLogType type) +{ + if(mLogType!=type) + { + mLogType = type; + releaseLogger(); + instantiateLogger(type); + } +} + +eCAmLogType CAmLog::getLogType() const +{ + return mLogType; +} diff --git a/AudioManagerCore/src/CAmRouter.cpp b/AudioManagerCore/src/CAmRouter.cpp new file mode 100644 index 0000000..f98bf11 --- /dev/null +++ b/AudioManagerCore/src/CAmRouter.cpp @@ -0,0 +1,884 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2012, BMW AG + * + * This file is part of GENIVI Project AudioManager. + * + * Contributions are licensed to the GENIVI Alliance under one or more + * Contribution License Agreements. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012 + * \author Aleksandar Donchev, Aleksander.Donchev@partner.bmw.de BMW 2013,2014 + * + * \file CAmRouter.cpp + * For further information see http://www.genivi.org/. + * + */ + +#include <cassert> +#include <algorithm> +#include <vector> +#include <iterator> +#include "CAmRouter.h" +#include "IAmDatabaseHandler.h" +#include "CAmControlSender.h" +#include "CAmDltWrapper.h" + + + +namespace am { + + +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), + mOnlyFreeConversionNodes(false), + mRoutingGraph(), + mNodeListSources(), + mNodeListSinks(), + mNodeListGateways(), + mNodeListConverters() +{ + 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 + * @param sourceID + * @param sinkID + * @param returnList this list contains a set of routes + * @return E_OK in case of success + */ +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(); + am_Source_s source; + am_Sink_s sink; + am_Error_e error = mpDatabaseHandler->getSourceInfoDB(sourceID, source); + if(error!=E_OK) + return error; + error = mpDatabaseHandler->getSinkInfoDB(sinkID, sink); + if(error!=E_OK) + return error; + error = getRoute(onlyfree, source, sink, returnList); + return error; +} + + +am_Error_e CAmRouter::getRoute(const bool onlyfree, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes) +{ + am_Error_e error; + load(onlyfree); + + CAmRoutingNode* pRootSource = sourceNodeWithID(aSource.sourceID); + CAmRoutingNode* pRootSink = sinkNodeWithID(aSink.sinkID); + + assert(pRootSource); + assert(pRootSink); + +#ifdef TRACE_GRAPH + mRoutingGraph.trace([&](const CAmRoutingNode & node, const std::vector<CAmVertex<am_RoutingNodeData_s,uint16_t>*> & list) { + std::cout << "Node " << node.getIndex() << " :"; + ((CAmRoutingNode &)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 + + std::vector<std::vector<CAmRoutingNode*>> pathNodes; + error = getAllPaths(*pRootSource, *pRootSink, listRoutes, pathNodes); + return error; +} + +void CAmRouter::load(const bool onlyFree) +{ + clear(); + mOnlyFreeConversionNodes = onlyFree; + +#if defined (WITH_DATABASE_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; +#endif + am_RoutingNodeData_s nodeDataSrc; + nodeDataSrc.type = CAmNodeDataType::SOURCE; + mpDatabaseHandler->enumerateSources([&](const am_Source_s & obj){ +#if defined (WITH_DATABASE_STORAGE) + listSources.push_back(obj); + nodeDataSrc.data.source = &listSources.back(); +#else + nodeDataSrc.data.source = (am_Source_s*)&obj; +#endif + mNodeListSources[nodeDataSrc.data.source->domainID].push_back(&mRoutingGraph.addNode(nodeDataSrc)); + }); + am_RoutingNodeData_s nodeDataSink; + nodeDataSink.type = CAmNodeDataType::SINK; + mpDatabaseHandler->enumerateSinks([&](const am_Sink_s & obj){ +#if defined (WITH_DATABASE_STORAGE) + listSinks.push_back(obj); + nodeDataSrc.data.sink = &listSinks.back(); +#else + nodeDataSink.data.sink = (am_Sink_s*)&obj; +#endif + mNodeListSinks[nodeDataSink.data.sink->domainID].push_back(&mRoutingGraph.addNode(nodeDataSink)); + }); + am_RoutingNodeData_s nodeDataGateway; + nodeDataGateway.type = CAmNodeDataType::GATEWAY; + mpDatabaseHandler->enumerateGateways([&](const am_Gateway_s & obj){ +#if defined (WITH_DATABASE_STORAGE) + listGateways.push_back(obj); + nodeDataSrc.data.gateway = &listGateways.back(); +#else + nodeDataGateway.data.gateway = (am_Gateway_s*)&obj; +#endif + mNodeListGateways[nodeDataGateway.data.gateway->controlDomainID].push_back(&mRoutingGraph.addNode(nodeDataGateway)); + }); + am_RoutingNodeData_s nodeDataConverter; + nodeDataConverter.type = CAmNodeDataType::CONVERTER; + mpDatabaseHandler->enumerateConverters([&](const am_Converter_s & obj){ +#if defined (WITH_DATABASE_STORAGE) + listConverters.push_back(obj); + nodeDataSrc.data.converter = &listConverters.back(); +#else + nodeDataConverter.data.converter = (am_Converter_s*)&obj; +#endif + mNodeListConverters[nodeDataConverter.data.converter->domainID].push_back(&mRoutingGraph.addNode(nodeDataConverter)); + }); + +#ifdef ROUTING_BUILD_CONNECTIONS + constructConverterConnections(); + constructGatewayConnections(); + constructSourceSinkConnections(); +#endif +} + +void CAmRouter::clear() +{ + mRoutingGraph.clear(); + mNodeListSources.clear(); + mNodeListSinks.clear(); + mNodeListGateways.clear(); + mNodeListConverters.clear(); +} + +CAmRoutingNode* CAmRouter::sinkNodeWithID(const am_sinkID_t sinkID) +{ + CAmRoutingNode* result = NULL; + for(auto it = mNodeListSinks.begin(); it!=mNodeListSinks.end(); it++) + { + result = sinkNodeWithID(sinkID, it->first); + if(result) + return result; + } + return result; +} + +CAmRoutingNode* CAmRouter::sinkNodeWithID(const am_sinkID_t sinkID, const am_domainID_t domainID) +{ + CAmRoutingNode* result = NULL; + std::vector<CAmRoutingNode*> & value = mNodeListSinks[domainID]; + auto iter = std::find_if(value.begin(), value.end(), [sinkID](CAmRoutingNode* node){ + return node->getData().data.sink->sinkID==sinkID; + }); + if(iter!=value.end()) + result = *iter; + return result; +} + +CAmRoutingNode* CAmRouter::sourceNodeWithID(const am_sourceID_t sourceID) +{ + CAmRoutingNode* result = NULL; + for(auto it = mNodeListSources.begin(); it!=mNodeListSources.end(); it++) + { + result = sourceNodeWithID(sourceID, it->first); + if(result) + return result; + } + return result; +} + +CAmRoutingNode* CAmRouter::sourceNodeWithID(const am_sourceID_t sourceID, const am_domainID_t domainID) +{ + CAmRoutingNode* result = NULL; + std::vector<CAmRoutingNode*> & value = mNodeListSources[domainID]; + auto iter = std::find_if(value.begin(), value.end(), [sourceID](CAmRoutingNode* node){ + return node->getData().data.source->sourceID==sourceID; + }); + if(iter!=value.end()) + result = *iter; + return result; +} + +CAmRoutingNode* CAmRouter::converterNodeWithSinkID(const am_sinkID_t sinkID, const am_domainID_t domainID) +{ + CAmRoutingNode* result = NULL; + std::vector<CAmRoutingNode*> & value = mNodeListConverters[domainID]; + auto iter = std::find_if(value.begin(), value.end(), [sinkID](CAmRoutingNode* node){ + return node->getData().data.converter->sinkID==sinkID; + }); + if(iter!=value.end()) + result = *iter; + return result; +} + +CAmRoutingNode* CAmRouter::gatewayNodeWithSinkID(const am_sinkID_t sinkID) +{ + for(auto it = mNodeListGateways.begin(); it!=mNodeListGateways.end(); it++) + { + std::vector<CAmRoutingNode*> & value = it->second; + auto iter = std::find_if(value.begin(), value.end(), [sinkID](CAmRoutingNode* node){ + return node->getData().data.gateway->sinkID==sinkID; + }); + if(iter!=value.end()) + return *iter; + } + return NULL; +} + +#ifdef ROUTING_BUILD_CONNECTIONS + +void CAmRouter::constructSourceSinkConnections() +{ + std::vector<am_CustomConnectionFormat_t> intersection; + for(auto itSrc = mNodeListSources.begin(); itSrc!=mNodeListSources.end(); itSrc++) + { + for(auto it = itSrc->second.begin(); it!=itSrc->second.end(); it++) + { + CAmRoutingNode* srcNode = *it; + am_RoutingNodeData_s & srcNodeData = srcNode->getData(); + am_Source_s * source = srcNodeData.data.source; + for(auto itSink = mNodeListSinks[itSrc->first].begin(); itSink!=mNodeListSinks[itSrc->first].end(); itSink++) + { + CAmRoutingNode* sinkNode = *itSink; + am_RoutingNodeData_s & sinkNodeData = sinkNode->getData(); + am_Sink_s * sink = sinkNodeData.data.sink; + + intersection.clear(); + //Check whether the hidden sink formats match the source formats... + listPossibleConnectionFormats(source->listConnectionFormats, sink->listConnectionFormats, intersection); + if(intersection.size()>0)//OK match source -> sink + { + mRoutingGraph.connectNodes(*srcNode, *sinkNode, CF_UNKNOWN, 1); + } + } + } + } +} + +void CAmRouter::constructGatewayConnections() +{ + std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats; + for(auto iter = mNodeListGateways.begin(); iter!=mNodeListGateways.end(); iter++) + { + for(auto it = iter->second.begin(); it!=iter->second.end(); it++) + { + CAmRoutingNode* gatewayNode = *it; + am_RoutingNodeData_s & gatewayNodeData = gatewayNode->getData(); + am_Gateway_s * gateway = gatewayNodeData.data.gateway; + //Get only gateways with end point in current source domain + if(!mOnlyFreeConversionNodes || !isComponentConnected(*gateway)) + { + //Get the sink connected to the gateway... + CAmRoutingNode *gatewaySinkNode = this->sinkNodeWithID(gateway->sinkID, gateway->domainSinkID); + if(gatewaySinkNode) + { + am_RoutingNodeData_s & gatewaySinkData = gatewaySinkNode->getData(); + //Check whether the hidden sink formats match the source formats... + sourceFormats.clear(); + sinkFormats.clear(); + if(getAllowedFormatsFromConvMatrix(gateway->convertionMatrix, gateway->listSourceFormats, gateway->listSinkFormats, sourceFormats, sinkFormats)) + { + CAmRoutingNode *gatewaySourceNode = this->sourceNodeWithID(gateway->sourceID, gateway->domainSourceID); + if(gatewaySourceNode) + { + //Connections hidden_sink->gateway->hidden_source + mRoutingGraph.connectNodes(*gatewaySinkNode, *gatewayNode, CF_UNKNOWN, 1); + mRoutingGraph.connectNodes(*gatewayNode, *gatewaySourceNode, CF_UNKNOWN, 1); + } + } + } + } + } + } +} + +void CAmRouter::constructConverterConnections() +{ + std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats; + + for(auto iter = mNodeListConverters.begin(); iter!=mNodeListConverters.end(); iter++) + { + for(auto it = iter->second.begin(); it!=iter->second.end(); it++) + { + CAmRoutingNode* converterNode = *it; + am_RoutingNodeData_s & converterNodeData = converterNode->getData(); + am_Converter_s * converter = converterNodeData.data.converter; + //Get only converters with end point in current source domain + if(!mOnlyFreeConversionNodes || !isComponentConnected(*converter)) + { + //Get the sink connected to the converter... + CAmRoutingNode *converterSinkNode = this->sinkNodeWithID(converter->sinkID, converter->domainID); + if(converterSinkNode) + { + am_RoutingNodeData_s & converterSinkData = converterSinkNode->getData(); + //Check whether the hidden sink formats match the source formats... + sourceFormats.clear(); + sinkFormats.clear(); + if(getAllowedFormatsFromConvMatrix(converter->convertionMatrix, converter->listSourceFormats, converter->listSinkFormats, sourceFormats, sinkFormats)) + { + CAmRoutingNode *converterSourceNode = this->sourceNodeWithID(converter->sourceID, converter->domainID); + if(converterSourceNode) + { + //Connections hidden_sink->converter->hidden_source + mRoutingGraph.connectNodes(*converterSinkNode, *converterNode, CF_UNKNOWN, 1); + mRoutingGraph.connectNodes(*converterNode, *converterSourceNode, CF_UNKNOWN, 1); + } + } + } + } + } + } +} +#else + +void CAmRouter::getVerticesForSource(const CAmRoutingNode & node, CAmRoutingListVertices & list) +{ + am_RoutingNodeData_s & srcNodeData = ((CAmRoutingNode*)&node)->getData(); + std::vector<am_CustomConnectionFormat_t> intersection; + am_Source_s * source = srcNodeData.data.source; + std::vector<CAmRoutingNode*> & sinks = mNodeListSinks[source->domainID]; + for(auto itSink = sinks.begin(); itSink!=sinks.end(); itSink++) + { + CAmRoutingNode* sinkNode = *itSink; + am_RoutingNodeData_s & sinkNodeData = sinkNode->getData(); + am_Sink_s * sink = sinkNodeData.data.sink; + + intersection.clear(); + //Check whether the hidden sink formats match the source formats... + listPossibleConnectionFormats(source->listConnectionFormats, sink->listConnectionFormats, intersection); + if(intersection.size()>0)//OK match source -> sink + { + list.emplace_back(sinkNode, CF_UNKNOWN, 1); + } + } +} + +void CAmRouter::getVerticesForSink(const CAmRoutingNode & node, CAmRoutingListVertices & list) +{ + am_RoutingNodeData_s & sinkNodeData = ((CAmRoutingNode*)&node)->getData(); + std::vector<am_CustomConnectionFormat_t> intersection; + am_Sink_s * sink = sinkNodeData.data.sink; + + CAmRoutingNode *converterNode = converterNodeWithSinkID(sink->sinkID, sink->domainID); + if(converterNode) + { + std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats; + am_RoutingNodeData_s & converterData = converterNode->getData(); + am_Converter_s * converter = converterData.data.converter; + if(!mOnlyFreeConversionNodes || !isComponentConnected(*converter)) + { + if(getAllowedFormatsFromConvMatrix(converter->convertionMatrix, converter->listSourceFormats, converter->listSinkFormats, sourceFormats, sinkFormats)) + list.emplace_back(converterNode, CF_UNKNOWN, 1); + } + } + else + { + std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats; + CAmRoutingNode *gatewayNode = gatewayNodeWithSinkID(sink->sinkID); + if(gatewayNode) + { + std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats; + am_RoutingNodeData_s & gatewayData = gatewayNode->getData(); + am_Gateway_s * gateway = gatewayData.data.gateway; + if(!mOnlyFreeConversionNodes || !isComponentConnected(*gateway)) + { + if(getAllowedFormatsFromConvMatrix(gateway->convertionMatrix, gateway->listSourceFormats, gateway->listSinkFormats, sourceFormats, sinkFormats)) + list.emplace_back(gatewayNode, CF_UNKNOWN, 1); + } + } + } + +} + +void CAmRouter::getVerticesForConverter(const CAmRoutingNode & node, CAmRoutingListVertices & list) +{ + std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats; + am_RoutingNodeData_s & converterNodeData = ((CAmRoutingNode*)&node)->getData(); + am_Converter_s * converter = converterNodeData.data.converter; + //Get only converters with end point in current source domain + if(getAllowedFormatsFromConvMatrix(converter->convertionMatrix, converter->listSourceFormats, converter->listSinkFormats, sourceFormats, sinkFormats)) + { + CAmRoutingNode *converterSourceNode = this->sourceNodeWithID(converter->sourceID, converter->domainID); + if(converterSourceNode) + { + list.emplace_back(converterSourceNode, CF_UNKNOWN, 1); + } + } +} + +void CAmRouter::getVerticesForGateway(const CAmRoutingNode & node, CAmRoutingListVertices & list) +{ + am_RoutingNodeData_s & gatewayNodeData = ((CAmRoutingNode*)&node)->getData(); + std::vector<am_CustomConnectionFormat_t> sourceFormats, sinkFormats; + am_Gateway_s * gateway = gatewayNodeData.data.gateway; + if(getAllowedFormatsFromConvMatrix(gateway->convertionMatrix, gateway->listSourceFormats, gateway->listSinkFormats, sourceFormats, sinkFormats)) + { + CAmRoutingNode *gatewaySourceNode = this->sourceNodeWithID(gateway->sourceID, gateway->domainSourceID); + if(gatewaySourceNode) + { + //Connections hidden_sink->gateway->hidden_source + list.emplace_back(gatewaySourceNode, CF_UNKNOWN, 1); + } + } +} + +void CAmRouter::getVerticesForNode( + const CAmRoutingNode & node, + CAmRoutingListVertices & list + ) +{ + am_RoutingNodeData_s & nodeData = ((CAmRoutingNode*)&node)->getData(); + if(nodeData.type==CAmNodeDataType::SOURCE) + { + getVerticesForSource(node, list); + } + else if(nodeData.type==CAmNodeDataType::SINK) + { + getVerticesForSink(node, list); + } + else if(nodeData.type==CAmNodeDataType::CONVERTER) + { + getVerticesForConverter(node, list); + } + else if(nodeData.type==CAmNodeDataType::GATEWAY) + { + getVerticesForGateway(node, list); + } +} + +#endif + +am_Error_e CAmRouter::determineConnectionFormatsForPath(am_Route_s & routeObjects, std::vector<CAmRoutingNode*> & nodes) +{ + std::vector<am_RoutingElement_s>::iterator routingElementIterator = routeObjects.route.begin(); + std::vector<CAmRoutingNode*>::iterator nodeIterator = nodes.begin(); + if( routingElementIterator!= routeObjects.route.end() && nodeIterator!=nodes.end() ) + return doConnectionFormatsForPath(routeObjects, nodes, routingElementIterator, nodeIterator); + return E_OK; +} + +am_Error_e CAmRouter::doConnectionFormatsForPath(am_Route_s & routeObjects, + std::vector<CAmRoutingNode*> & nodes, + std::vector<am_RoutingElement_s>::iterator routingElementIterator, + std::vector<CAmRoutingNode*>::iterator nodeIterator) +{ + am_Error_e returnError = E_NOT_POSSIBLE; + std::vector<am_CustomConnectionFormat_t> listConnectionFormats; + std::vector<am_CustomConnectionFormat_t> listMergeConnectionFormats; + + std::vector<CAmRoutingNode*>::iterator currentNodeIterator = nodeIterator; + std::vector<am_RoutingElement_s>::iterator currentRoutingElementIterator = routingElementIterator; + + if (currentRoutingElementIterator!=routeObjects.route.begin()) + { + std::vector<am_CustomConnectionFormat_t> listConnectionFormats; + std::vector<am_RoutingElement_s>::iterator tempIterator = (currentRoutingElementIterator-1); + CAmRoutingNode * currentNode = *currentNodeIterator; + getSourceSinkPossibleConnectionFormats(currentNodeIterator+1, currentNodeIterator+2, listConnectionFormats); + + if(currentNode->getData().type==CAmNodeDataType::GATEWAY) + { + am_Gateway_s *gateway = currentNode->getData().data.gateway; + getMergeConnectionFormats(gateway, tempIterator->connectionFormat, listConnectionFormats, listMergeConnectionFormats); + } + else if(currentNode->getData().type==CAmNodeDataType::CONVERTER) + { + am_Converter_s *converter = currentNode->getData().data.converter; + getMergeConnectionFormats(converter, tempIterator->connectionFormat, listConnectionFormats, listMergeConnectionFormats); + } + currentNodeIterator+=3; + } + else + { + CAmRoutingNode * currentNode = *currentNodeIterator; + assert(currentNode->getData().type==CAmNodeDataType::SOURCE); + + currentNodeIterator++; + assert(currentNodeIterator!=nodes.end()); + + CAmRoutingNode * nodeSink = *currentNodeIterator; + assert(nodeSink->getData().type==CAmNodeDataType::SINK); + + am_Source_s *source = currentNode->getData().data.source; + am_Sink_s *sink = nodeSink->getData().data.sink; + 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); +} + +#ifdef ROUTING_BUILD_CONNECTIONS + +void CAmRouter::getShortestPath(const CAmRoutingNode & source, + const CAmRoutingNode & destination, + std::vector<CAmRoutingNode*> & resultPath) +{ + mRoutingGraph.getShortestPath(source, destination, resultPath); +} + +void CAmRouter::getShortestPath(CAmRoutingNode & aSource, CAmRoutingNode & aSink, + am_Route_s & resultPath, std::vector<CAmRoutingNode*> & 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, CAmRoutingNode &)> cb = [&](const am_GraphPathPosition_e, CAmRoutingNode & object) + { + resultNodesPath.insert(resultNodesPath.begin(), (CAmRoutingNode*)&object); + am_RoutingNodeData_s & routingData = object.getData(); + if(routingData.type==CAmNodeDataType::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==CAmNodeDataType::SOURCE) + { + element->domainID = routingData.data.source->domainID; + element->sourceID = routingData.data.source->sourceID; + element->connectionFormat = CF_UNKNOWN; + } + }; + mRoutingGraph.getShortestPath(aSource, aSink, cb); +} + +#endif + +am_Error_e CAmRouter::getAllPaths(CAmRoutingNode & aSource, + CAmRoutingNode & aSink, + std::vector<am_Route_s> & resultPath, + std::vector<std::vector<CAmRoutingNode*>> & resultNodesPath, + const bool includeCycles) +{ +#ifndef ROUTING_BUILD_CONNECTIONS + bool cycles = false; +#else + bool cycles = includeCycles; +#endif + if(((CAmRoutingNode*)&aSource)->getData().type!=CAmNodeDataType::SOURCE || + ((CAmRoutingNode*)&aSink)->getData().type!=CAmNodeDataType::SINK) + return E_NOT_POSSIBLE; + + uint8_t errorsCount = 0, successCount = 0; + generateAllPaths(aSource, aSink, cycles, [&](const std::vector<CAmRoutingNode*> & 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==CAmNodeDataType::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==CAmNodeDataType::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<CAmRoutingNode*> &)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<<"\nSuccessfully determined connection formats for path from source:"<<nextRoute.sourceID<<" to sink:"<<nextRoute.sinkID<<"\n"; + for(auto it = nextRoute.route.begin(); it!=nextRoute.route.end(); it++) + { + am_RoutingElement_s & routingElement = *it; + std::cout<<"[" + <<routingElement.sourceID + <<"->" + <<routingElement.sinkID + <<" cf:" + <<routingElement.connectionFormat + <<" d:" + <<routingElement.domainID + <<"]"; + } + std::cout<<"\n"; +#endif + successCount++; + } + }); + if(successCount) + return E_OK; + if(errorsCount) + return E_NOT_POSSIBLE; + return E_OK; +} + +bool CAmRouter::shouldGoInDomain(const std::vector<am_domainID_t> & visitedDomains, const am_domainID_t nodeDomainID) +{ + if(visitedDomains.size()) + { + if(visitedDomains.back()==nodeDomainID) + return true; + + for(auto it=visitedDomains.begin();it!=visitedDomains.end()-1; it++) + { + if(nodeDomainID==*it) + return false; + } + } + return true; +} + +void CAmRouter::generateAllPaths(const CAmRoutingNode & src, + const CAmRoutingNode & dst, + const bool includeCycles, + std::function<void(const std::vector<CAmRoutingNode*> & path)> cb) +{ + if(!includeCycles) + { + std::vector<CAmRoutingNode*> visited; + std::vector<am_domainID_t> visitedDomains; + visited.push_back((CAmRoutingNode*)&src); + visitedDomains.push_back(((CAmRoutingNode*)&src)->getData().domainID()); + ((CAmRoutingNode*)&src)->setStatus(GES_VISITED); + goThroughAllPaths(dst, visited, visitedDomains, cb); + } + else + mRoutingGraph.getAllPaths(src, dst, cb); +} + +void CAmRouter::goThroughAllPaths(const CAmRoutingNode & dst, + std::vector<CAmRoutingNode*> & visited, + std::vector<am_domainID_t> & visitedDomains, + std::function<void(const std::vector<CAmRoutingNode*> & path)> cb) +{ +#ifndef ROUTING_BUILD_CONNECTIONS + CAmRoutingListVertices vertices; + getVerticesForNode(*visited.back(), vertices); + const CAmRoutingListVertices * nodes = &vertices; +#else + const CAmRoutingListVertices * nodes = mRoutingGraph.getVertexList()[visited.back()->getIndex()]; +#endif + CAmRoutingListVertices::const_iterator vItr(nodes->begin()); + for (; vItr != nodes->end(); ++vItr) + { + const CAmRoutingVertex & vertex = (*vItr); + if(vertex.getNode()->getStatus()!=GES_NOT_VISITED || !shouldGoInDomain(visitedDomains, vertex.getNode()->getData().domainID())) + continue; + if (vertex.getNode()==&dst) + { + vertex.getNode()->setStatus(GES_IN_PROGRESS); + visited.push_back(vertex.getNode()); + visitedDomains.push_back(vertex.getNode()->getData().domainID()); + //notify observer + cb(visited); + //remove last node from the list + auto last = visited.end()-1; + visited.erase(last); + visitedDomains.erase(visitedDomains.end()-1); + vertex.getNode()->setStatus(GES_NOT_VISITED); + break; + } + } + vItr = nodes->begin(); + //bfs like loop + for (; vItr != nodes->end(); ++vItr) + { + const CAmRoutingVertex & vertex = (*vItr); + if(vertex.getNode()->getStatus()!=GES_NOT_VISITED + ||vertex.getNode()==&dst || + !shouldGoInDomain(visitedDomains, vertex.getNode()->getData().domainID())) + continue; + vertex.getNode()->setStatus(GES_IN_PROGRESS); + visited.push_back(vertex.getNode()); + visitedDomains.push_back(vertex.getNode()->getData().domainID()); + goThroughAllPaths(dst, visited, visitedDomains, cb); + //remove last node from the list + auto last = visited.end()-1; + visited.erase(last); + visitedDomains.erase(visitedDomains.end()-1); + vertex.getNode()->setStatus(GES_NOT_VISITED); + } +} + +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) +{ + 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; +} + +void CAmRouter::listPossibleConnectionFormats(std::vector<am_CustomConnectionFormat_t> & inListSourceFormats, + std::vector<am_CustomConnectionFormat_t> & inListSinkFormats, + std::vector<am_CustomConnectionFormat_t> & outListFormats) +{ + 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); +} + + +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(); + 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(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); + + //iterate line-wise through the matrix and add more formats + do + { + if (*matrixIterator) + { + listFormats.push_back(listSourceFormats.at((matrixIterator - convertionMatrix.begin()) / listSinkFormats.size())); + } + std::advance(matrixIterator, listSinkFormats.size()); + } while (convertionMatrix.end() - matrixIterator > 0); + + return listFormats.size(); +} + + +void CAmRouter::getSourceSinkPossibleConnectionFormats(std::vector<CAmRoutingNode*>::iterator iteratorSource, + std::vector<CAmRoutingNode*>::iterator iteratorSink, + std::vector<am_CustomConnectionFormat_t> & outConnectionFormats) +{ + CAmRoutingNode * nodeSink = *iteratorSink; + assert(nodeSink->getData().type==CAmNodeDataType::SINK); + + CAmRoutingNode * nodeSource = *iteratorSource; + assert(nodeSource->getData().type==CAmNodeDataType::SOURCE); + + am_Source_s *source = nodeSource->getData().data.source; + am_Sink_s *sink = nodeSink->getData().data.sink; + listPossibleConnectionFormats(source->listConnectionFormats, sink->listConnectionFormats, outConnectionFormats); +} + + +} diff --git a/AudioManagerCore/src/CAmRoutingReceiver.cpp b/AudioManagerCore/src/CAmRoutingReceiver.cpp new file mode 100644 index 0000000..4189936 --- /dev/null +++ b/AudioManagerCore/src/CAmRoutingReceiver.cpp @@ -0,0 +1,620 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2012, BMW AG + * + * This file is part of GENIVI Project AudioManager. + * + * Contributions are licensed to the GENIVI Alliance under one or more + * Contribution License Agreements. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012 + * + * \file CAmRoutingReceiver.cpp + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmRoutingReceiver.h" +#include <cassert> +#include <algorithm> +#include "IAmDatabaseHandler.h" +#include "CAmRoutingSender.h" +#include "CAmControlSender.h" +#include "CAmDltWrapper.h" +#include "CAmSocketHandler.h" + +namespace am +{ + +CAmRoutingReceiver::CAmRoutingReceiver(IAmDatabaseHandler *iDatabaseHandler, CAmRoutingSender *iRoutingSender, CAmControlSender *iControlSender, CAmSocketHandler *iSocketHandler) : + mpDatabaseHandler(iDatabaseHandler), // + mpRoutingSender(iRoutingSender), // + mpControlSender(iControlSender), // + mpSocketHandler(iSocketHandler), // + mpDBusWrapper(NULL), // + mListStartupHandles(), // + mListRundownHandles(), // + handleCount(0), // + mWaitStartup(false), // + mWaitRundown(false), // + mLastStartupError(E_OK), // + mLastRundownError(E_OK) // +{ + assert(mpDatabaseHandler!=NULL); + assert(mpRoutingSender!=NULL); + assert(mpControlSender!=NULL); + assert(mpSocketHandler!=NULL); +} + +CAmRoutingReceiver::CAmRoutingReceiver(IAmDatabaseHandler *iDatabaseHandler, CAmRoutingSender *iRoutingSender, CAmControlSender *iControlSender, CAmSocketHandler *iSocketHandler, CAmDbusWrapper *iDBusWrapper) : + mpDatabaseHandler(iDatabaseHandler), // + mpRoutingSender(iRoutingSender), // + mpControlSender(iControlSender), // + mpSocketHandler(iSocketHandler), // + mpDBusWrapper(iDBusWrapper), // + mListStartupHandles(), // + mListRundownHandles(), // + handleCount(0), // + mWaitStartup(false), // + mWaitRundown(false), + mLastStartupError(E_OK), // + mLastRundownError(E_OK) // +{ + assert(mpDatabaseHandler!=NULL); + assert(mpRoutingSender!=NULL); + assert(mpControlSender!=NULL); + assert(mpSocketHandler!=NULL); + assert(mpDBusWrapper!=NULL); +} + +CAmRoutingReceiver::~CAmRoutingReceiver() +{ +} + +void CAmRoutingReceiver::ackConnect(const am_Handle_s handle, const am_connectionID_t connectionID, const am_Error_e error) +{ + mpRoutingSender->removeHandle(handle); + if (error == am_Error_e::E_OK) + { + mpDatabaseHandler->changeConnectionFinal(connectionID); + } + else + { + mpDatabaseHandler->removeConnection(connectionID); + mpRoutingSender->removeConnectionLookup(connectionID); + } + mpControlSender->cbAckConnect(handle, error); +} + +void CAmRoutingReceiver::ackDisconnect(const am_Handle_s handle, const am_connectionID_t connectionID, const am_Error_e error) +{ + + //so we will remove the connection anyway no matter what is answered + mpRoutingSender->removeHandle(handle); + mpDatabaseHandler->removeConnection(connectionID); + mpRoutingSender->removeConnectionLookup(connectionID); + mpControlSender->cbAckDisconnect(handle, error); +} + +void CAmRoutingReceiver::ackSetSinkVolumeChange(const am_Handle_s handle, const am_volume_t volume, const am_Error_e error) +{ + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if (error== am_Error_e::E_OK || error== am_Error_e::E_ABORTED) + { + mpDatabaseHandler->changeSinkVolume(handleData.sinkID, volume); + } + + if(error == am_Error_e::E_OK || handleData.volume!=volume) + { + logError("ackSetSinkVolumeChange volumes do not match, requested volume",handleData.volume,"returned volume",volume); + } + mpControlSender->cbAckSetSinkVolumeChange(handle, volume, error); +} + +void CAmRoutingReceiver::ackSetSourceVolumeChange(const am_Handle_s handle, const am_volume_t volume, const am_Error_e error) +{ + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if (error== am_Error_e::E_OK || error== am_Error_e::E_ABORTED) + { + mpDatabaseHandler->changeSourceVolume(handleData.sourceID, volume); + } + + if(error == E_OK || handleData.volume!=volume) + { + logError("ackSetSourceVolumeChange volumes do not match, requested volume",handleData.volume,"returned volume",volume); + } + mpControlSender->cbAckSetSourceVolumeChange(handle, volume, error); +} + +void CAmRoutingReceiver::ackSetSourceState(const am_Handle_s handle, const am_Error_e error) +{ + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + //no error, so we can write the change into the database; + if (error == am_Error_e::E_OK) + { + mpDatabaseHandler->changeSourceState(handleData.sourceID, handleData.sourceState); + } + + mpControlSender->cbAckSetSourceState(handle, error); +} + +void CAmRoutingReceiver::ackSetSinkSoundProperty(const am_Handle_s handle, const am_Error_e error) +{ + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if (error==am_Error_e::E_OK) + { + mpDatabaseHandler->changeSinkSoundPropertyDB(handleData.soundPropery, handleData.sinkID); + } + + mpControlSender->cbAckSetSinkSoundProperty(handle, error); + +} + +void am::CAmRoutingReceiver::ackSetSinkSoundProperties(const am_Handle_s handle, const am_Error_e error) +{ + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if (error==am_Error_e::E_OK) + { + std::vector<am_SoundProperty_s>::const_iterator it = handleData.soundProperties->begin(); + for (; it != handleData.soundProperties->end(); ++it) + { + mpDatabaseHandler->changeSinkSoundPropertyDB(*it, handleData.sinkID); + } + } + + try + { + delete handleData.soundProperties; + } + catch(...) + { + logError("exception while deleting handleData while ackSetSinkSoundProperties"); + } + mpControlSender->cbAckSetSinkSoundProperties(handle, error); +} + +void CAmRoutingReceiver::ackSetSourceSoundProperty(const am_Handle_s handle, const am_Error_e error) +{ + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if(error==am_Error_e::E_OK) + { + mpDatabaseHandler->changeSourceSoundPropertyDB(handleData.soundPropery, handleData.sourceID); + } + mpControlSender->cbAckSetSourceSoundProperty(handle, error); +} + +void am::CAmRoutingReceiver::ackSetSourceSoundProperties(const am_Handle_s handle, const am_Error_e error) +{ + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if(error==am_Error_e::E_OK) + { + std::vector<am_SoundProperty_s>::const_iterator it = handleData.soundProperties->begin(); + for (; it != handleData.soundProperties->end(); ++it) + { + mpDatabaseHandler->changeSourceSoundPropertyDB(*it, handleData.sourceID); + } + } + + try + { + delete handleData.soundProperties; + } + catch(...) + { + logError("exception while deleting handleData while ackSetSourceSoundProperties"); + } + mpControlSender->cbAckSetSourceSoundProperties(handle, error); +} + +void CAmRoutingReceiver::ackCrossFading(const am_Handle_s handle, const am_HotSink_e hotSink, const am_Error_e error) +{ + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if(error==am_Error_e::E_OK) + { + mpDatabaseHandler->changeCrossFaderHotSink(handleData.crossfaderID, hotSink); + } + mpControlSender->cbAckCrossFade(handle, hotSink, error); +} + +void CAmRoutingReceiver::ackSourceVolumeTick(const am_Handle_s handle, const am_sourceID_t sourceID, const am_volume_t volume) +{ + mpControlSender->hookSystemSourceVolumeTick(handle, sourceID, volume); +} + +void CAmRoutingReceiver::ackSinkVolumeTick(const am_Handle_s handle, const am_sinkID_t sinkID, const am_volume_t volume) +{ + mpControlSender->hookSystemSinkVolumeTick(handle, sinkID, volume); +} + +am_Error_e CAmRoutingReceiver::peekDomain(const std::string & name, am_domainID_t & domainID) +{ + return (mpDatabaseHandler->peekDomain(name, domainID)); + +} + +am_Error_e CAmRoutingReceiver::registerDomain(const am_Domain_s & domainData, am_domainID_t & domainID) +{ + return (mpControlSender->hookSystemRegisterDomain(domainData, domainID)); +} + +am_Error_e CAmRoutingReceiver::deregisterDomain(const am_domainID_t domainID) +{ + return (mpControlSender->hookSystemDeregisterDomain(domainID)); +} + +am_Error_e CAmRoutingReceiver::registerGateway(const am_Gateway_s & gatewayData, am_gatewayID_t & gatewayID) +{ + 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)); +} + +am_Error_e CAmRoutingReceiver::registerSink(const am_Sink_s & sinkData, am_sinkID_t & sinkID) +{ + return (mpControlSender->hookSystemRegisterSink(sinkData, sinkID)); +} + +am_Error_e CAmRoutingReceiver::deregisterSink(const am_sinkID_t sinkID) +{ + return (mpControlSender->hookSystemDeregisterSink(sinkID)); +} + +am_Error_e CAmRoutingReceiver::peekSource(const std::string & name, am_sourceID_t & sourceID) +{ + return (mpDatabaseHandler->peekSource(name, sourceID)); +} + +am_Error_e CAmRoutingReceiver::registerSource(const am_Source_s & sourceData, am_sourceID_t & sourceID) +{ + return (mpControlSender->hookSystemRegisterSource(sourceData, sourceID)); +} + +am_Error_e CAmRoutingReceiver::deregisterSource(const am_sourceID_t sourceID) +{ + return (mpControlSender->hookSystemDeregisterSource(sourceID)); +} + +am_Error_e CAmRoutingReceiver::registerCrossfader(const am_Crossfader_s & crossfaderData, am_crossfaderID_t & crossfaderID) +{ + return (mpControlSender->hookSystemRegisterCrossfader(crossfaderData, crossfaderID)); +} + +am_Error_e CAmRoutingReceiver::deregisterCrossfader(const am_crossfaderID_t crossfaderID) +{ + return (mpControlSender->hookSystemDeregisterCrossfader(crossfaderID)); +} + +void CAmRoutingReceiver::hookInterruptStatusChange(const am_sourceID_t sourceID, const am_InterruptState_e interruptState) +{ + return (mpControlSender->hookSystemInterruptStateChange(sourceID, interruptState)); +} + +void CAmRoutingReceiver::hookDomainRegistrationComplete(const am_domainID_t domainID) +{ + mpControlSender->hookSystemDomainRegistrationComplete(domainID); +} + +void CAmRoutingReceiver::hookSinkAvailablityStatusChange(const am_sinkID_t sinkID, const am_Availability_s & availability) +{ + mpControlSender->hookSystemSinkAvailablityStateChange(sinkID, availability); +} + +void CAmRoutingReceiver::hookSourceAvailablityStatusChange(const am_sourceID_t sourceID, const am_Availability_s & availability) +{ + mpControlSender->hookSystemSourceAvailablityStateChange(sourceID, availability); +} + +void CAmRoutingReceiver::hookDomainStateChange(const am_domainID_t domainID, const am_DomainState_e domainState) +{ + mpControlSender->hookSystemDomainStateChange(domainID, domainState); +} + +void CAmRoutingReceiver::hookTimingInformationChanged(const am_connectionID_t connectionID, const am_timeSync_t delay) +{ + mpDatabaseHandler->changeConnectionTimingInformation(connectionID, delay); + mpControlSender->hookSystemSingleTimingInformationChanged(connectionID,delay); +} + +void CAmRoutingReceiver::sendChangedData(const std::vector<am_EarlyData_s> & earlyData) +{ + mpControlSender->hookSystemReceiveEarlyData(earlyData); +} + +am_Error_e CAmRoutingReceiver::peekSinkClassID(const std::string& name, am_sinkClass_t& sinkClassID) +{ + return (mpDatabaseHandler->peekSinkClassID(name, sinkClassID)); +} + +am_Error_e CAmRoutingReceiver::peekSourceClassID(const std::string& name, am_sourceClass_t& sourceClassID) +{ + return (mpDatabaseHandler->peekSourceClassID(name, sourceClassID)); +} + +#ifdef WITH_DBUS_WRAPPER +am_Error_e CAmRoutingReceiver::getDBusConnectionWrapper(CAmDbusWrapper *& dbusConnectionWrapper) const +{ + dbusConnectionWrapper = mpDBusWrapper; + return (E_OK); +#else +am_Error_e CAmRoutingReceiver::getDBusConnectionWrapper(CAmDbusWrapper *& ) const +{ + return (E_UNKNOWN); +#endif +} + +am_Error_e CAmRoutingReceiver::getSocketHandler(CAmSocketHandler *& socketHandler) const +{ + socketHandler = mpSocketHandler; + return (E_OK); +} + +void CAmRoutingReceiver::getInterfaceVersion(std::string & version) const +{ + version = RoutingVersion; +} + +void CAmRoutingReceiver::confirmRoutingReady(const uint16_t handle, const am_Error_e error) +{ + if (error!=E_OK) + mLastStartupError=error; + mListStartupHandles.erase(std::remove(mListStartupHandles.begin(), mListStartupHandles.end(), handle), mListStartupHandles.end()); + if (mWaitStartup && mListStartupHandles.empty()) + mpControlSender->confirmRoutingReady(mLastStartupError); +} + +void CAmRoutingReceiver::confirmRoutingRundown(const uint16_t handle, const am_Error_e error) +{ + if (error!=E_OK) + mLastRundownError=error; + mListRundownHandles.erase(std::remove(mListRundownHandles.begin(), mListRundownHandles.end(), handle), mListRundownHandles.end()); + if (mWaitRundown && mListRundownHandles.empty()) + mpControlSender->confirmRoutingRundown(mLastRundownError); +} + +uint16_t am::CAmRoutingReceiver::getStartupHandle() +{ + uint16_t handle = ++handleCount; //todo: handle overflow + mListStartupHandles.push_back(handle); + return (handle); +} + +uint16_t am::CAmRoutingReceiver::getRundownHandle() +{ + uint16_t handle = ++handleCount; //todo: handle overflow + mListRundownHandles.push_back(handle); + return (handle); +} + +void am::CAmRoutingReceiver::waitOnStartup(bool startup) +{ + mWaitStartup = startup; + mLastStartupError=E_OK; +} + +void CAmRoutingReceiver::ackSinkNotificationConfiguration(const am_Handle_s handle, const am_Error_e error) +{ + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if(error==am_Error_e::E_OK) + { + mpDatabaseHandler->changeSinkNotificationConfigurationDB(handleData.sinkID,*handleData.notificationConfiguration); + } + + try + { + delete handleData.notificationConfiguration; + } + catch(...) + { + logError("exception while deleting handleData while ackSinkNotificationConfiguration"); + } + mpControlSender->cbAckSetSinkNotificationConfiguration(handle,error); +} + +void CAmRoutingReceiver::ackSourceNotificationConfiguration(const am_Handle_s handle, const am_Error_e error) +{ + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if(error==am_Error_e::E_OK) + { + mpDatabaseHandler->changeSourceNotificationConfigurationDB(handleData.sourceID,*handleData.notificationConfiguration); + } + try + { + delete handleData.notificationConfiguration; + } + catch(...) + { + logError("exception while deleting handleData while ackSourceNotificationConfiguration"); + } + mpControlSender->cbAckSetSourceNotificationConfiguration(handle,error); +} + +am_Error_e CAmRoutingReceiver::updateGateway(const am_gatewayID_t gatewayID, const std::vector<am_CustomConnectionFormat_t>& listSourceFormats, const std::vector<am_CustomConnectionFormat_t>& listSinkFormats, const std::vector<bool>& convertionMatrix) +{ + 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)); +} + +am_Error_e CAmRoutingReceiver::updateSource(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_SoundProperty_s>& listSoundProperties, const std::vector<am_CustomConnectionFormat_t>& listConnectionFormats, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties) +{ + return (mpControlSender->hookSystemUpdateSource(sourceID,sourceClassID,listSoundProperties,listConnectionFormats,listMainSoundProperties)); +} + +void CAmRoutingReceiver::ackSetVolumes(const am_Handle_s handle, const std::vector<am_Volumes_s>& listvolumes, const am_Error_e error) +{ + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if(error==am_Error_e::E_OK) + { + std::vector<am_Volumes_s>::const_iterator iterator (listvolumes.begin()); + + for (;iterator!=listvolumes.end();++iterator) + { + if (iterator->volumeType==VT_SINK) + { + mpDatabaseHandler->changeSinkVolume(iterator->volumeID.sink,iterator->volume); + } + else if (iterator->volumeType==VT_SOURCE) + { + mpDatabaseHandler->changeSourceVolume(iterator->volumeID.source,iterator->volume); + } + } + + } + + try + { + delete handleData.listVolumes; + } + catch(...) + { + logError("exception while deleting handleData while ackSetVolumes"); + } + + mpControlSender->cbAckSetVolume(handle,listvolumes,error); +} + +void CAmRoutingReceiver::hookSinkNotificationDataChange(const am_sinkID_t sinkID, const am_NotificationPayload_s& payload) +{ + logInfo("CAmRoutingReceiver::hookSinkNotificationDataChange received, sinkID=",sinkID,"type=",payload.type,"notificationValue=",payload.value); + mpControlSender->hookSinkNotificationDataChanged(sinkID,payload); +} + +void CAmRoutingReceiver::hookSourceNotificationDataChange(const am_sourceID_t sourceID, const am_NotificationPayload_s& payload) +{ + logInfo("CAmRoutingReceiver::hookSourceNotificationDataChange received, sinkID=",sourceID,"type=",payload.type,"notificationValue=",payload.value); + mpControlSender->hookSourceNotificationDataChanged(sourceID,payload); +} + +am_Error_e CAmRoutingReceiver::getDomainOfSink(const am_sinkID_t sinkID, am_domainID_t& domainID) const +{ + return (mpDatabaseHandler->getDomainOfSink(sinkID,domainID)); +} + +am_Error_e CAmRoutingReceiver::getDomainOfSource(const am_sourceID_t sourceID, am_domainID_t& domainID) const +{ + return (mpDatabaseHandler->getDomainOfSource(sourceID,domainID)); +} + +am_Error_e CAmRoutingReceiver::getDomainOfCrossfader(const am_crossfaderID_t crossfader, am_domainID_t& domainID) const +{ + return (mpDatabaseHandler->getDomainOfCrossfader(crossfader,domainID)); +} + +void CAmRoutingReceiver::waitOnRundown(bool rundown) +{ + mWaitRundown = rundown; + mLastRundownError=E_OK; +} + +am_Error_e CAmRoutingSender::removeConnectionLookup(const am_connectionID_t connectionID) +{ + ConnectionInterfaceMap::iterator iter = mMapConnectionInterface.begin(); + iter = mMapConnectionInterface.find(connectionID); + if (iter != mMapConnectionInterface.end()) + { + mMapConnectionInterface.erase(iter); + return (E_OK); + } + return (E_UNKNOWN); +} + +} diff --git a/AudioManagerCore/src/CAmRoutingSender.cpp b/AudioManagerCore/src/CAmRoutingSender.cpp new file mode 100644 index 0000000..35e35b8 --- /dev/null +++ b/AudioManagerCore/src/CAmRoutingSender.cpp @@ -0,0 +1,838 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2012, BMW AG + * + * This file is part of GENIVI Project AudioManager. + * + * Contributions are licensed to the GENIVI Alliance under one or more + * Contribution License Agreements. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012 + * + * \file CAmRoutingSender.cpp + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmRoutingSender.h" +#include <utility> +#include <dirent.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <dlfcn.h> +#include <cassert> +#include <iostream> +#include <sstream> +#include <stdexcept> +#include "CAmRoutingReceiver.h" +#include "TAmPluginTemplate.h" +#include "CAmDltWrapper.h" + +namespace am +{ + +#define REQUIRED_INTERFACE_VERSION_MAJOR 1 //!< major interface version. All versions smaller than this will be rejected +#define REQUIRED_INTERFACE_VERSION_MINOR 0 //!< minor interface version. All versions smaller than this will be rejected + +CAmRoutingSender::CAmRoutingSender(const std::vector<std::string>& listOfPluginDirectories) : + mHandleCount(0), // + mlistActiveHandles(), // + mListInterfaces(), // + mMapConnectionInterface(), // + mMapCrossfaderInterface(), // + mMapDomainInterface(), // + mMapSinkInterface(), // + mMapSourceInterface(), // + mMapHandleInterface(), // + mpRoutingReceiver() +{ + + if (listOfPluginDirectories.empty()) + { + logError("CAmRoutingSender::CAmRoutingSender: List of routingplugins is empty"); + } + + std::vector<std::string> sharedLibraryNameList; + std::vector<std::string>::const_iterator dirIter = listOfPluginDirectories.begin(); + std::vector<std::string>::const_iterator dirIterEnd = listOfPluginDirectories.end(); + + // search communicator plugins in configured directories + for (; dirIter < dirIterEnd; ++dirIter) + { + const char* directoryName = dirIter->c_str(); + logInfo("Searching for HookPlugins in", directoryName); + DIR *directory = opendir(directoryName); + + if (!directory) + { + logError("RoutingSender::RoutingSender Error opening directory: ", directoryName); + continue; + } + + // iterate content of directory + struct dirent *itemInDirectory = 0; + while ((itemInDirectory = readdir(directory))) + { + unsigned char entryType = itemInDirectory->d_type; + std::string entryName = itemInDirectory->d_name; + std::string fullName = *dirIter + "/" + entryName; + + bool regularFile = (entryType == DT_REG || entryType == DT_LNK); + bool sharedLibExtension = ("so" == entryName.substr(entryName.find_last_of(".") + 1)); + + // Handle cases where readdir() could not determine the file type + if (entryType == DT_UNKNOWN) { + struct stat buf; + + if (stat(fullName.c_str(), &buf)) { + logInfo(__PRETTY_FUNCTION__,"Failed to stat file: ", entryName, errno); + continue; + } + + regularFile = S_ISREG(buf.st_mode); + } + + if (regularFile && sharedLibExtension) + { + logInfo("RoutingSender::RoutingSender adding file: ", entryName); + std::string name(directoryName); + sharedLibraryNameList.push_back(name + "/" + entryName); + } + else + { + logInfo("RoutingSender::RoutingSender PluginSearch ignoring file :", entryName); + } + } + + closedir(directory); + } + + // iterate all communicator plugins and start them + std::vector<std::string>::iterator iter = sharedLibraryNameList.begin(); + std::vector<std::string>::iterator iterEnd = sharedLibraryNameList.end(); + + for (; iter != iterEnd; ++iter) + { + logInfo("RoutingSender::RoutingSender try loading: ", *iter); + + IAmRoutingSend* (*createFunc)(); + void* tempLibHandle = NULL; + createFunc = getCreateFunction<IAmRoutingSend*()>(*iter, tempLibHandle); + + if (!createFunc) + { + logError("RoutingSender::RoutingSender Entry point of RoutingPlugin not found"); + continue; + } + + IAmRoutingSend* router = createFunc(); + + if (!router) + { + logError("RoutingSender::RoutingSender RoutingPlugin initialization failed. Entry Function not callable"); + dlclose(tempLibHandle); + continue; + } + + InterfaceNamePairs routerInterface; + routerInterface.routingInterface = router; + + //check libversion + std::string version, cVersion(RoutingVersion); + router->getInterfaceVersion(version); + uint16_t minorVersion, majorVersion, cMinorVersion, cMajorVersion; + std::istringstream(version.substr(0, 1)) >> majorVersion; + std::istringstream(version.substr(2, 1)) >> minorVersion; + std::istringstream(cVersion.substr(0, 1)) >> cMajorVersion; + std::istringstream(cVersion.substr(2, 1)) >> cMinorVersion; + + + + if (majorVersion < cMajorVersion || ((majorVersion == cMajorVersion) && (minorVersion > cMinorVersion))) + { + logError("Routing initialization failed. Version of Interface to old"); + dlclose(tempLibHandle); + continue; + } + + //here, the busname is saved together with the interface. Later The domains will register with the name and sinks, sources etc with the domain.... + router->returnBusName(routerInterface.busName); + assert(!routerInterface.busName.empty()); + mListInterfaces.push_back(routerInterface); + mListLibraryHandles.push_back(tempLibHandle); + } +} + +CAmRoutingSender::~CAmRoutingSender() +{ + //unloadLibraries(); + HandlesMap::iterator it = mlistActiveHandles.begin(); + + //clean up heap if existent + for (; it != mlistActiveHandles.end(); ++it) + { + if (it->first.handleType == H_SETSINKSOUNDPROPERTIES || it->first.handleType == H_SETSOURCESOUNDPROPERTIES) + { + delete it->second.soundProperties; + } + } +} + +am_Error_e CAmRoutingSender::startupInterfaces(CAmRoutingReceiver *iRoutingReceiver) +{ + mpRoutingReceiver = iRoutingReceiver; + am_Error_e returnError = E_OK; + + std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin(); + std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end(); + for (; iter < iterEnd; ++iter) + { + am_Error_e error = (*iter).routingInterface->startupInterface(iRoutingReceiver); + if (error != E_OK) + { + returnError = error; + } + } + return (returnError); +} + +am_Error_e CAmRoutingSender::asyncAbort(const am_Handle_s& handle) +{ + HandleInterfaceMap::iterator iter = mMapHandleInterface.begin(); + iter = mMapHandleInterface.find(handle.handle); + if (iter != mMapHandleInterface.end()) + { + removeHandle(handle); + return (iter->second->asyncAbort(handle)); + } + + return (E_NON_EXISTENT); +} + +am_Error_e CAmRoutingSender::asyncConnect(am_Handle_s& handle, const am_connectionID_t connectionID, const am_sourceID_t sourceID, const am_sinkID_t sinkID, const am_CustomConnectionFormat_t connectionFormat) +{ + am_handleData_c handleData; + SinkInterfaceMap::iterator iter = mMapSinkInterface.begin(); + iter = mMapSinkInterface.find(sinkID); + if (iter != mMapSinkInterface.end()) + { + handleData.connectionID = connectionID; + handle = createHandle(handleData, H_CONNECT); + mMapConnectionInterface.insert(std::make_pair(connectionID, iter->second)); + mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); + am_Error_e syncError(iter->second->asyncConnect(handle, connectionID, sourceID, sinkID, connectionFormat)); + + if (syncError) + { + removeHandle(handle); + removeConnectionLookup(connectionID); + } + return(syncError); + + } + + return (E_NON_EXISTENT); +} + +am_Error_e CAmRoutingSender::asyncDisconnect(am_Handle_s& handle, const am_connectionID_t connectionID) +{ + am_handleData_c handleData; + ConnectionInterfaceMap::iterator iter = mMapConnectionInterface.begin(); + iter = mMapConnectionInterface.find(connectionID); + if (iter != mMapConnectionInterface.end()) + { + handleData.connectionID = connectionID; + handle = createHandle(handleData, H_DISCONNECT); + mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); + am_Error_e syncError(iter->second->asyncDisconnect(handle, connectionID)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); + } + + return (E_NON_EXISTENT); +} + +am_Error_e CAmRoutingSender::asyncSetSinkVolume(am_Handle_s& handle, const am_sinkID_t sinkID, const am_volume_t volume, const am_CustomRampType_t ramp, const am_time_t time) +{ + am_handleData_c handleData; + SinkInterfaceMap::iterator iter = mMapSinkInterface.begin(); + iter = mMapSinkInterface.find(sinkID); + if (iter != mMapSinkInterface.end()) + { + handleData.sinkID = sinkID; + handleData.volume = volume; + handle = createHandle(handleData, H_SETSINKVOLUME); + mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); + am_Error_e syncError(iter->second->asyncSetSinkVolume(handle, sinkID, volume, ramp, time)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); + } + return (E_NON_EXISTENT); +} + +am_Error_e CAmRoutingSender::asyncSetSourceVolume(am_Handle_s& handle, const am_sourceID_t sourceID, const am_volume_t volume, const am_CustomRampType_t ramp, const am_time_t time) +{ + am_handleData_c handleData; + SourceInterfaceMap::iterator iter = mMapSourceInterface.begin(); + iter = mMapSourceInterface.find(sourceID); + if (iter != mMapSourceInterface.end()) + { + handleData.sourceID = sourceID; + handleData.volume = volume; + handle = createHandle(handleData, H_SETSOURCEVOLUME); + mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); + am_Error_e syncError(iter->second->asyncSetSourceVolume(handle, sourceID, volume, ramp, time)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); + } + return (E_NON_EXISTENT); +} + +am_Error_e CAmRoutingSender::asyncSetSourceState(am_Handle_s& handle, const am_sourceID_t sourceID, const am_SourceState_e state) +{ + am_handleData_c handleData; + SourceInterfaceMap::iterator iter = mMapSourceInterface.begin(); + iter = mMapSourceInterface.find(sourceID); + if (iter != mMapSourceInterface.end()) + { + handleData.sourceID = sourceID; + handleData.sourceState = state; + handle = createHandle(handleData, H_SETSOURCESTATE); + mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); + am_Error_e syncError(iter->second->asyncSetSourceState(handle, sourceID, state)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); + } + return (E_NON_EXISTENT); +} + +am_Error_e CAmRoutingSender::asyncSetSinkSoundProperty(am_Handle_s& handle, const am_sinkID_t sinkID, const am_SoundProperty_s & soundProperty) +{ + am_handleData_c handleData; + SinkInterfaceMap::iterator iter = mMapSinkInterface.begin(); + iter = mMapSinkInterface.find(sinkID); + if (iter != mMapSinkInterface.end()) + { + handleData.sinkID = sinkID; + handleData.soundPropery = soundProperty; + handle = createHandle(handleData, H_SETSINKSOUNDPROPERTY); + mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); + am_Error_e syncError(iter->second->asyncSetSinkSoundProperty(handle, sinkID, soundProperty)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); + } + return (E_NON_EXISTENT); +} + +am_Error_e CAmRoutingSender::asyncSetSourceSoundProperty(am_Handle_s& handle, const am_sourceID_t sourceID, const am_SoundProperty_s & soundProperty) +{ + am_handleData_c handleData; + SourceInterfaceMap::iterator iter = mMapSourceInterface.begin(); + iter = mMapSourceInterface.find(sourceID); + if (iter != mMapSourceInterface.end()) + { + handleData.sourceID = sourceID; + handleData.soundPropery = soundProperty; + handle = createHandle(handleData, H_SETSOURCESOUNDPROPERTY); + mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); + am_Error_e syncError(iter->second->asyncSetSourceSoundProperty(handle, sourceID, soundProperty)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); + } + return (E_NON_EXISTENT); +} + +am_Error_e CAmRoutingSender::asyncSetSourceSoundProperties(am_Handle_s& handle, const std::vector<am_SoundProperty_s> & listSoundProperties, const am_sourceID_t sourceID) +{ + am_handleData_c handleData; + SourceInterfaceMap::iterator iter = mMapSourceInterface.begin(); + iter = mMapSourceInterface.find(sourceID); + if (iter != mMapSourceInterface.end()) + { + handleData.sourceID = sourceID; + handleData.soundProperties = new std::vector<am_SoundProperty_s>(listSoundProperties); + handle = createHandle(handleData, H_SETSOURCESOUNDPROPERTIES); + mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); + am_Error_e syncError(iter->second->asyncSetSourceSoundProperties(handle, sourceID, listSoundProperties)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); + } + return (E_NON_EXISTENT); +} + +am_Error_e CAmRoutingSender::asyncSetSinkSoundProperties(am_Handle_s& handle, const std::vector<am_SoundProperty_s> & listSoundProperties, const am_sinkID_t sinkID) +{ + am_handleData_c handleData; + SinkInterfaceMap::iterator iter = mMapSinkInterface.begin(); + iter = mMapSinkInterface.find(sinkID); + if (iter != mMapSinkInterface.end()) + { + handleData.sinkID = sinkID; + handleData.soundProperties = new std::vector<am_SoundProperty_s>(listSoundProperties); + handle = createHandle(handleData, H_SETSINKSOUNDPROPERTIES); + mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); + am_Error_e syncError(iter->second->asyncSetSinkSoundProperties(handle, sinkID, listSoundProperties)); + if (syncError) + { + removeHandle(handle); + delete handleData.soundProperties; + } + return(syncError); + } + return (E_NON_EXISTENT); + +} + +am_Error_e CAmRoutingSender::asyncCrossFade(am_Handle_s& handle, const am_crossfaderID_t crossfaderID, const am_HotSink_e hotSink, const am_CustomRampType_t rampType, const am_time_t time) +{ + am_handleData_c handleData; + CrossfaderInterfaceMap::iterator iter = mMapCrossfaderInterface.begin(); + iter = mMapCrossfaderInterface.find(crossfaderID); + if (iter != mMapCrossfaderInterface.end()) + { + handleData.crossfaderID = crossfaderID; + handleData.hotSink = hotSink; + handle = createHandle(handleData, H_CROSSFADE); + mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); + am_Error_e syncError(iter->second->asyncCrossFade(handle, crossfaderID, hotSink, rampType, time)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); + } + return (E_NON_EXISTENT); +} + +am_Error_e CAmRoutingSender::setDomainState(const am_domainID_t domainID, const am_DomainState_e domainState) +{ + DomainInterfaceMap::iterator iter = mMapDomainInterface.begin(); + iter = mMapDomainInterface.find(domainID); + if (iter != mMapDomainInterface.end()) + return (iter->second->setDomainState(domainID, domainState)); + return (E_NON_EXISTENT); +} + +/** + * @author Christian + * this adds the domain to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface. + * This must be done whenever a domain is registered. + */ +am_Error_e CAmRoutingSender::addDomainLookup(const am_Domain_s& domainData) +{ + std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin(); + std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end(); + for (; iter < iterEnd; ++iter) + { + if ((*iter).busName.compare(domainData.busname) == 0) + { + mMapDomainInterface.insert(std::make_pair(domainData.domainID, (*iter).routingInterface)); + return (E_OK); + } + } + logError(__PRETTY_FUNCTION__," Could not find busname for bus",domainData.busname); + return (E_UNKNOWN); +} + +/** + * @author Christian + * this adds the Source to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface. + * This must be done whenever a Source is registered. + */ +am_Error_e CAmRoutingSender::addSourceLookup(const am_Source_s& sourceData) +{ + DomainInterfaceMap::iterator iter = mMapDomainInterface.begin(); + iter = mMapDomainInterface.find(sourceData.domainID); + if (iter != mMapDomainInterface.end()) + { + mMapSourceInterface.insert(std::make_pair(sourceData.sourceID, iter->second)); + return (E_OK); + } + logError(__PRETTY_FUNCTION__," Could not find domainInterface for domainID",sourceData.domainID); + return (E_UNKNOWN); +} + +/** + * @author Christian + * this adds the Sink to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface. + * This must be done whenever a Sink is registered. + */ +am_Error_e CAmRoutingSender::addSinkLookup(const am_Sink_s& sinkData) +{ + DomainInterfaceMap::iterator iter = mMapDomainInterface.begin(); + iter = mMapDomainInterface.find(sinkData.domainID); + if (iter != mMapDomainInterface.end()) + { + mMapSinkInterface.insert(std::make_pair(sinkData.sinkID, iter->second)); + return (E_OK); + } + logError(__PRETTY_FUNCTION__,"Could not find domainInterface for domainID",sinkData.domainID); + return (E_UNKNOWN); +} + +/** + * @author Christian + * this adds the Crossfader to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface. + * This must be done whenever a Crossfader is registered. + */ +am_Error_e CAmRoutingSender::addCrossfaderLookup(const am_Crossfader_s& crossfaderData) +{ + DomainInterfaceMap::iterator iter = mMapSourceInterface.begin(); + iter = mMapSourceInterface.find(crossfaderData.sourceID); + if (iter != mMapSourceInterface.end()) + { + mMapSourceInterface.insert(std::make_pair(crossfaderData.crossfaderID, iter->second)); + return (E_OK); + } + logError(__PRETTY_FUNCTION__," Could not find sourceInterface for source",crossfaderData.sourceID); + return (E_UNKNOWN); +} + +/** + * @author Christian + * this removes the Domain to the lookup table of the Router. This must be done everytime a domain is deregistered. + */ +am_Error_e CAmRoutingSender::removeDomainLookup(const am_domainID_t domainID) +{ + DomainInterfaceMap::iterator iter = mMapDomainInterface.begin(); + iter = mMapDomainInterface.find(domainID); + if (iter != mMapDomainInterface.end()) + { + mMapDomainInterface.erase(iter); + return (E_OK); + } + + return (E_NON_EXISTENT); +} + +/** + * @author Christian + * this removes the Source to the lookup table of the Router. This must be done everytime a source is deregistered. + */ +am_Error_e CAmRoutingSender::removeSourceLookup(const am_sourceID_t sourceID) +{ + SourceInterfaceMap::iterator iter = mMapSourceInterface.begin(); + iter = mMapSourceInterface.find(sourceID); + if (iter != mMapSourceInterface.end()) + { + mMapSourceInterface.erase(iter); + return (E_OK); + } + + return (E_NON_EXISTENT); +} + +/** + * @author Christian + * this removes the Sink to the lookup table of the Router. This must be done everytime a sink is deregistered. + */ +am_Error_e CAmRoutingSender::removeSinkLookup(const am_sinkID_t sinkID) +{ + SinkInterfaceMap::iterator iter = mMapSinkInterface.begin(); + iter = mMapSinkInterface.find(sinkID); + if (iter != mMapSinkInterface.end()) + { + mMapSinkInterface.erase(iter); + return (E_OK); + } + + return (E_NON_EXISTENT); +} + +/** + * @author Christian + * this removes the Crossfader to the lookup table of the Router. This must be done everytime a crossfader is deregistered. + */ +am_Error_e CAmRoutingSender::removeCrossfaderLookup(const am_crossfaderID_t crossfaderID) +{ + CrossfaderInterfaceMap::iterator iter = mMapCrossfaderInterface.begin(); + iter = mMapCrossfaderInterface.find(crossfaderID); + if (iter != mMapCrossfaderInterface.end()) + { + mMapCrossfaderInterface.erase(iter); + return (E_OK); + } + + return (E_NON_EXISTENT); +} + +/** + * removes a handle from the list + * @param handle to be removed + * @return E_OK in case of success + */ +am_Error_e CAmRoutingSender::removeHandle(const am_Handle_s& handle) +{ + if (mlistActiveHandles.erase(handle)) + { + return (E_OK); + } + logError(__PRETTY_FUNCTION__,"Could not remove handle",handle.handle); + return (E_UNKNOWN); +} + +am_Error_e CAmRoutingSender::getListHandles(std::vector<am_Handle_s> & listHandles) const +{ + listHandles.clear(); + HandlesMap::const_iterator it = mlistActiveHandles.begin(); + for (; it != mlistActiveHandles.end(); ++it) + { + listHandles.push_back(it->first); + } + return (E_OK); +} + +/** + * creates a handle and adds it to the list of handles + * @param handleData the data that should be saves together with the handle + * @param type the type of handle to be created + * @return the handle + */ +am_Handle_s CAmRoutingSender::createHandle(const am_handleData_c& handleData, const am_Handle_e type) +{ + am_Handle_s handle; + if (++mHandleCount>=1024) //defined by 10 bit (out if structure!) + mHandleCount=1; + handle.handle = mHandleCount; + handle.handleType = type; + 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); +} + +/** + * returns the data that belong to handles + * @param handle the handle + * @return a class holding the handle data + */ +am_Error_e CAmRoutingSender::returnHandleData(const am_Handle_s handle,CAmRoutingSender::am_handleData_c& handleData) const +{ + HandlesMap::const_iterator it = mlistActiveHandles.begin(); + it = mlistActiveHandles.find(handle); + if (it!=mlistActiveHandles.end()) + { + handleData = it->second; + return (am_Error_e::E_OK); + } + handleData.sinkID=0; + logError(__PRETTY_FUNCTION__,"could not find handle data for handle",handle.handle,handle.handleType); + return (am_Error_e::E_NON_EXISTENT); +} + +void CAmRoutingSender::setRoutingReady() +{ + mpRoutingReceiver->waitOnStartup(false); + + //create a list of handles + std::vector<uint16_t> listStartupHandles; + for (size_t i = 0; i < mListInterfaces.size(); i++) + { + listStartupHandles.push_back(mpRoutingReceiver->getStartupHandle()); + } + + //set the receiver ready to wait for replies + mpRoutingReceiver->waitOnStartup(true); + + std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin(); + std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end(); + std::vector<uint16_t>::const_iterator handleIter(listStartupHandles.begin()); + for (; iter < iterEnd; ++iter) + { + (*iter).routingInterface->setRoutingReady(*(handleIter++)); + } +} + +void CAmRoutingSender::setRoutingRundown() +{ + mpRoutingReceiver->waitOnRundown(false); + //create a list of handles + std::vector<uint16_t> listStartupHandles; + for (size_t i = 0; i < mListInterfaces.size(); i++) + { + listStartupHandles.push_back(mpRoutingReceiver->getRundownHandle()); + } + + //set the receiver ready to wait for replies + mpRoutingReceiver->waitOnRundown(true); + + std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin(); + std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end(); + std::vector<uint16_t>::const_iterator handleIter(listStartupHandles.begin()); + for (; iter < iterEnd; ++iter) + { + (*iter).routingInterface->setRoutingRundown(*(handleIter++)); + } +} + +am_Error_e CAmRoutingSender::asyncSetVolumes(am_Handle_s& handle, const std::vector<am_Volumes_s>& listVolumes) +{ + am_handleData_c handleData; + IAmRoutingSend* pRoutingInterface(NULL); + if (listVolumes.empty()) + return (E_NOT_POSSIBLE); + + //we need an interface so lets get either the sink or source ID from the first entry in the listVolumes + if (listVolumes[0].volumeType==VT_SINK) + { + am_sinkID_t sinkID=listVolumes[0].volumeID.sink; + SinkInterfaceMap::iterator iter = mMapSinkInterface.begin(); + iter = mMapSinkInterface.find(sinkID); + if(iter!=mMapSinkInterface.end()) + pRoutingInterface=iter->second; + else + return(E_NON_EXISTENT); + } + + else if (listVolumes[0].volumeType==VT_SOURCE) + { + am_sourceID_t sourceID=listVolumes[0].volumeID.source; + SourceInterfaceMap::iterator iter = mMapSourceInterface.begin(); + iter = mMapSourceInterface.find(sourceID); + if (iter!=mMapSourceInterface.end()) + pRoutingInterface=iter->second; + else + return(E_NON_EXISTENT); + } + else + return (E_NON_EXISTENT); + + handleData.volumeID=listVolumes[0].volumeID; + handleData.listVolumes= new std::vector<am_Volumes_s>(listVolumes); + handle = createHandle(handleData, H_SETVOLUMES); + + mMapHandleInterface.insert(std::make_pair(+ handle.handle, pRoutingInterface)); + am_Error_e syncError(pRoutingInterface->asyncSetVolumes(handle, listVolumes)); + if (syncError) + { + removeHandle(handle); + delete handleData.listVolumes; + } + return(syncError); + +} + +am_Error_e CAmRoutingSender::asyncSetSinkNotificationConfiguration(am_Handle_s& handle, const am_sinkID_t sinkID, const am_NotificationConfiguration_s& notificationConfiguration) +{ + am_handleData_c handleData; + SinkInterfaceMap::iterator iter = mMapSinkInterface.begin(); + iter = mMapSinkInterface.find(sinkID); + if (iter != mMapSinkInterface.end()) + { + handleData.sinkID = sinkID; + handleData.notificationConfiguration = new am_NotificationConfiguration_s(notificationConfiguration); + handle = createHandle(handleData, H_SETSINKNOTIFICATION); + mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); + am_Error_e syncError(iter->second->asyncSetSinkNotificationConfiguration(handle, sinkID,notificationConfiguration)); + if (syncError) + { + removeHandle(handle); + delete handleData.notificationConfiguration; + } + return(syncError); + } + return (E_NON_EXISTENT); +} + +am_Error_e CAmRoutingSender::asyncSetSourceNotificationConfiguration(am_Handle_s& handle, const am_sourceID_t sourceID, const am_NotificationConfiguration_s& notificationConfiguration) +{ + am_handleData_c handleData; + SourceInterfaceMap::iterator iter = mMapSourceInterface.begin(); + iter = mMapSourceInterface.find(sourceID); + if (iter != mMapSourceInterface.end()) + { + handleData.sourceID = sourceID; + handleData.notificationConfiguration = new am_NotificationConfiguration_s(notificationConfiguration); + handle = createHandle(handleData, H_SETSOURCENOTIFICATION); + mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); + am_Error_e syncError(iter->second->asyncSetSourceNotificationConfiguration(handle, sourceID,notificationConfiguration)); + if (syncError) + { + removeHandle(handle); + delete handleData.notificationConfiguration; + } + return(syncError); + } + return (E_NON_EXISTENT); +} + +void CAmRoutingSender::unloadLibraries(void) +{ + std::vector<void*>::iterator iterator = mListLibraryHandles.begin(); + for (; iterator < mListLibraryHandles.end(); ++iterator) + { + dlclose(*iterator); + } + mListLibraryHandles.clear(); +} + +am_Error_e CAmRoutingSender::getListPlugins(std::vector<std::string>& interfaces) const +{ + std::vector<InterfaceNamePairs>::const_iterator it = mListInterfaces.begin(); + for (; it != mListInterfaces.end(); ++it) + { + interfaces.push_back(it->busName); + } + return (E_OK); +} + +void CAmRoutingSender::getInterfaceVersion(std::string & version) const +{ + version = RoutingVersion; +} +am_Error_e CAmRoutingSender::resyncConnectionState(const am_domainID_t domainID,std::vector<am_Connection_s>& listOfExistingConnections) +{ + DomainInterfaceMap::iterator iter = mMapDomainInterface.begin(); + iter = mMapDomainInterface.find(domainID); + if (iter != mMapDomainInterface.end()) + return (iter->second->resyncConnectionState(domainID, listOfExistingConnections)); + return (E_NON_EXISTENT); +} + +am_Error_e CAmRoutingSender::returnHandleDataAndRemove(const am_Handle_s handle,CAmRoutingSender::am_handleData_c& handleData) +{ + HandlesMap::const_iterator it = mlistActiveHandles.begin(); + it = mlistActiveHandles.find(handle); + if (it!=mlistActiveHandles.end()) + { + handleData = it->second; + mlistActiveHandles.erase(handle); + return (am_Error_e::E_OK); + } + handleData.sinkID=0; + logError(__PRETTY_FUNCTION__,"could not find handle data for handle",handle.handle,handle.handleType); + return (am_Error_e::E_NON_EXISTENT); + +} + +} diff --git a/AudioManagerCore/src/CAmTelnetMenuHelper.cpp b/AudioManagerCore/src/CAmTelnetMenuHelper.cpp new file mode 100644 index 0000000..2aae4f5 --- /dev/null +++ b/AudioManagerCore/src/CAmTelnetMenuHelper.cpp @@ -0,0 +1,1438 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2012, BMW AG + * + * This file is part of GENIVI Project AudioManager. + * + * Contributions are licensed to the GENIVI Alliance under one or more + * Contribution License Agreements. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012 + * \author Frank Herchet, frank.fh.herchet@bmw.de BMW 2012 + * + * \file CAmTelnetMenuHelper.cpp + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmTelnetMenuHelper.h" +#include <cassert> +#include "audiomanagerconfig.h" +#include "CAmRouter.h" +#include "CAmTelnetServer.h" +#include "IAmDatabaseHandler.h" +#include "CAmControlSender.h" +#include "CAmCommandSender.h" +#include "CAmRoutingSender.h" +#include "CAmRoutingReceiver.h" +#include "CAmCommandReceiver.h" +#include "CAmControlReceiver.h" +#include "CAmDltWrapper.h" + +static const std::string COLOR_WELCOME("\033[1;33m\033[44m"); +static const std::string COLOR_HEAD("\033[1m\033[42m"); +static const std::string COLOR_DEFAULT("\033[0m"); + + +namespace am { + +CAmTelnetMenuHelper* CAmTelnetMenuHelper::instance = NULL; + +/****************************************************************************/ +CAmTelnetMenuHelper::CAmTelnetMenuHelper(CAmSocketHandler *iSocketHandler, CAmCommandSender *iCommandSender, CAmCommandReceiver *iCommandReceiver, CAmRoutingSender *iRoutingSender, CAmRoutingReceiver *iRoutingReceiver, CAmControlSender *iControlSender, CAmControlReceiver *iControlReceiver, IAmDatabaseHandler *iDatabasehandler, CAmRouter *iRouter, CAmTelnetServer *iTelnetServer) +/****************************************************************************/ +:mpTelenetServer(iTelnetServer), mpSocketHandler(iSocketHandler), mpCommandSender(iCommandSender), mpCommandReceiver(iCommandReceiver), mpRoutingSender(iRoutingSender), mpRoutingReceiver(iRoutingReceiver), mpControlSender(iControlSender), mpControlReceiver(iControlReceiver), mpDatabasehandler(iDatabasehandler), mpRouter(iRouter) +{ + instance = this; + createCommandMaps(); +} + +/****************************************************************************/ +CAmTelnetMenuHelper::~CAmTelnetMenuHelper() +/****************************************************************************/ +{ +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::createCommandMaps() +/****************************************************************************/ +{ + // ROOT commands + mRootCommands.clear(); + mRootCommands.insert(std::make_pair("help", sCommandPrototypeInfo("show all possible commands", &CAmTelnetMenuHelper::helpCommand))); + mRootCommands.insert(std::make_pair("list", sCommandPrototypeInfo("Go into 'list'-submenu", &CAmTelnetMenuHelper::rootListCommand))); + mRootCommands.insert(std::make_pair("info", sCommandPrototypeInfo("Go into 'info'-submenu", &CAmTelnetMenuHelper::rootInfoCommand))); + mRootCommands.insert(std::make_pair("set", sCommandPrototypeInfo("Go into 'set'-submenu", &CAmTelnetMenuHelper::rootSetCommand))); + mRootCommands.insert(std::make_pair("get", sCommandPrototypeInfo("Go into 'get'-submenu", &CAmTelnetMenuHelper::rootGetCommand))); + mRootCommands.insert(std::make_pair("exit", sCommandPrototypeInfo("quit telnet session", &CAmTelnetMenuHelper::exitCommand))); + // List commands + mListCommands.insert(std::make_pair("help", sCommandPrototypeInfo(std::string("show all possible commands"), &CAmTelnetMenuHelper::helpCommand))); + mListCommands.insert(std::make_pair("conn", sCommandPrototypeInfo("list all connections", &CAmTelnetMenuHelper::listConnectionsCommand))); + mListCommands.insert(std::make_pair("sources", sCommandPrototypeInfo("list all available sources", &CAmTelnetMenuHelper::listSourcesCommand))); + mListCommands.insert(std::make_pair("sinks", sCommandPrototypeInfo("list all available sinks", &CAmTelnetMenuHelper::listSinksCommands))); + mListCommands.insert(std::make_pair("crfader", sCommandPrototypeInfo("list all crossfaders", &CAmTelnetMenuHelper::listCrossfaders))); + mListCommands.insert(std::make_pair("domains", sCommandPrototypeInfo("list all domains", &CAmTelnetMenuHelper::listDomainsCommand))); + mListCommands.insert(std::make_pair("gws", sCommandPrototypeInfo("list all gateways", &CAmTelnetMenuHelper::listGatewaysCommand))); + mListCommands.insert(std::make_pair("mainconn", sCommandPrototypeInfo("list all main connections", &CAmTelnetMenuHelper::listMainConnectionsCommand))); + mListCommands.insert(std::make_pair("mainsinks", sCommandPrototypeInfo("list all main sinks", &CAmTelnetMenuHelper::listMainSinksCommand))); + mListCommands.insert(std::make_pair("mainsources", sCommandPrototypeInfo("list all main sources", &CAmTelnetMenuHelper::listMainSourcesCommand))); + mListCommands.insert(std::make_pair("..", sCommandPrototypeInfo("one step back in menu tree (back to root folder)", &CAmTelnetMenuHelper::oneStepBackCommand))); + mListCommands.insert(std::make_pair("exit", sCommandPrototypeInfo("close telnet session", &CAmTelnetMenuHelper::exitCommand))); + // Set commands + mSetCommands.insert(std::make_pair("help", sCommandPrototypeInfo(std::string("show all possible commands"), &CAmTelnetMenuHelper::helpCommand))); + mSetCommands.insert(std::make_pair("..", sCommandPrototypeInfo("one step back in menu tree (back to root folder)", &CAmTelnetMenuHelper::oneStepBackCommand))); + mSetCommands.insert(std::make_pair("exit", sCommandPrototypeInfo("close telnet session", &CAmTelnetMenuHelper::exitCommand))); + mSetCommands.insert(std::make_pair("conn", sCommandPrototypeInfo("use 'conn sourceId sinkId' to connect a source and a sink", &CAmTelnetMenuHelper::setConnection))); + mSetCommands.insert(std::make_pair("routing", sCommandPrototypeInfo("use 'routing sourceId sinkId' to get all\n\t possible routes between a sourceID and a sinkID", &CAmTelnetMenuHelper::setRoutingCommand))); + mSetCommands.insert(std::make_pair("disc", sCommandPrototypeInfo("use 'disc connectionID' to disconnect \n\t this connection", &CAmTelnetMenuHelper::setDisconnectConnId))); + mSetCommands.insert(std::make_pair("sinkvolume", sCommandPrototypeInfo("use 'sinkvolume sinkID volume' to set \n\t absorption in db of sink", &CAmTelnetMenuHelper::setSinkVolume))); + mSetCommands.insert(std::make_pair("sinkvolstep", sCommandPrototypeInfo("use 'sinkvolstep sinkID volumestep' to increment \n\t or decrement volume", &CAmTelnetMenuHelper::setVolumeStep))); + mSetCommands.insert(std::make_pair("sinkprop", sCommandPrototypeInfo("use 'sinkprop type value' to set \n\t a specific sinksoundproperty", &CAmTelnetMenuHelper::setSinkSoundProperty))); + mSetCommands.insert(std::make_pair("sinkmute", sCommandPrototypeInfo("use 'sinkmute sinkid mutestate' to mute \n\t or unmute", &CAmTelnetMenuHelper::setSinkMuteState))); + mSetCommands.insert(std::make_pair("sourceprop", sCommandPrototypeInfo("use 'sourceprop type value' to set \n\t a specific sinksoundproperty", &CAmTelnetMenuHelper::setSourceSoundProperty))); + // Get commands + mGetCommands.insert(std::make_pair("help", sCommandPrototypeInfo(std::string("show all possible commands"), &CAmTelnetMenuHelper::helpCommand))); + mGetCommands.insert(std::make_pair("routing", sCommandPrototypeInfo("show current routing", &CAmTelnetMenuHelper::getRoutingCommand))); + mGetCommands.insert(std::make_pair("sendv", sCommandPrototypeInfo("show senderversion", &CAmTelnetMenuHelper::getSenderversionCommand))); + mGetCommands.insert(std::make_pair("recv", sCommandPrototypeInfo("show receiverversion ", &CAmTelnetMenuHelper::getReceiverversionCommand))); + mGetCommands.insert(std::make_pair("..", sCommandPrototypeInfo("one step back in menu tree (back to root folder)", &CAmTelnetMenuHelper::oneStepBackCommand))); + mGetCommands.insert(std::make_pair("exit", sCommandPrototypeInfo("close telnet session", &CAmTelnetMenuHelper::exitCommand))); + // Info comands + mInfoCommands.insert(std::make_pair("help", sCommandPrototypeInfo(std::string("show all possible commands"), &CAmTelnetMenuHelper::helpCommand))); + mInfoCommands.insert(std::make_pair("sysprop", sCommandPrototypeInfo("show all systemproperties", &CAmTelnetMenuHelper::infoSystempropertiesCommand))); + mInfoCommands.insert(std::make_pair("dump", sCommandPrototypeInfo("create a database dump of currently used data", &CAmTelnetMenuHelper::infoDumpCommand))); + mInfoCommands.insert(std::make_pair("..", sCommandPrototypeInfo("one step back in menu tree (back to root folder)", &CAmTelnetMenuHelper::oneStepBackCommand))); + mInfoCommands.insert(std::make_pair("exit", sCommandPrototypeInfo("close telnet session", &CAmTelnetMenuHelper::exitCommand))); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::newSocketConnection(int filedescriptor) +/****************************************************************************/ +{ + EMainState state = eRootState; + std::map<int, EMainState>::iterator it; + std::stringstream welcome; + it = mCurrentMainStateMap.find(filedescriptor); + if (it != mCurrentMainStateMap.end()) + { + // socket connection already exists, delete entry and go back to root state + mCurrentMainStateMap.erase(it); + } + it = mCurrentMainStateMap.begin(); + // insert new socket connection + mCurrentMainStateMap.insert(it, std::make_pair(filedescriptor, state)); + // Send welcome message + welcome << COLOR_WELCOME << "Welcome to GENIVI AudioManager " << DAEMONVERSION << COLOR_DEFAULT << "\n>"; + assert(send(filedescriptor, welcome.str().c_str(), welcome.str().size(), 0)>=0); + logInfo("[TN] New connection: ", filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::socketConnectionsClosed(int filedescriptor) +/****************************************************************************/ +{ + std::map<int, EMainState>::iterator it; + it = mCurrentMainStateMap.find(filedescriptor); + if (it != mCurrentMainStateMap.end()) + { + mCurrentMainStateMap.erase(it); + } + else + { + logError("[TN] socketConnectionsClosed, fd not found, ", filedescriptor); + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::enterCmdQueue(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + std::map<int, EMainState>::iterator it; + std::string cmd; + tCommandMap::iterator cmditer; + // find current filedescriptor to get the current state of the telnet session + it = mCurrentMainStateMap.find(filedescriptor); + while (!CmdQueue.empty()) + { + cmd = CmdQueue.front(); + // Now remove the first command, it's stored in 'cmd' + CmdQueue.pop(); + // telnet session found. depending on the current state, different commands are available + switch (it->second) + { + case eRootState: + cmditer = mRootCommands.find(cmd); + if (mRootCommands.end() != cmditer) + cmditer->second.CommandPrototype(CmdQueue, filedescriptor); + else + sendError(filedescriptor, "Command not found\n"); + + break; + case eListState: + cmditer = mListCommands.find(cmd); + if (mListCommands.end() != cmditer) + cmditer->second.CommandPrototype(CmdQueue, filedescriptor); + else + sendError(filedescriptor, "Command not found\n"); + + break; + case eInfoState: + cmditer = mInfoCommands.find(cmd); + if (mInfoCommands.end() != cmditer) + cmditer->second.CommandPrototype(CmdQueue, filedescriptor); + else + sendError(filedescriptor, "Command not found\n"); + + break; + case eGetState: + cmditer = mGetCommands.find(cmd); + if (mGetCommands.end() != cmditer) + cmditer->second.CommandPrototype(CmdQueue, filedescriptor); + else + sendError(filedescriptor, "Command not found\n"); + + break; + case eSetState: + cmditer = mSetCommands.find(cmd); + if (mSetCommands.end() != cmditer) + cmditer->second.CommandPrototype(CmdQueue, filedescriptor); + else + sendError(filedescriptor, "Command not found\n"); + + break; + default: + break; + } + } + + sendCurrentCmdPrompt(filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::sendError(int& filedescriptor, std::string error_string) +/****************************************************************************/ +{ + assert(send(filedescriptor, error_string.c_str(), error_string.size(), 0)>=0); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::sendTelnetLine(int& filedescriptor, std::stringstream& line) +/****************************************************************************/ +{ + assert(send(filedescriptor, line.str().c_str(), line.str().size(), 0)>=0); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::sendCurrentCmdPrompt(int& filedescriptor) +/****************************************************************************/ +{ + std::map<int, EMainState>::iterator it; + std::stringstream outputstream; + outputstream << std::endl; + it = mCurrentMainStateMap.find(filedescriptor); + if (it != mCurrentMainStateMap.end()) + { + switch (it->second) + { + case eRootState: + outputstream << "\\>"; + break; + case eListState: + outputstream << "\\List>"; + break; + case eGetState: + outputstream << "\\Get>"; + break; + case eSetState: + outputstream << "\\Set>"; + break; + case eInfoState: + outputstream << "\\Info>"; + break; + default: + break; + } + assert(send(filedescriptor, outputstream.str().c_str(), outputstream.str().size(), 0)>=0); + } + else + { + logInfo("[TN] sendCurrentCmdPrompt, fd not found: ", filedescriptor); + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::exitCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->exitCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::oneStepBackCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::map<int, EMainState>::iterator it; + it = mCurrentMainStateMap.find(filedescriptor); + if (it != mCurrentMainStateMap.end()) + { + switch (it->second) + { + case eRootState: + it->second = eRootState; + break; + case eListState: + it->second = eRootState; + ; + break; + case eGetState: + it->second = eRootState; + ; + break; + case eSetState: + it->second = eRootState; + ; + break; + case eInfoState: + it->second = eRootState; + ; + break; + default: + it->second = eRootState; + break; + } + logInfo("[TN] oneStepBackCommandExec, state: ", it->second); + } + +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::oneStepBackCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->oneStepBackCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::exitCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::map<int, EMainState>::iterator it; + std::stringstream line; + std::stringstream output; + // Sending a last message to the client + output << "bye!" << COLOR_DEFAULT << std::endl; + sendTelnetLine(filedescriptor, output); + tCommandMap::iterator iter; + it = mCurrentMainStateMap.find(filedescriptor); + if (it != mCurrentMainStateMap.end()) + { + if (NULL != mpTelenetServer) + { + logInfo("[TN] exitCommandExec, removing fd ", filedescriptor); + mpTelenetServer->disconnectClient(filedescriptor); + mCurrentMainStateMap.erase(it); + } + else + { + logError("[TN] exitCommandExec, mpTelenetServer == NULL, fd ", filedescriptor); + } + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::helpCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->helpCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::helpCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::map<int, EMainState>::iterator it; + std::stringstream line; + tCommandMap::iterator cmdIter; + it = mCurrentMainStateMap.find(filedescriptor); + if (it != mCurrentMainStateMap.end()) + { + line << COLOR_HEAD << "###################################################" << COLOR_DEFAULT << std::endl; + line << COLOR_HEAD << "###### The following commands are supported: ######" << COLOR_DEFAULT << std::endl; + line << COLOR_HEAD << "###################################################" << COLOR_DEFAULT << std::endl << std::endl; + switch (it->second) + { + case eRootState: + cmdIter = mRootCommands.begin(); + while (cmdIter != mRootCommands.end()) + { + line << cmdIter->first << "\t\t- " << cmdIter->second.info << std::endl; + cmdIter++; + } + break; + case eListState: + cmdIter = mListCommands.begin(); + while (cmdIter != mListCommands.end()) + { + line << cmdIter->first << "\t\t- " << cmdIter->second.info << std::endl; + cmdIter++; + } + break; + case eGetState: + cmdIter = mGetCommands.begin(); + while (cmdIter != mGetCommands.end()) + { + line << cmdIter->first << "\t\t- " << cmdIter->second.info << std::endl; + cmdIter++; + } + break; + case eSetState: + cmdIter = mSetCommands.begin(); + while (cmdIter != mSetCommands.end()) + { + line << cmdIter->first << "\t\t- " << cmdIter->second.info << std::endl; + cmdIter++; + } + break; + case eInfoState: + cmdIter = mInfoCommands.begin(); + while (cmdIter != mInfoCommands.end()) + { + line << cmdIter->first << "\t\t- " << cmdIter->second.info << std::endl; + cmdIter++; + } + break; + default: + break; + } + + sendTelnetLine(filedescriptor, line); + } + +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::rootGetCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->rootGetCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::rootGetCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::map<int, EMainState>::iterator it; + it = mCurrentMainStateMap.find(filedescriptor); + if (it != mCurrentMainStateMap.end()) + { + it->second = eGetState; + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::rootSetCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->rootSetCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::rootSetCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::map<int, EMainState>::iterator it; + it = mCurrentMainStateMap.find(filedescriptor); + if (it != mCurrentMainStateMap.end()) + { + it->second = eSetState; + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::rootListCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->rootListCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::rootListCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::map<int, EMainState>::iterator it; + it = mCurrentMainStateMap.find(filedescriptor); + if (it != mCurrentMainStateMap.end()) + { + it->second = eListState; + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::rootInfoCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->rootInfoCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::rootInfoCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::map<int, EMainState>::iterator it; + it = mCurrentMainStateMap.find(filedescriptor); + if (it != mCurrentMainStateMap.end()) + { + it->second = eInfoState; + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listConnectionsCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->listConnectionsCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listConnectionsCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::vector < am_Connection_s > listConnections; + if (E_OK == mpDatabasehandler->getListConnections(listConnections)) + { + std::stringstream output; + output << "\tConnections: " << listConnections.size() << std::endl; + for (std::vector<am_Connection_s>::iterator iter(listConnections.begin()); iter < listConnections.end(); iter++) + { + output << "\tID: " << iter->connectionID << "\tSrcID: " << iter->sourceID << "\tSinkID: " << iter->sinkID << "\tFormat: " << iter->connectionFormat << "\tdelay: " << iter->delay << std::endl; + } + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "ERROR: mDatabasehandler->getListConnections"); + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listSourcesCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->listSourcesCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listSourcesCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::vector < am_Source_s > listSources; + if (E_OK == mpDatabasehandler->getListSources(listSources)) + { + std::stringstream output; + output << "\tSources: " << listSources.size() << std::endl; + for (std::vector<am_Source_s>::iterator iter(listSources.begin()); iter < listSources.end(); iter++) + { + output << "\tID: " << iter->sourceID << "\tName: " << iter->name << "\tDomainID: " << iter->domainID << "\tState: " << iter->sourceState << "\tVolume: " << iter->volume << std::endl; + } + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "ERROR: mDatabasehandler->getListSources"); + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listSinksCommands(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->listSinksCommandsExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listSinksCommandsExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::vector < am_Sink_s > listSinks; + if (E_OK == mpDatabasehandler->getListSinks(listSinks)) + { + std::stringstream output; + output << "\tSinks: " << listSinks.size() << std::endl; + for (std::vector<am_Sink_s>::iterator iter(listSinks.begin()); iter < listSinks.end(); iter++) + { + output << "\tID: " << iter->sinkID << "\tDomainID: " << iter->domainID << "\tName: " << iter->name << "\tAvailable: " << iter->available.availability << "\tVolume: " << iter->volume << std::endl; + } + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "ERROR: mDatabasehandler->getListSinks"); + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listCrossfaders(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->listCrossfadersExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listCrossfadersExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::vector < am_Crossfader_s > listCrossfaders; + if (E_OK == mpDatabasehandler->getListCrossfaders(listCrossfaders)) + { + std::stringstream output; + output << "\tCrossfader: " << listCrossfaders.size() << std::endl; + for (std::vector<am_Crossfader_s>::iterator iter(listCrossfaders.begin()); iter < listCrossfaders.end(); iter++) + { + output << "\tID: " << iter->crossfaderID << "\tName: " << iter->name << "\tSinkA: " << iter->sinkID_A << "\tSinkB: " << iter->sinkID_B << "\tSourceID: " << iter->sourceID << std::endl; + } + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "ERROR: mDatabasehandler->getListCrossfaders"); + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listDomainsCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->listDomainsCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listDomainsCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::vector < am_Domain_s > listDomains; + if (E_OK == mpDatabasehandler->getListDomains(listDomains)) + { + std::stringstream output; + output << "\tDomains: " << listDomains.size() << std::endl; + for (std::vector<am_Domain_s>::iterator iter(listDomains.begin()); iter < listDomains.end(); iter++) + { + output << "\tID: " << iter->domainID << "\tName: " << iter->name << "\tBusname: " << iter->busname << "\tNodename: " << iter->nodename << "\tState: " << static_cast<int>(iter->state) << std::endl; + } + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "ERROR: mDatabasehandler->getListDomains"); + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listGatewaysCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->listGatewaysCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listGatewaysCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::vector < am_Gateway_s > listGateways; + if (E_OK == mpDatabasehandler->getListGateways(listGateways)) + { + std::stringstream output; + output << "\tGateways: " << listGateways.size(); + for (std::vector<am_Gateway_s>::iterator iter(listGateways.begin()); iter < listGateways.end(); iter++) + { + output << "\tID: " << iter->gatewayID << "\tName: " << iter->name << "\tSourceID: " << iter->sourceID << "\tSinkID: " << iter->sinkID << std::endl; + } + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "ERROR: mDatabasehandler->getListGateways"); + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::getRoutingCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->getRoutingCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::getRoutingCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + (void) (filedescriptor); +//TODO: fill with function +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::getSenderversionCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->getSenderversionCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::getSenderversionCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::stringstream output; + std::string versionCommand; + std::string versionRouting; + std::string versionControl; + mpControlSender->getInterfaceVersion(versionControl); + mpRoutingSender->getInterfaceVersion(versionRouting); + mpCommandSender->getInterfaceVersion(versionCommand); + output << "\tSender versions:" << std::endl << "\tCtrl: " << versionControl << " | " << "Cmd: " << versionCommand << " | " << "Routing: " << versionRouting << std::endl; + sendTelnetLine(filedescriptor, output); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::getReceiverversionCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->getReceiverversionCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::getReceiverversionCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::stringstream output; + std::string versionCommand; + std::string versionRouting; + std::string versionControl; + mpControlReceiver->getInterfaceVersion(versionControl); + mpRoutingReceiver->getInterfaceVersion(versionRouting); + mpCommandReceiver->getInterfaceVersion(versionCommand); + output << "\tReceiver versions:" << std::endl << "\tCtrl: " << versionControl << " | " << "Cmd: " << versionCommand << " | " << "Routing: " << versionRouting << std::endl; + sendTelnetLine(filedescriptor, output); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::infoSystempropertiesCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->infoSystempropertiesCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::infoDumpCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->infoDumpCommandExec(CmdQueue, filedescriptor); +} + + +/****************************************************************************/ +void CAmTelnetMenuHelper::setVolumeStep(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->setSinkVolumeExec(CmdQueue,filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setVolumeStepExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + if (CmdQueue.size() >= 2) + { + int16_t volumestep = 0; + am_sinkID_t sinkID = 0; + bool error = false; + std::istringstream istream_sinkID(CmdQueue.front()); + CmdQueue.pop(); + std::istringstream istream_volumestep(CmdQueue.front()); + CmdQueue.pop(); + if (!(istream_volumestep >> volumestep)) + error = true; + + if (!(istream_sinkID >> sinkID)) + error = true; + + if (error) + { + sendError(filedescriptor, "Error parsing setVolumeStep 'sinkID' or 'volumestep'"); + return; + } + if (E_OK == mpCommandReceiver->volumeStep(sinkID,volumestep)) + { + std::stringstream output; + output << "SetSinkVolumeStep set: " << sinkID << "->" << volumestep << std::endl; + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "Error SetSinkVolumeStep"); + } + } + else + { + sendError(filedescriptor, "Not enough arguments to set SetSinkVolumeStep, please enter 'sinkID' and 'volumestep' after command"); + return; + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setSinkMuteState(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->setSinkMuteStateExec(CmdQueue,filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setSinkMuteStateExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + if (CmdQueue.size() >= 2) + { + u_int16_t tmp = 0; + am_MuteState_e MuteState = MS_UNKNOWN; + am_sinkID_t sinkID = 0; + bool error = false; + std::istringstream istream_sinkID(CmdQueue.front()); + CmdQueue.pop(); + std::istringstream istream_mutestate(CmdQueue.front()); + CmdQueue.pop(); + if (!(istream_mutestate >> tmp)) + error = true; + + if (!(istream_sinkID >> sinkID)) + error = true; + + if(tmp < MS_MAX) + { + MuteState = static_cast<am_MuteState_e>(tmp); + } + else + { + sendError(filedescriptor, "You tried to set an invalid am_MuteState_e"); + error = true; + } + + if (error) + { + sendError(filedescriptor, "Error parsing setSinkMuteState 'sinkID' or 'mutestate'"); + return; + } + if (E_OK == mpCommandReceiver->setSinkMuteState(sinkID,MuteState)) + { + std::stringstream output; + output << "setSinkMuteState set: " << sinkID << "->" << MuteState << std::endl; + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "Error setSinkMuteState"); + } + } + else + { + sendError(filedescriptor, "Not enough arguments to set setSinkMuteState, please enter 'sinkID' and 'mutestate' after command"); + return; + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setSourceSoundProperty(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->setSourceSoundPropertiesExec(CmdQueue,filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setSourceSoundPropertyExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + unsigned int tmpType = 0; + bool error = false; + if (CmdQueue.size() >= 3) + { + std::istringstream istream_sourceID(CmdQueue.front()); + CmdQueue.pop(); + std::istringstream istream_type(CmdQueue.front()); + CmdQueue.pop(); + std::istringstream istream_value(CmdQueue.front()); + CmdQueue.pop(); + if (!(istream_type >> tmpType)) + error = true; + + am_MainSoundProperty_s soundProperty; + soundProperty.type = static_cast<am_CustomMainSoundPropertyType_t>(tmpType); + + if (!(istream_value >> soundProperty.value)) + error = true; + + am_sourceID_t sourceID = 0; + if (!(istream_sourceID >> sourceID)) + error = true; + + if (error) + { + sendError(filedescriptor, "Error parsing setMainSourceSoundProperty 'type', 'value' or 'sourceID'"); + return; + } + if (E_OK == mpCommandReceiver->setMainSourceSoundProperty(soundProperty, sourceID)) + { + std::stringstream output; + output << "setMainSourceSoundProperty set: " << soundProperty.type << "->" << soundProperty.value << std::endl; + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "Error setMainSourceSoundProperty"); + } + } + else + { + sendError(filedescriptor, "Not enough arguments to set setMainSourceSoundProperty, please enter 'sourceID', 'type' and 'value' after command"); + return; + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::infoSystempropertiesCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::vector < am_SystemProperty_s > listSystemProperties; + if (E_OK == mpDatabasehandler->getListSystemProperties(listSystemProperties)) + { + std::stringstream output; + output << "\tSystemproperties: " << listSystemProperties.size() << std::endl; + std::vector<am_SystemProperty_s>::iterator it; + for (it = listSystemProperties.begin(); it < listSystemProperties.end(); it++) + { + output << "\tType: " << it->type << " Value: " << it->value << std::endl; + } + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "ERROR: mDatabasehandler->getListSystemProperties"); + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::infoDumpCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + + std::stringstream *pOutput = new std::stringstream(); + + mpDatabasehandler->dump(*pOutput); + + sendTelnetLine(filedescriptor, *pOutput); + + delete pOutput; +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setRoutingCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->setRoutingCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setRoutingCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + if (CmdQueue.size() >= 2) + { + bool error = false; + std::istringstream istream_sourceID(CmdQueue.front()); + CmdQueue.pop(); + std::istringstream istream_sinkID(CmdQueue.front()); + CmdQueue.pop(); + am_sourceID_t sourceID = 0; + if (!(istream_sourceID >> sourceID)) + error = true; + + am_sinkID_t sinkID = 0; + if (!(istream_sinkID >> sinkID)) + error = true; + + if (error) + { + sendError(filedescriptor, "Error parsing sourcID and sinkID"); + return; + } + std::vector < am_Route_s > routingList; + if (E_OK == mpRouter->getRoute(true, sourceID, sinkID, routingList)) + { + std::stringstream output; + std::vector<am_Route_s>::iterator rlIter = routingList.begin(); + for (int rlCnt = 1; rlIter < routingList.end(); rlIter++) + { + output << "#" << rlCnt << " "; + std::vector<am_RoutingElement_s>::iterator reIter = rlIter->route.begin(); + for (; reIter < rlIter->route.end(); reIter++) + { + output << ">(" << reIter->sourceID << ")->--[D:" << reIter->domainID << "][F:" << reIter->connectionFormat << "]-->-(" << reIter->sinkID << ")" << std::endl; + } + rlCnt++; + } + + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "Error getting route"); + } + } + else + { + if (!CmdQueue.empty()) + CmdQueue.pop(); + + sendError(filedescriptor, "Not enough arguments to set routing. Please enter sourceID and sinkID after command"); + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setConnection(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->setConnectionExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setConnectionExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + bool error = false; + am_Error_e rError = E_OK; + if (CmdQueue.size() >= 2) + { + std::istringstream istream_sourceID(CmdQueue.front()); + CmdQueue.pop(); + std::istringstream istream_sinkID(CmdQueue.front()); + CmdQueue.pop(); + am_sourceID_t sourceID = 0; + if (!(istream_sourceID >> sourceID)) + error = true; + + am_sinkID_t sinkID = 0; + if (!(istream_sinkID >> sinkID)) + error = true; + + if (error) + { + sendError(filedescriptor, "Error parsing sinkID and/or sourceID"); + return; + } +// Try to set up connection + am_mainConnectionID_t connID = 0; + rError = mpCommandReceiver->connect(sourceID, sinkID, connID); + if (E_OK == rError) + { + std::stringstream output; + output << "ConnID: " << connID << "\tSrc: " << sourceID << " ---> Sink: " << sinkID << std::endl; + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "Error connecting sourceID and sinkID"); + } + } + else + { +// remove 1 element if list is not empty + if (!CmdQueue.empty()) + CmdQueue.pop(); + + sendError(filedescriptor, "Not enough arguments to set routing. Please enter sourceID and sinkID after command"); + return; + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setDisconnectConnId(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->setDisconnectConnIdExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setDisconnectConnIdExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + am_mainConnectionID_t connID = 0; + bool error = false; + am_Error_e rError = E_OK; + if (CmdQueue.size() >= 1) + { + std::istringstream istream_connID(CmdQueue.front()); + CmdQueue.pop(); + if (!(istream_connID >> connID)) + error = true; + + if (error) + { + sendError(filedescriptor, "Error parsing connID"); + return; + } +// Try to disconnect connection id + rError = mpCommandReceiver->disconnect(connID); + if (E_OK == rError) + { + std::stringstream output; + output << "ConnID " << connID << " closed successfully! " << std::endl; + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "Error disconnecting connectionID"); + } + } + else + { + sendError(filedescriptor, "Not enough arguments to disconnect a Main Connection, please enter 'connectionID' after command"); + return; + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setSourceSoundProperties(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->setConnectionExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setSourceSoundPropertiesExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + if (CmdQueue.size() >= 3) + { + bool error = false; + std::istringstream istream_sourceID(CmdQueue.front()); + CmdQueue.pop(); + std::istringstream istream_type(CmdQueue.front()); + CmdQueue.pop(); + std::istringstream istream_value(CmdQueue.front()); + CmdQueue.pop(); + unsigned int tmpType = 0; + if (!(istream_type >> tmpType)) + error = true; + + am_MainSoundProperty_s soundProperty; + soundProperty.type = static_cast<am_CustomMainSoundPropertyType_t>(tmpType); + + if (!(istream_value >> soundProperty.value)) + error = true; + + am_sinkID_t sourceID = 0; + if (!(istream_sourceID >> sourceID)) + error = true; + + if (error) + { + sendError(filedescriptor, "Error parsing MainSinkSoundProperty 'type', 'value' or 'sourceID'"); + return; + } + if (E_OK == mpCommandReceiver->setMainSourceSoundProperty(soundProperty, sourceID)) + { + std::stringstream output; + output << "MainSourceSoundProperty set: " << soundProperty.type << "->" << soundProperty.value << std::endl; + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "Error setMainSourceSoundProperty"); + } + } + else + { + sendError(filedescriptor, "Not enough arguments to set MainSourceSoundProperty, please enter 'sourceID', 'type' and 'value' after command"); + return; + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setSinkSoundProperty(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->setSinkSoundPropertyExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setSinkSoundPropertyExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + unsigned int tmpType = 0; + bool error = false; + if (CmdQueue.size() >= 3) + { + std::istringstream istream_sinkID(CmdQueue.front()); + CmdQueue.pop(); + std::istringstream istream_type(CmdQueue.front()); + CmdQueue.pop(); + std::istringstream istream_value(CmdQueue.front()); + CmdQueue.pop(); + if (!(istream_type >> tmpType)) + error = true; + + am_MainSoundProperty_s soundProperty; + soundProperty.type = static_cast<am_CustomMainSoundPropertyType_t>(tmpType); + + if (!(istream_value >> soundProperty.value)) + error = true; + + am_sinkID_t sinkID = 0; + if (!(istream_sinkID >> sinkID)) + error = true; + + if (error) + { + sendError(filedescriptor, "Error parsing MainSinkSoundProperty 'type', 'value' or 'sinkID'"); + return; + } + if (E_OK == mpCommandReceiver->setMainSinkSoundProperty(soundProperty, sinkID)) + { + std::stringstream output; + output << "MainSinkSoundProperty set: " << soundProperty.type << "->" << soundProperty.value << std::endl; + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "Error setMainSinkSoundProperty"); + } + } + else + { + sendError(filedescriptor, "Not enough arguments to set MainSinkSoundProperty, please enter 'sinkID', 'type' and 'value' after command"); + return; + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setSinkVolume(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->setSinkVolumeExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::setSinkVolumeExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + if (CmdQueue.size() >= 2) + { + am_volume_t volume = 0; + am_sinkID_t sinkID = 0; + bool error = false; + std::istringstream istream_sinkID(CmdQueue.front()); + CmdQueue.pop(); + std::istringstream istream_volume(CmdQueue.front()); + CmdQueue.pop(); + if (!(istream_volume >> volume)) + error = true; + + if (!(istream_sinkID >> sinkID)) + error = true; + + if (error) + { + sendError(filedescriptor, "Error parsing SetSinkVolume 'sinkID' or 'volume'"); + return; + } + if (E_OK == mpCommandReceiver->setVolume(sinkID,volume)) + { + std::stringstream output; + output << "setVolume set: " << sinkID << "->" << volume << std::endl; + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "Error setVolume"); + } + } + else + { + sendError(filedescriptor, "Not enough arguments to set setVolume, please enter 'sinkID' and 'volume' after command"); + return; + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listPluginsCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->listPluginsCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listPluginsCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::vector < std::string > PlugInNames; + std::vector<std::string>::iterator iter; + std::stringstream output; + if (E_OK == mpCommandSender->getListPlugins(PlugInNames)) + { + output << "\tCommandSender Plugins loaded: " << PlugInNames.size() << std::endl; + for (iter = PlugInNames.begin(); iter < PlugInNames.end(); iter++) + { + output << iter->c_str() << std::endl; + } + } + else + { + sendError(filedescriptor, "ERROR: mCommandSender->getListPlugins"); + } + if (E_OK == mpRoutingSender->getListPlugins(PlugInNames)) + { + output << std::endl << "\tRoutingSender Plugins loaded: " << PlugInNames.size() << std::endl; + for (iter = PlugInNames.begin(); iter < PlugInNames.end(); iter++) + { + output << iter->c_str() << std::endl; + } + } + else + { + sendError(filedescriptor, "ERROR: mRoutingSender->getListPlugins"); + } + sendTelnetLine(filedescriptor, output); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listMainSourcesCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->listMainSourcesCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listMainSourcesCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::vector < am_SourceType_s > listMainSources; + if (E_OK == mpDatabasehandler->getListMainSources(listMainSources)) + { + std::stringstream output; + output << std::endl << "\tMainSources: " << listMainSources.size() << std::endl; + std::vector<am_SourceType_s>::iterator iter; + for (iter = listMainSources.begin(); iter < listMainSources.end(); iter++) + { + output << "\tID: " << iter->sourceID << "\tName: " << iter->name << "\tsourceClassID: " << iter->sourceClassID << "\tavailability: " << iter->availability.availability << std::endl; + } + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "ERROR: mDatabasehandler->getListMainSources"); + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listMainSinksCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->listMainSinksCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listMainSinksCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::vector < am_SinkType_s > listMainSinks; + if (E_OK == mpDatabasehandler->getListMainSinks(listMainSinks)) + { + std::stringstream output; + output << std::endl << "\tMainSinks: " << listMainSinks.size() << std::endl; + std::vector<am_SinkType_s>::iterator iter; + for (iter = listMainSinks.begin(); iter < listMainSinks.end(); iter++) + { + output << "\tID: " << iter->sinkID << "\tsinkClassID: " << iter->sinkClassID << "\tName: " << iter->name << "\tAvailable: " << iter->availability.availability << "\tVolume: " << iter->volume << std::endl; + } + sendTelnetLine(filedescriptor, output); + } + else + { + sendError(filedescriptor, "ERROR: mDatabasehandler->getListMainSinks"); + } +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listMainConnectionsCommand(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + instance->listMainConnectionsCommandExec(CmdQueue, filedescriptor); +} + +/****************************************************************************/ +void CAmTelnetMenuHelper::listMainConnectionsCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor) +/****************************************************************************/ +{ + (void) (CmdQueue); + std::vector<am_MainConnection_s> listMainConnections; + + if(E_OK == mpDatabasehandler->getListMainConnections(listMainConnections)) + { + std::stringstream output; + output << std::endl << "\tMainConnections: " << listMainConnections.size() << std::endl; + + std::vector<am_MainConnection_s>::iterator iter; + for (iter = listMainConnections.begin(); iter < listMainConnections.end(); iter++) + { + output << "\tID: " << iter->mainConnectionID + << "\tState: " << iter->connectionState + << "\tDelay: " << iter->delay + << "\tsourceID: " << iter->sourceID + << "\tsinkID: " << iter->sinkID << std::endl; + + output << "ConnectionIDs: "; + std::vector<am_connectionID_t>::iterator list_connIDs_iter = iter->listConnectionID.begin(); + for(;list_connIDs_iter < iter->listConnectionID.end();list_connIDs_iter++) + { + output << *list_connIDs_iter << " "; + } + + output << std::endl; + } + sendTelnetLine(filedescriptor,output); + } + else + { + sendError(filedescriptor,"ERROR: mDatabasehandler->getListMainSinks"); + } +} +} + + + + + diff --git a/AudioManagerCore/src/CAmTelnetServer.cpp b/AudioManagerCore/src/CAmTelnetServer.cpp new file mode 100755 index 0000000..22f7b0e --- /dev/null +++ b/AudioManagerCore/src/CAmTelnetServer.cpp @@ -0,0 +1,257 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2012, BMW AG + * + * This file is part of GENIVI Project AudioManager. + * + * Contributions are licensed to the GENIVI Alliance under one or more + * Contribution License Agreements. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012 + * \author Frank Herchet, frank.fh.herchet@bmw.de BMW 2012 + * + * \file CAmTelnetServer.cpp + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmTelnetServer.h" +#include <cassert> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <sys/ioctl.h> +#include <string.h> +#include <netdb.h> +#include <audiomanagerconfig.h> +#include <errno.h> +#include <sstream> +#include <istream> +#include <iostream> +#include <iterator> +#include <unistd.h> +#include <stdexcept> +#include <cstdlib> +#include "CAmRoutingSender.h" +#include "CAmTelnetMenuHelper.h" +#include "CAmDltWrapper.h" + +namespace am +{ + +CAmTelnetServer* CAmTelnetServer::mpInstance = NULL; + +#define PRINT_BOOL(var) var ? output+="true\t\t" : output+="false\t\t"; + +CAmTelnetServer::CAmTelnetServer(CAmSocketHandler *iSocketHandler, CAmCommandSender *iCommandSender, CAmCommandReceiver *iCommandReceiver, CAmRoutingSender *iRoutingSender, CAmRoutingReceiver *iRoutingReceiver, CAmControlSender *iControlSender, CAmControlReceiver *iControlReceiver, IAmDatabaseHandler *iDatabasehandler, CAmRouter *iRouter, unsigned int servPort, unsigned int maxConnections) : + telnetConnectFiredCB(this, &CAmTelnetServer::connectSocket), // + telnetReceiveFiredCB(this, &CAmTelnetServer::receiveData), // + telnetDispatchCB(this, &CAmTelnetServer::dispatchData), // + telnetCheckCB(this, &CAmTelnetServer::check), // + mpSocketHandler(iSocketHandler), // + mpCommandSender(iCommandSender), // + mpCommandReceiver(iCommandReceiver), // + mpRoutingSender(iRoutingSender), // + mpRoutingReceiver(iRoutingReceiver), // + mpControlSender(iControlSender), // + mpControlReceiver(iControlReceiver), // + mpDatabasehandler(iDatabasehandler), // + mpRouter(iRouter), // + mConnecthandle(), // + mListMessages(), // + mListConnections(), // + mConnectFD(0), // + mServerPort(servPort), // + mMaxConnections(maxConnections), // + mTelnetMenuHelper(iSocketHandler, iCommandSender, iCommandReceiver, iRoutingSender, iRoutingReceiver, iControlSender, iControlReceiver, iDatabasehandler, iRouter, this) +{ + assert(mpSocketHandler!=NULL); + assert(mpCommandReceiver!=NULL); + assert(mpCommandSender!=NULL); + assert(mpControlSender!=NULL); + assert(mpControlReceiver!=NULL); + assert(mpRoutingSender!=NULL); + assert(mpRoutingReceiver!=NULL); + assert(mpDatabasehandler!=NULL); + assert(mpRouter!=NULL); + assert(servPort!=0); + assert(mMaxConnections!=0); + + mpInstance = this; + //mTelnetMenuHelper.setTelnetServer(this); + + int yes = 1; + struct sockaddr_in servAddr; + + //setup the port Listener + mConnectFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + assert (mConnectFD>0); + assert(setsockopt(mConnectFD, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int))==0); + memset(&servAddr, 0, sizeof(servAddr)); + servAddr.sin_family = AF_INET; + servAddr.sin_addr.s_addr = INADDR_ANY; + servAddr.sin_port = htons(servPort); + if(bind(mConnectFD, (struct sockaddr *) &servAddr, sizeof(servAddr))!=0) + { + logError("CAmTelnetServer::CAmTelnetServer bind failed, error",errno); + throw std::runtime_error("CAmTelnetServer::CAmTelnetServer bind failed"); + } + + if (listen(mConnectFD, mMaxConnections) < 0) + { + logError("TelnetServer::TelnetServerk cannot listen ", errno); + throw std::runtime_error("CAmTelnetServer::CAmTelnetServer bind failed"); + } + else + logInfo("TelnetServer::TelnetServer started listening on port", mServerPort); + + int a = 1; + ioctl(mConnectFD, FIONBIO, (char *) &a); + setsockopt(mConnectFD, SOL_SOCKET, SO_KEEPALIVE, (char *) &a, sizeof(a)); + + short events = 0; + events |= POLLIN; + mpSocketHandler->addFDPoll(mConnectFD, events, NULL, &telnetConnectFiredCB, NULL, NULL, NULL, mConnecthandle); +} + +CAmTelnetServer::~CAmTelnetServer() +{ +} + +void CAmTelnetServer::connectSocket(const pollfd pfd, const sh_pollHandle_t handle, void *userData) +{ + (void) handle; + (void) userData; + //first, accept the connection, create a new filedescriptor + struct sockaddr answer; + socklen_t len = sizeof(answer); + connection_s connection; + connection.handle = 0; + connection.filedescriptor = accept(pfd.fd, (struct sockaddr*) &answer, &len); + + assert(connection.filedescriptor>0); + + // Notiy menuhelper + mTelnetMenuHelper.newSocketConnection(connection.filedescriptor); + + //set the correct event: + short event = 0; + event |= POLLIN; + + //add the filedescriptor to the sockethandler and register the callbacks for receiving the data + mpSocketHandler->addFDPoll(connection.filedescriptor, event, NULL, &telnetReceiveFiredCB, &telnetCheckCB, &telnetDispatchCB, NULL, connection.handle); + mListConnections.push_back(connection); +} + +void CAmTelnetServer::disconnectClient(int filedescriptor) +{ + std::vector<connection_s>::iterator iter = mListConnections.begin(); + while (iter != mListConnections.end()) + { + if (filedescriptor == iter->filedescriptor) + { + if (E_OK == mpSocketHandler->removeFDPoll(iter->handle)) + { + mListConnections.erase(iter); + close(filedescriptor); + } + else + { + // TODO: Handle error + } + + break; + } + iter++; + } +} + +void CAmTelnetServer::receiveData(const pollfd pollfd, const sh_pollHandle_t handle, void *userData) +{ + (void) handle; + (void) userData; + //initialize buffer + char buffer[100]; + //read until buffer is full or no more data is there + int read = recv(pollfd.fd, buffer, 100, 0); + if (read > 1) + { + //read the message and store it in a queue - its a telnet connection so data will be sent on enter ! + std::string msg = std::string(buffer, read); + mListMessages.push(msg); + } +} + +bool CAmTelnetServer::dispatchData(const sh_pollHandle_t handle, void *userData) +{ + (void) userData; + std::vector<connection_s>::iterator iterator = mListConnections.begin(); + for (; iterator != mListConnections.end(); ++iterator) + { + if (iterator->handle == handle) + break; + } + if (iterator==mListConnections.end()) + { + logError("CAmTelnetServer::dispatchData could not find handle !"); + return (false); + } + + std::string command; + std::queue<std::string> MsgQueue; + if (!mListMessages.empty()) + { + sliceCommand(mListMessages.front(), command, MsgQueue); + mListMessages.pop(); + mTelnetMenuHelper.enterCmdQueue(MsgQueue, iterator->filedescriptor); + } + else + { + logError("CAmTelnetServer::dispatchData Message queue was empty!"); + } + + // must return false to stop endless polling + return (false); +} + +bool CAmTelnetServer::check(const sh_pollHandle_t handle, void *userData) +{ + (void) handle; + (void) userData; + if (mListMessages.size() != 0) + return (true); + return (false); +} + +void am::CAmTelnetServer::sliceCommand(const std::string & string, std::string & command, std::queue<std::string> & MsgQueue) +{ + (void) command; + std::stringstream stream(string); + std::istream_iterator<std::string> begin(stream); + std::istream_iterator<std::string> end; + std::string cmd; + bool endOfStream = false; + + int c = 0; + + while (!endOfStream) + { + cmd = *begin; + MsgQueue.push(cmd); + begin++; + + if (begin == end) + { + endOfStream = true; + } + c++; + } +} +} + |