diff options
Diffstat (limited to 'AudioManagerCore')
63 files changed, 24426 insertions, 0 deletions
diff --git a/AudioManagerCore/CMakeLists.txt b/AudioManagerCore/CMakeLists.txt new file mode 100644 index 0000000..2a553ba --- /dev/null +++ b/AudioManagerCore/CMakeLists.txt @@ -0,0 +1,109 @@ +# 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 +# +# For further information see http://www.genivi.org/. +# + +cmake_minimum_required(VERSION 3.0) + +project (AudioManagerCore LANGUAGES CXX VERSION ${DAEMONVERSION}) + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") + +SET(AUDIOMANAGER_CORE_INCLUDE + ${AUDIOMANAGER_CORE}/include + ${AUDIOMANAGER_UTILITIES_INCLUDE} + CACHE INTERNAL "AUDIOMANAGER_CORE_INCLUDE directories" FORCE) + +SET(AUDIO_MANAGER_CORE_LIBS + ${AUDIO_MANAGER_UTILITIES_LIBS} + AudioManagerUtilities + CACHE INTERNAL "AUDIO_MANAGER_CORE_LIBS libs" FORCE) + +IF (WITH_SHARED_CORE) + SET(LIBRARY_TYPE SHARED) +ELSE (WITH_SHARED_CORE) + SET(LIBRARY_TYPE STATIC) +ENDIF (WITH_SHARED_CORE) + +set(AUDIOMAN_CORE_SRCS_CXX + src/CAmCommandReceiver.cpp + src/CAmCommandSender.cpp + src/CAmControlReceiver.cpp + src/CAmControlSender.cpp + src/CAmDatabaseObserver.cpp + src/CAmRoutingReceiver.cpp + src/CAmRoutingSender.cpp + src/CAmRouter.cpp + src/CAmLog.cpp + src/CAmDatabaseHandlerMap.cpp +) + +if(WITH_TELNET) + set (AUDIOMAN_CORE_SRCS_CXX + ${AUDIOMAN_CORE_SRCS_CXX} + src/CAmTelnetServer.cpp + src/CAmTelnetMenuHelper.cpp) +endif(WITH_TELNET) + +INCLUDE_DIRECTORIES(${AUDIOMANAGER_CORE_INCLUDE}) + +ADD_LIBRARY(AudioManagerCore ${LIBRARY_TYPE} ${AUDIOMAN_CORE_SRCS_CXX}) + +TARGET_LINK_LIBRARIES(AudioManagerCore ${AUDIO_MANAGER_CORE_LIBS} ) + +ADD_DEPENDENCIES(AudioManagerCore AudioManagerUtilities) + +set_target_properties(AudioManagerCore PROPERTIES VERSION ${AudioManagerCore_VERSION} SOVERSION ${AudioManagerCore_VERSION_MAJOR}) + + +IF (WITH_SHARED_CORE) + INSTALL(TARGETS AudioManagerCore + LIBRARY DESTINATION lib + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + COMPONENT bin) +ELSE (WITH_SHARED_CORE) + INSTALL(TARGETS AudioManagerCore + ARCHIVE DESTINATION lib + COMPONENT dev) +ENDIF (WITH_SHARED_CORE) + +configure_file( ${CMAKE_SOURCE_DIR}/cmake/audiomanagercore.pc.in ${CMAKE_BINARY_DIR}/audiomanagercore.pc @ONLY ) +install(FILES ${CMAKE_BINARY_DIR}/audiomanagercore.pc DESTINATION lib/pkgconfig COMPONENT devel) + +configure_package_config_file ( + ${CMAKE_SOURCE_DIR}/cmake/AudioManagerCoreConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/AudioManagerCoreConfig.cmake + INSTALL_DESTINATION lib/${LIB_INSTALL_SUFFIX}/cmake + PATH_VARS AUDIO_INCLUDE_FOLDER ) + +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/AudioManagerCoreConfigVersion.cmake + VERSION ${DAEMONVERSION} + COMPATIBILITY SameMajorVersion ) + +install( +FILES ${CMAKE_CURRENT_BINARY_DIR}/AudioManagerCoreConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/AudioManagerCoreConfigVersion.cmake +DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/cmake/AudioManagerCore-${DAEMONVERSION}) + +INSTALL(DIRECTORY "${AUDIOMANAGER_CORE}/include/" + DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${LIB_INSTALL_SUFFIX}/AudioManagerCore + COMPONENT dev) + +if(WITH_TESTS) + add_subdirectory (test) +endif(WITH_TESTS) + + + diff --git a/AudioManagerCore/include/CAmCommandReceiver.h b/AudioManagerCore/include/CAmCommandReceiver.h new file mode 100644 index 0000000..0f30d81 --- /dev/null +++ b/AudioManagerCore/include/CAmCommandReceiver.h @@ -0,0 +1,97 @@ +/** + * 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.h + * For further information see http://www.genivi.org/. + * + */ + +#ifndef COMMANDRECEIVER_H_ +#define COMMANDRECEIVER_H_ + +#include "IAmCommand.h" + +namespace am +{ + +class IAmDatabaseHandler; +class CAmControlSender; +class CAmDbusWrapper; +class CAmSocketHandler; + +/** + * This class realizes the command Interface + */ +class CAmCommandReceiver: public IAmCommandReceive +{ +public: + CAmCommandReceiver(IAmDatabaseHandler* iDatabaseHandler, CAmControlSender* iControlSender, CAmSocketHandler* iSocketHandler); + CAmCommandReceiver(IAmDatabaseHandler* iDatabaseHandler, CAmControlSender* iControlSender, CAmSocketHandler* iSocketHandler, CAmDbusWrapper* iDBusWrapper); + ~CAmCommandReceiver(); + am_Error_e connect(const am_sourceID_t sourceID, const am_sinkID_t sinkID, am_mainConnectionID_t& mainConnectionID); + am_Error_e disconnect(const am_mainConnectionID_t mainConnectionID); + am_Error_e setVolume(const am_sinkID_t sinkID, const am_mainVolume_t volume); + am_Error_e volumeStep(const am_sinkID_t sinkID, const int16_t volumeStep); + am_Error_e setSinkMuteState(const am_sinkID_t sinkID, const am_MuteState_e muteState); + am_Error_e setMainSinkSoundProperty(const am_MainSoundProperty_s& soundProperty, const am_sinkID_t sinkID); + am_Error_e setMainSourceSoundProperty(const am_MainSoundProperty_s& soundProperty, const am_sourceID_t sourceID); + am_Error_e setSystemProperty(const am_SystemProperty_s& property); + am_Error_e getVolume(const am_sinkID_t sinkID, am_mainVolume_t& mainVolume) const; + am_Error_e getListMainConnections(std::vector<am_MainConnectionType_s>& listConnections) const; + am_Error_e getListMainSinks(std::vector<am_SinkType_s>& listMainSinks) const; + am_Error_e getListMainSources(std::vector<am_SourceType_s>& listMainSources) const; + am_Error_e getListMainSinkSoundProperties(const am_sinkID_t sinkID, std::vector<am_MainSoundProperty_s>& listSoundProperties) const; + am_Error_e getListMainSourceSoundProperties(const am_sourceID_t sourceID, std::vector<am_MainSoundProperty_s>& listSourceProperties) const; + am_Error_e getListSourceClasses(std::vector<am_SourceClass_s>& listSourceClasses) const; + am_Error_e getListSinkClasses(std::vector<am_SinkClass_s>& listSinkClasses) const; + am_Error_e getListSystemProperties(std::vector<am_SystemProperty_s>& listSystemProperties) const; + am_Error_e getTimingInformation(const am_mainConnectionID_t mainConnectionID, am_timeSync_t& delay) const; + am_Error_e getDBusConnectionWrapper(CAmDbusWrapper*& dbusConnectionWrapper) const; + am_Error_e getSocketHandler(CAmSocketHandler*& socketHandler) const; + void confirmCommandReady(const uint16_t handle, const am_Error_e error); + void confirmCommandRundown(const uint16_t handle, const am_Error_e error); + void getInterfaceVersion(std::string& version) const; + am_Error_e getListMainSinkNotificationConfigurations(const am_sinkID_t sinkID, std::vector<am_NotificationConfiguration_s>& listMainNotificationConfigurations) const ; + am_Error_e getListMainSourceNotificationConfigurations(const am_sourceID_t sourceID, std::vector<am_NotificationConfiguration_s>& listMainNotificationConfigurations) const ; + am_Error_e setMainSinkNotificationConfiguration(const am_sinkID_t sinkID, const am_NotificationConfiguration_s& mainNotificationConfiguration) ; + am_Error_e setMainSourceNotificationConfiguration(const am_sourceID_t sourceID, const am_NotificationConfiguration_s& mainNotificationConfiguration) ; + + uint16_t getStartupHandle(); //!< returns a startup handle + uint16_t getRundownHandle(); //!< returns a rundown handle + + void waitOnStartup(bool startup); //!< tells the ComandReceiver to start waiting for all handles to be confirmed + void waitOnRundown(bool rundown); //!< tells the ComandReceiver to start waiting for all handles to be confirmed + +private: + IAmDatabaseHandler* mDatabaseHandler; //!< pointer to the databasehandler + CAmControlSender* mControlSender; //!< pointer to the control sender + CAmDbusWrapper* mDBusWrapper; //!< pointer to the dbuswrapper + CAmSocketHandler* mSocketHandler; //!< pointer to the SocketHandler + + uint16_t handleCount; //!< counts all handles + std::vector<uint16_t> mListStartupHandles; //!< list of handles that wait for a confirm + std::vector<uint16_t> mListRundownHandles; //!< list of handles that wait for a confirm + bool mWaitStartup; //!< if true confirmation will be sent if list of handles = 0 + bool mWaitRundown; //!< if true confirmation will be sent if list of handles = 0 + am_Error_e mLastErrorStartup; + am_Error_e mLastErrorRundown; +}; + +} + +#endif /* COMMANDRECEIVER_H_ */ diff --git a/AudioManagerCore/include/CAmCommandSender.h b/AudioManagerCore/include/CAmCommandSender.h new file mode 100644 index 0000000..82363de --- /dev/null +++ b/AudioManagerCore/include/CAmCommandSender.h @@ -0,0 +1,91 @@ +/** + * 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.h + * For further information see http://www.genivi.org/. + * + */ + +#ifndef COMMANDSENDER_H_ +#define COMMANDSENDER_H_ + +#ifdef UNIT_TEST +#include "../test/IAmCommandBackdoor.h" //we need this for the unit test +#endif + +#include "IAmCommand.h" + +namespace am +{ + +class CAmCommandReceiver; + + +/** + * This class is used to send data to the CommandInterface. + * All loaded plugins will be called when a callback is invoked. + */ +class CAmCommandSender +{ +public: + CAmCommandSender(const std::vector<std::string>& listOfPluginDirectories); + ~CAmCommandSender(); + am_Error_e startupInterfaces(CAmCommandReceiver* iCommandReceiver); + void setCommandReady(); + void setCommandRundown(); + void cbNewMainConnection(const am_MainConnectionType_s mainConnection); + void cbRemovedMainConnection(const am_mainConnectionID_t mainConnection); + void cbNewSink(am_SinkType_s sink); + void cbRemovedSink(const am_sinkID_t sink); + void cbNewSource(const am_SourceType_s source); + void cbRemovedSource(const am_sourceID_t source); + void cbNumberOfSinkClassesChanged(); + void cbNumberOfSourceClassesChanged(); + void cbMainConnectionStateChanged(const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState); + void cbMainSinkSoundPropertyChanged(const am_sinkID_t sinkID, const am_MainSoundProperty_s& soundProperty); + void cbMainSourceSoundPropertyChanged(const am_sourceID_t sourceID, const am_MainSoundProperty_s& soundProperty); + void cbSinkAvailabilityChanged(const am_sinkID_t sinkID, const am_Availability_s& availability); + void cbSourceAvailabilityChanged(const am_sourceID_t sourceID, const am_Availability_s& availability); + void cbVolumeChanged(const am_sinkID_t sinkID, const am_mainVolume_t volume); + void cbSinkMuteStateChanged(const am_sinkID_t sinkID, const am_MuteState_e muteState); + void cbSystemPropertyChanged(const am_SystemProperty_s& systemProperty); + void cbTimingInformationChanged(const am_mainConnectionID_t mainConnectionID, const am_timeSync_t time); + void getInterfaceVersion(std::string& version) const; + am_Error_e getListPlugins(std::vector<std::string>& interfaces) const; + void cbSinkUpdated(const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties); + void cbSourceUpdated(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties); + void cbSinkNotification(const am_sinkID_t sinkID, const am_NotificationPayload_s& notification); + void cbSourceNotification(const am_sourceID_t sourceID, const am_NotificationPayload_s& notification); + void cbSinkMainNotificationConfigurationChanged(const am_sinkID_t sinkID, const am_NotificationConfiguration_s& mainNotificationConfiguration); + void cbSourceMainNotificationConfigurationChanged(const am_sourceID_t sourceID, const am_NotificationConfiguration_s& mainNotificationConfiguration); + +#ifdef UNIT_TEST + friend class IAmCommandBackdoor; //this is to get access to the loaded plugins and be able to exchange the interfaces +#endif +private: + void unloadLibraries(void); //!< unload the shared libraries + std::vector<IAmCommandSend*> mListInterfaces; //!< list of all interfaces + std::vector<void*> mListLibraryHandles; //!< list of all library handles. This information is used to unload the plugins correctly. + std::vector<std::string> mListLibraryNames; //!< list of all library names. This information is used for getListPlugins. + + CAmCommandReceiver *mCommandReceiver; +}; + +} + +#endif /* COMMANDSENDER_H_ */ diff --git a/AudioManagerCore/include/CAmControlReceiver.h b/AudioManagerCore/include/CAmControlReceiver.h new file mode 100644 index 0000000..3f39189 --- /dev/null +++ b/AudioManagerCore/include/CAmControlReceiver.h @@ -0,0 +1,156 @@ +/** + * 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.h + * For further information see http://www.genivi.org/. + * + */ + +#ifndef CONTRONLRECEIVER_H_ +#define CONTRONLRECEIVER_H_ + +#include "IAmControl.h" + +namespace am +{ + +class CAmSocketHandler; +class IAmDatabaseHandler; +class CAmRoutingSender; +class CAmCommandSender; +class CAmRouter; +class CAmNodeStateCommunicator; + +/** + * This class is used to receive all commands from the control interface + */ +class CAmControlReceiver: public IAmControlReceive +{ +public: + CAmControlReceiver(IAmDatabaseHandler *iDatabaseHandler, CAmRoutingSender *iRoutingSender, CAmCommandSender *iCommandSender, CAmSocketHandler *iSocketHandler, CAmRouter* iRouter); + ~CAmControlReceiver(); + am_Error_e getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s>& returnList); + am_Error_e connect(am_Handle_s& handle, am_connectionID_t& connectionID, const am_CustomConnectionFormat_t format, const am_sourceID_t sourceID, const am_sinkID_t sinkID); + am_Error_e disconnect(am_Handle_s& handle, const am_connectionID_t connectionID); + am_Error_e 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); + am_Error_e abortAction(const am_Handle_s handle); + am_Error_e setSourceState(am_Handle_s& handle, const am_sourceID_t sourceID, const am_SourceState_e state); + am_Error_e 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); + am_Error_e 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); + am_Error_e setSinkSoundProperties(am_Handle_s& handle, const am_sinkID_t sinkID, const std::vector<am_SoundProperty_s>& soundProperty); + am_Error_e setSinkSoundProperty(am_Handle_s& handle, const am_sinkID_t sinkID, const am_SoundProperty_s& soundProperty); + am_Error_e setSourceSoundProperties(am_Handle_s& handle, const am_sourceID_t sourceID, const std::vector<am_SoundProperty_s>& soundProperty); + am_Error_e setSourceSoundProperty(am_Handle_s& handle, const am_sourceID_t sourceID, const am_SoundProperty_s& soundProperty); + am_Error_e setDomainState(const am_domainID_t domainID, const am_DomainState_e domainState); + am_Error_e enterDomainDB(const am_Domain_s& domainData, am_domainID_t& domainID); + am_Error_e enterMainConnectionDB(const am_MainConnection_s& mainConnectionData, am_mainConnectionID_t& connectionID); + am_Error_e enterSinkDB(const am_Sink_s& sinkData, am_sinkID_t& sinkID); + am_Error_e enterCrossfaderDB(const am_Crossfader_s& crossfaderData, am_crossfaderID_t& crossfaderID); + am_Error_e enterGatewayDB(const am_Gateway_s& gatewayData, am_gatewayID_t& gatewayID); + am_Error_e enterConverterDB(const am_Converter_s & converterData, am_converterID_t & converterID); + am_Error_e enterSourceDB(const am_Source_s& sourceData, am_sourceID_t& sourceID); + am_Error_e enterSinkClassDB(const am_SinkClass_s& sinkClass, am_sinkClass_t& sinkClassID); + am_Error_e enterSourceClassDB(am_sourceClass_t& sourceClassID, const am_SourceClass_s& sourceClass); + am_Error_e changeSinkClassInfoDB(const am_SinkClass_s& sinkClass); + am_Error_e changeSourceClassInfoDB(const am_SourceClass_s& sourceClass); + am_Error_e enterSystemPropertiesListDB(const std::vector<am_SystemProperty_s>& listSystemProperties); + am_Error_e changeMainConnectionRouteDB(const am_mainConnectionID_t mainconnectionID, const std::vector<am_connectionID_t>& listConnectionID); + am_Error_e changeMainConnectionStateDB(const am_mainConnectionID_t mainconnectionID, const am_ConnectionState_e connectionState); + am_Error_e changeSinkMainVolumeDB(const am_mainVolume_t mainVolume, const am_sinkID_t sinkID); + am_Error_e changeSinkAvailabilityDB(const am_Availability_s& availability, const am_sinkID_t sinkID); + am_Error_e changDomainStateDB(const am_DomainState_e domainState, const am_domainID_t domainID); + am_Error_e changeSinkMuteStateDB(const am_MuteState_e muteState, const am_sinkID_t sinkID); + am_Error_e changeMainSinkSoundPropertyDB(const am_MainSoundProperty_s& soundProperty, const am_sinkID_t sinkID); + am_Error_e changeMainSourceSoundPropertyDB(const am_MainSoundProperty_s& soundProperty, const am_sourceID_t sourceID); + am_Error_e changeSourceAvailabilityDB(const am_Availability_s& availability, const am_sourceID_t sourceID); + am_Error_e changeSystemPropertyDB(const am_SystemProperty_s& property); + am_Error_e removeMainConnectionDB(const am_mainConnectionID_t mainConnectionID); + am_Error_e removeSinkDB(const am_sinkID_t sinkID); + am_Error_e removeSourceDB(const am_sourceID_t sourceID); + am_Error_e removeGatewayDB(const am_gatewayID_t gatewayID); + am_Error_e removeConverterDB(const am_converterID_t converterID); + am_Error_e removeCrossfaderDB(const am_crossfaderID_t crossfaderID); + am_Error_e removeDomainDB(const am_domainID_t domainID); + am_Error_e removeSinkClassDB(const am_sinkClass_t sinkClassID); + am_Error_e removeSourceClassDB(const am_sourceClass_t sourceClassID); + am_Error_e getSourceClassInfoDB(const am_sourceID_t sourceID, am_SourceClass_s& classInfo) const; + am_Error_e getSinkClassInfoDB(const am_sinkID_t sinkID, am_SinkClass_s& sinkClass) const; + am_Error_e getSinkInfoDB(const am_sinkID_t sinkID, am_Sink_s& sinkData) const; + am_Error_e getSourceInfoDB(const am_sourceID_t sourceID, am_Source_s& sourceData) const; + am_Error_e getGatewayInfoDB(const am_gatewayID_t gatewayID, am_Gateway_s& gatewayData) const; + am_Error_e getConverterInfoDB(const am_converterID_t converterID, am_Converter_s& converterData) const; + am_Error_e getCrossfaderInfoDB(const am_crossfaderID_t crossfaderID, am_Crossfader_s& crossfaderData) const; + am_Error_e getMainConnectionInfoDB(const am_mainConnectionID_t mainConnectionID, am_MainConnection_s& mainConnectionData) const; + am_Error_e getListSinksOfDomain(const am_domainID_t domainID, std::vector<am_sinkID_t>& listSinkID) const; + am_Error_e getListSourcesOfDomain(const am_domainID_t domainID, std::vector<am_sourceID_t>& listSourceID) const; + am_Error_e getListCrossfadersOfDomain(const am_domainID_t domainID, std::vector<am_crossfaderID_t>& listCrossfadersID) const; + am_Error_e getListGatewaysOfDomain(const am_domainID_t domainID, std::vector<am_gatewayID_t>& listGatewaysID) const; + am_Error_e getListConvertersOfDomain(const am_domainID_t domainID, std::vector<am_converterID_t>& listConverterID) const; + am_Error_e getListMainConnections(std::vector<am_MainConnection_s>& listMainConnections) const; + am_Error_e getListDomains(std::vector<am_Domain_s>& listDomains) const; + am_Error_e getListConnections(std::vector<am_Connection_s>& listConnections) const; + am_Error_e getListSinks(std::vector<am_Sink_s>& listSinks) const; + am_Error_e getListSources(std::vector<am_Source_s>& listSources) const; + am_Error_e getListSourceClasses(std::vector<am_SourceClass_s>& listSourceClasses) const; + am_Error_e getListHandles(std::vector<am_Handle_s>& listHandles) const; + am_Error_e getListCrossfaders(std::vector<am_Crossfader_s>& listCrossfaders) const; + am_Error_e getListGateways(std::vector<am_Gateway_s>& listGateways) const; + am_Error_e getListConverters(std::vector<am_Converter_s>& listConverters) const; + am_Error_e getListSinkClasses(std::vector<am_SinkClass_s>& listSinkClasses) const; + am_Error_e getListSystemProperties(std::vector<am_SystemProperty_s>& listSystemProperties) const; + void setCommandReady(); + void setCommandRundown(); + void setRoutingReady(); + void setRoutingRundown(); + void confirmControllerReady(const am_Error_e error); + void confirmControllerRundown(const am_Error_e error); + am_Error_e getSocketHandler(CAmSocketHandler*& socketHandler); + void getInterfaceVersion(std::string& version) const; + am_Error_e 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) ; + am_Error_e 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) ; + am_Error_e 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) ; + am_Error_e changeConverterDB(const am_converterID_t converterID, const std::vector<am_CustomConnectionFormat_t>& listSourceConnectionFormats, const std::vector<am_CustomConnectionFormat_t>& listSinkConnectionFormats, const std::vector<bool>& convertionMatrix); + am_Error_e setVolumes(am_Handle_s& handle, const std::vector<am_Volumes_s>& listVolumes) ; + am_Error_e setSinkNotificationConfiguration(am_Handle_s& handle, const am_sinkID_t sinkID, const am_NotificationConfiguration_s& notificationConfiguration) ; + am_Error_e setSourceNotificationConfiguration(am_Handle_s& handle, const am_sourceID_t sourceID, const am_NotificationConfiguration_s& notificationConfiguration) ; + void sendMainSinkNotificationPayload(const am_sinkID_t sinkID, const am_NotificationPayload_s& notificationPayload) ; + void sendMainSourceNotificationPayload(const am_sourceID_t sourceID, const am_NotificationPayload_s& notificationPayload) ; + am_Error_e changeMainSinkNotificationConfigurationDB(const am_sinkID_t sinkID, const am_NotificationConfiguration_s& mainNotificationConfiguration) ; + am_Error_e changeMainSourceNotificationConfigurationDB(const am_sourceID_t sourceID, const am_NotificationConfiguration_s& mainNotificationConfiguration) ; + am_Error_e getListMainSinkSoundProperties(const am_sinkID_t sinkID, std::vector<am_MainSoundProperty_s>& listSoundproperties) const; + am_Error_e getListMainSourceSoundProperties(const am_sourceID_t sourceID, std::vector<am_MainSoundProperty_s>& listSoundproperties) const; + am_Error_e getListSinkSoundProperties(const am_sinkID_t sinkID, std::vector<am_SoundProperty_s>& listSoundproperties) const; + am_Error_e getListSourceSoundProperties(const am_sourceID_t sourceID, std::vector<am_SoundProperty_s>& listSoundproperties) const; + am_Error_e getMainSinkSoundPropertyValue(const am_sinkID_t sinkID, const am_CustomMainSoundPropertyType_t propertyType, int16_t& value) const; + am_Error_e getSinkSoundPropertyValue(const am_sinkID_t sinkID, const am_CustomSoundPropertyType_t propertyType, int16_t& value) const; + am_Error_e getMainSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomMainSoundPropertyType_t propertyType, int16_t& value) const; + am_Error_e getSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomSoundPropertyType_t propertyType, int16_t& value) const; + am_Error_e resyncConnectionState(const am_domainID_t domainID, std::vector<am_Connection_s>& listOfExistingConnections); + +private: + IAmDatabaseHandler* mDatabaseHandler; //!< pointer tto the databasehandler + CAmRoutingSender* mRoutingSender; //!< pointer to the routing send interface. + CAmCommandSender* mCommandSender; //!< pointer to the command send interface + CAmSocketHandler* mSocketHandler; //!< pointer to the socketHandler + CAmRouter* mRouter; //!< pointer to the Router + CAmNodeStateCommunicator* mNodeStateCommunicator; +}; + +} + +#endif /* CONTRONLRECEIVER_H_ */ diff --git a/AudioManagerCore/include/CAmControlSender.h b/AudioManagerCore/include/CAmControlSender.h new file mode 100644 index 0000000..40ab379 --- /dev/null +++ b/AudioManagerCore/include/CAmControlSender.h @@ -0,0 +1,154 @@ +/** + * 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.h + * For further information see http://www.genivi.org/. + * + */ + +#ifndef CONTROLSENDER_H_ +#define CONTROLSENDER_H_ + +#ifdef UNIT_TEST +#include "../test/IAmControlBackdoor.h" +#endif + +#include "IAmControl.h" +#include "CAmSocketHandler.h" +#include "unistd.h" + +namespace am +{ + +/** + * sends data to the commandInterface, takes the file of the library that needs to be loaded + */ +class CAmControlSender +{ +public: + CAmControlSender(std::string controlPluginFile,CAmSocketHandler* sockethandler); + CAmControlSender(); + ~CAmControlSender(); + am_Error_e startupController(IAmControlReceive* controlreceiveinterface) ; + void setControllerReady() ; + void setControllerRundown(const int16_t signal) ; + am_Error_e hookUserConnectionRequest(const am_sourceID_t sourceID, const am_sinkID_t sinkID, am_mainConnectionID_t& mainConnectionID) ; + am_Error_e hookUserDisconnectionRequest(const am_mainConnectionID_t connectionID) ; + am_Error_e hookUserSetMainSinkSoundProperty(const am_sinkID_t sinkID, const am_MainSoundProperty_s& soundProperty) ; + am_Error_e hookUserSetMainSourceSoundProperty(const am_sourceID_t sourceID, const am_MainSoundProperty_s& soundProperty) ; + am_Error_e hookUserSetSystemProperty(const am_SystemProperty_s& property) ; + am_Error_e hookUserVolumeChange(const am_sinkID_t SinkID, const am_mainVolume_t newVolume) ; + am_Error_e hookUserVolumeStep(const am_sinkID_t SinkID, const int16_t increment) ; + am_Error_e hookUserSetSinkMuteState(const am_sinkID_t sinkID, const am_MuteState_e muteState) ; + am_Error_e hookSystemRegisterDomain(const am_Domain_s& domainData, am_domainID_t& domainID) ; + am_Error_e hookSystemDeregisterDomain(const am_domainID_t domainID) ; + void hookSystemDomainRegistrationComplete(const am_domainID_t domainID) ; + am_Error_e hookSystemRegisterSink(const am_Sink_s& sinkData, am_sinkID_t& sinkID) ; + am_Error_e hookSystemDeregisterSink(const am_sinkID_t sinkID) ; + am_Error_e hookSystemRegisterSource(const am_Source_s& sourceData, am_sourceID_t& sourceID) ; + am_Error_e hookSystemDeregisterSource(const am_sourceID_t sourceID) ; + am_Error_e hookSystemRegisterGateway(const am_Gateway_s& gatewayData, am_gatewayID_t& gatewayID) ; + am_Error_e hookSystemRegisterConverter(const am_Converter_s& converterData, am_converterID_t& converterID); + am_Error_e hookSystemDeregisterGateway(const am_gatewayID_t gatewayID) ; + am_Error_e hookSystemDeregisterConverter(const am_converterID_t converterID) ; + am_Error_e hookSystemRegisterCrossfader(const am_Crossfader_s& crossfaderData, am_crossfaderID_t& crossfaderID) ; + am_Error_e hookSystemDeregisterCrossfader(const am_crossfaderID_t crossfaderID) ; + void hookSystemSinkVolumeTick(const am_Handle_s handle, const am_sinkID_t sinkID, const am_volume_t volume) ; + void hookSystemSourceVolumeTick(const am_Handle_s handle, const am_sourceID_t sourceID, const am_volume_t volume) ; + void hookSystemInterruptStateChange(const am_sourceID_t sourceID, const am_InterruptState_e interruptState) ; + void hookSystemSinkAvailablityStateChange(const am_sinkID_t sinkID, const am_Availability_s& availability) ; + void hookSystemSourceAvailablityStateChange(const am_sourceID_t sourceID, const am_Availability_s& availability) ; + void hookSystemDomainStateChange(const am_domainID_t domainID, const am_DomainState_e state) ; + void hookSystemReceiveEarlyData(const std::vector<am_EarlyData_s>& data) ; + void hookSystemSpeedChange(const am_speed_t speed) ; + void hookSystemTimingInformationChanged(const am_mainConnectionID_t mainConnectionID, const am_timeSync_t time) ; + void cbAckConnect(const am_Handle_s handle, const am_Error_e errorID) ; + void cbAckDisconnect(const am_Handle_s handle, const am_Error_e errorID) ; + void cbAckCrossFade(const am_Handle_s handle, const am_HotSink_e hostsink, const am_Error_e error) ; + void cbAckSetSinkVolumeChange(const am_Handle_s handle, const am_volume_t volume, const am_Error_e error) ; + void cbAckSetSourceVolumeChange(const am_Handle_s handle, const am_volume_t voulme, const am_Error_e error) ; + void cbAckSetSourceState(const am_Handle_s handle, const am_Error_e error) ; + void cbAckSetSourceSoundProperties(const am_Handle_s handle, const am_Error_e error) ; + void cbAckSetSourceSoundProperty(const am_Handle_s handle, const am_Error_e error) ; + void cbAckSetSinkSoundProperties(const am_Handle_s handle, const am_Error_e error) ; + void cbAckSetSinkSoundProperty(const am_Handle_s handle, const am_Error_e error) ; + am_Error_e getConnectionFormatChoice(const am_sourceID_t sourceID, const am_sinkID_t sinkID, const am_Route_s listRoute, const std::vector<am_CustomConnectionFormat_t> listPossibleConnectionFormats, std::vector<am_CustomConnectionFormat_t>& listPrioConnectionFormats) ; + void confirmCommandReady(const am_Error_e error) ; + void confirmRoutingReady(const am_Error_e error) ; + void confirmCommandRundown(const am_Error_e error) ; + void confirmRoutingRundown(const am_Error_e error) ; + void getInterfaceVersion(std::string& version) const ; + am_Error_e 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) ; + am_Error_e 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) ; + am_Error_e 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) ; + am_Error_e 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); + void cbAckSetVolume(const am_Handle_s handle, const std::vector<am_Volumes_s>& listVolumes, const am_Error_e error) ; + void cbAckSetSinkNotificationConfiguration(const am_Handle_s handle, const am_Error_e error) ; + void cbAckSetSourceNotificationConfiguration(const am_Handle_s handle, const am_Error_e error) ; + void hookSinkNotificationDataChanged(const am_sinkID_t sinkID, const am_NotificationPayload_s& payload) ; + void hookSourceNotificationDataChanged(const am_sourceID_t sourceID, const am_NotificationPayload_s& payload) ; + am_Error_e hookUserSetMainSinkNotificationConfiguration(const am_sinkID_t sinkID, const am_NotificationConfiguration_s& notificationConfiguration) ; + am_Error_e hookUserSetMainSourceNotificationConfiguration(const am_sourceID_t sourceID, const am_NotificationConfiguration_s& notificationConfiguration) ; + void hookSystemSingleTimingInformationChanged(const am_connectionID_t connectionID, const am_timeSync_t time); + + void receiverCallback(const pollfd pollfd, const sh_pollHandle_t handle, void* userData); + bool checkerCallback(const sh_pollHandle_t handle, void* userData); + bool dispatcherCallback(const sh_pollHandle_t handle, void* userData); + + void setControllerRundownSafe(int16_t signal) + { + int16_t p(signal); + ssize_t result(-1); + result = write(mPipe[1], &p, sizeof(p)); + } + + TAmShPollFired<CAmControlSender> receiverCallbackT; + TAmShPollCheck<CAmControlSender> checkerCallbackT; + TAmShPollDispatch<CAmControlSender> dispatcherCallbackT; + + + //we need this here to call the rundown from the signal handler. In case everything screwed up + static void CallsetControllerRundown(int16_t signal) + { + if (mInstance) + mInstance->setControllerRundown(signal); + } + + //this static callback is used from the signal handler. It is used when a normal rundown is assumed and the mainloop is used to call rundown. + static void CallsetControllerRundownSafe(int16_t signal) + { + if (mInstance) + { + mInstance->setControllerRundownSafe(signal); + } + } + +#ifdef UNIT_TEST + friend class IAmControlBackdoor; +#endif +private: + int mPipe[2]; + void* mlibHandle; //!< pointer to the loaded control plugin interface + IAmControlSend* mController; //!< pointer to the ControlSend interface + static CAmControlSender* mInstance; + int16_t mSignal; +}; + +} + +#endif /* CONTROLSENDER_H_ */ diff --git a/AudioManagerCore/include/CAmDatabaseHandlerMap.h b/AudioManagerCore/include/CAmDatabaseHandlerMap.h new file mode 100644 index 0000000..cf319f7 --- /dev/null +++ b/AudioManagerCore/include/CAmDatabaseHandlerMap.h @@ -0,0 +1,495 @@ +/** + * 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.h + * For further information see http://www.genivi.org/. + * + */ + +#ifndef MAPHANDLER_H_ +#define MAPHANDLER_H_ + +#include <stdint.h> +#include <limits.h> +#include <sstream> +#include <iostream> +#include <unordered_map> +#include <algorithm> +#include <assert.h> +#include <vector> +#include "IAmDatabaseHandler.h" + +namespace am +{ +#ifndef AM_MAP_CAPACITY + #define AM_MAP_CAPACITY 0 +#endif + +#ifndef AM_MAX_CONNECTIONS + #define AM_MAX_CONNECTIONS 0x1000 +#endif + +#ifndef AM_MAX_MAIN_CONNECTIONS + #define AM_MAX_MAIN_CONNECTIONS SHRT_MAX +#endif + + + +//todo: check the enum values before entering & changing in the database. +//todo: change asserts for dynamic boundary checks into failure answers.# +//todo: check autoincrement boundary and set to 16bit limits +//todo: If the sink is part of a gateway, the listconnectionFormats is copied to the gatewayInformation. Check this statement for sinks & sources +//todo: exchange last_insert_row id to be more safe +//todo: create test to ensure uniqueness of names throughout the database +//todo: enforce the uniqueness of names + +/** + * This class handles and abstracts the database + */ +class CAmDatabaseHandlerMap : public IAmDatabaseHandler +{ + bool mFirstStaticSink; //!< bool for dynamic range handling + bool mFirstStaticSource; //!< bool for dynamic range handling + bool mFirstStaticGateway; //!< bool for dynamic range handling + bool mFirstStaticConverter; //!< bool for dynamic range handling + bool mFirstStaticSinkClass; //!< bool for dynamic range handling + bool mFirstStaticSourceClass; //!< bool for dynamic range handling + bool mFirstStaticCrossfader; //!< bool for dynamic range handling + +public: + CAmDatabaseHandlerMap(); + virtual ~CAmDatabaseHandlerMap(); + am_Error_e enterDomainDB(const am_Domain_s& domainData, am_domainID_t& domainID); + am_Error_e enterMainConnectionDB(const am_MainConnection_s& mainConnectionData, am_mainConnectionID_t& connectionID); + am_Error_e enterSinkDB(const am_Sink_s& sinkData, am_sinkID_t& sinkID); + am_Error_e enterCrossfaderDB(const am_Crossfader_s& crossfaderData, am_crossfaderID_t& crossfaderID); + am_Error_e enterGatewayDB(const am_Gateway_s& gatewayData, am_gatewayID_t& gatewayID); + am_Error_e enterConverterDB(const am_Converter_s & converterData, am_converterID_t & converterID); + am_Error_e enterSourceDB(const am_Source_s& sourceData, am_sourceID_t& sourceID); + am_Error_e enterConnectionDB(const am_Connection_s& connection, am_connectionID_t& connectionID); + am_Error_e enterSinkClassDB(const am_SinkClass_s& sinkClass, am_sinkClass_t& sinkClassID); + am_Error_e enterSourceClassDB(am_sourceClass_t& sourceClassID, const am_SourceClass_s& sourceClass); + am_Error_e enterSystemProperties(const std::vector<am_SystemProperty_s>& listSystemProperties); + am_Error_e changeMainConnectionRouteDB(const am_mainConnectionID_t mainconnectionID, const std::vector<am_connectionID_t>& listConnectionID); + am_Error_e changeMainConnectionStateDB(const am_mainConnectionID_t mainconnectionID, const am_ConnectionState_e connectionState); + am_Error_e changeSinkMainVolumeDB(const am_mainVolume_t mainVolume, const am_sinkID_t sinkID); + am_Error_e changeSinkAvailabilityDB(const am_Availability_s& availability, const am_sinkID_t sinkID); + am_Error_e changDomainStateDB(const am_DomainState_e domainState, const am_domainID_t domainID); + am_Error_e changeSinkMuteStateDB(const am_MuteState_e muteState, const am_sinkID_t sinkID); + am_Error_e changeMainSinkSoundPropertyDB(const am_MainSoundProperty_s& soundProperty, const am_sinkID_t sinkID); + am_Error_e changeMainSourceSoundPropertyDB(const am_MainSoundProperty_s& soundProperty, const am_sourceID_t sourceID); + am_Error_e changeSourceSoundPropertyDB(const am_SoundProperty_s& soundProperty, const am_sourceID_t sourceID); + am_Error_e changeSinkSoundPropertyDB(const am_SoundProperty_s& soundProperty, const am_sinkID_t sinkID); + am_Error_e changeSourceAvailabilityDB(const am_Availability_s& availability, const am_sourceID_t sourceID); + am_Error_e changeSystemPropertyDB(const am_SystemProperty_s& property); + am_Error_e changeDelayMainConnection(const am_timeSync_t & delay, const am_mainConnectionID_t & connectionID); + am_Error_e changeSinkClassInfoDB(const am_SinkClass_s& sinkClass); + am_Error_e changeSourceClassInfoDB(const am_SourceClass_s& sourceClass); + am_Error_e changeConnectionTimingInformation(const am_connectionID_t connectionID, const am_timeSync_t delay); + am_Error_e changeConnectionFinal(const am_connectionID_t connectionID); + am_Error_e changeSourceState(const am_sourceID_t sourceID, const am_SourceState_e sourceState); + am_Error_e changeSinkVolume(const am_sinkID_t sinkID, const am_volume_t volume); + am_Error_e changeSourceVolume(const am_sourceID_t sourceID, const am_volume_t volume); + am_Error_e changeCrossFaderHotSink(const am_crossfaderID_t crossfaderID, const am_HotSink_e hotsink); + am_Error_e removeMainConnectionDB(const am_mainConnectionID_t mainConnectionID); + am_Error_e removeSinkDB(const am_sinkID_t sinkID); + am_Error_e removeSourceDB(const am_sourceID_t sourceID); + am_Error_e removeGatewayDB(const am_gatewayID_t gatewayID); + am_Error_e removeConverterDB(const am_converterID_t converterID); + am_Error_e removeCrossfaderDB(const am_crossfaderID_t crossfaderID); + am_Error_e removeDomainDB(const am_domainID_t domainID); + am_Error_e removeSinkClassDB(const am_sinkClass_t sinkClassID); + am_Error_e removeSourceClassDB(const am_sourceClass_t sourceClassID); + am_Error_e removeConnection(const am_connectionID_t connectionID); + am_Error_e getSourceClassInfoDB(const am_sourceID_t sourceID, am_SourceClass_s& classInfo) const; + am_Error_e getSinkClassInfoDB(const am_sinkID_t sinkID, am_SinkClass_s& sinkClass) const; + am_Error_e getGatewayInfoDB(const am_gatewayID_t gatewayID, am_Gateway_s& gatewayData) const; + am_Error_e getConverterInfoDB(const am_converterID_t converterID, am_Converter_s& converterData) const; + am_Error_e getSinkInfoDB(const am_sinkID_t sinkID, am_Sink_s& sinkData) const; + am_Error_e getSourceInfoDB(const am_sourceID_t sourceID, am_Source_s& sourceData) const; + am_Error_e getCrossfaderInfoDB(const am_crossfaderID_t crossfaderID, am_Crossfader_s& crossfaderData) const; + am_Error_e getMainConnectionInfoDB(const am_mainConnectionID_t mainConnectionID, am_MainConnection_s& mainConnectionData) const; + am_Error_e getSinkMainVolume(const am_sinkID_t sinkID, am_mainVolume_t& mainVolume) const; + am_Error_e getSinkVolume(const am_sinkID_t sinkID, am_volume_t& volume) const; + am_Error_e getSourceVolume(const am_sourceID_t sourceID, am_volume_t& volume) const; + am_Error_e getSinkSoundPropertyValue(const am_sinkID_t sinkID, const am_CustomSoundPropertyType_t propertyType, int16_t& value) const; + am_Error_e getSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomSoundPropertyType_t propertyType, int16_t& value) const; + am_Error_e getMainSinkSoundPropertyValue(const am_sinkID_t sinkID, const am_CustomMainSoundPropertyType_t propertyType, int16_t& value) const; + am_Error_e getMainSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomMainSoundPropertyType_t propertyType, int16_t& value) const; + am_Error_e getListSinkSoundProperties(const am_sinkID_t sinkID, std::vector<am_SoundProperty_s>& listSoundproperties) const; + am_Error_e getListSourceSoundProperties(const am_sourceID_t sourceID, std::vector<am_SoundProperty_s>& listSoundproperties) const; + am_Error_e getListSinksOfDomain(const am_domainID_t domainID, std::vector<am_sinkID_t>& listSinkID) const; + am_Error_e getListSourcesOfDomain(const am_domainID_t domainID, std::vector<am_sourceID_t>& listSourceID) const; + am_Error_e getListCrossfadersOfDomain(const am_domainID_t domainID, std::vector<am_crossfaderID_t>& listGatewaysID) const; + am_Error_e getListGatewaysOfDomain(const am_domainID_t domainID, std::vector<am_gatewayID_t>& listGatewaysID) const; + am_Error_e getListConvertersOfDomain(const am_domainID_t domainID, std::vector<am_converterID_t>& listConvertersID) const; + am_Error_e getListMainConnections(std::vector<am_MainConnection_s>& listMainConnections) const; + am_Error_e getListDomains(std::vector<am_Domain_s>& listDomains) const; + am_Error_e getListConnections(std::vector<am_Connection_s>& listConnections) const; + am_Error_e getListSinks(std::vector<am_Sink_s>& listSinks) const; + am_Error_e getListSources(std::vector<am_Source_s>& lisSources) const; + am_Error_e getListSourceClasses(std::vector<am_SourceClass_s>& listSourceClasses) const; + am_Error_e getListCrossfaders(std::vector<am_Crossfader_s>& listCrossfaders) const; + am_Error_e getListGateways(std::vector<am_Gateway_s>& listGateways) const; + am_Error_e getListConverters(std::vector<am_Converter_s> & listConverters) const; + am_Error_e getListSinkClasses(std::vector<am_SinkClass_s>& listSinkClasses) const; + am_Error_e getListVisibleMainConnections(std::vector<am_MainConnectionType_s>& listConnections) const; + am_Error_e getListMainSinks(std::vector<am_SinkType_s>& listMainSinks) const; + am_Error_e getListMainSources(std::vector<am_SourceType_s>& listMainSources) const; + am_Error_e getListMainSinkSoundProperties(const am_sinkID_t sinkID, std::vector<am_MainSoundProperty_s>& listSoundProperties) const; + am_Error_e getListMainSourceSoundProperties(const am_sourceID_t sourceID, std::vector<am_MainSoundProperty_s>& listSourceProperties) const; + am_Error_e getListSystemProperties(std::vector<am_SystemProperty_s>& listSystemProperties) const; + am_Error_e getListSinkConnectionFormats(const am_sinkID_t sinkID, std::vector<am_CustomAvailabilityReason_t> & listConnectionFormats) const; + am_Error_e getListSourceConnectionFormats(const am_sourceID_t sourceID, std::vector<am_CustomAvailabilityReason_t> & listConnectionFormats) const; + am_Error_e getListGatewayConnectionFormats(const am_gatewayID_t gatewayID, std::vector<bool> & listConnectionFormat) const; + am_Error_e getTimingInformation(const am_mainConnectionID_t mainConnectionID, am_timeSync_t& delay) const; + am_Error_e getDomainOfSource(const am_sourceID_t sourceID, am_domainID_t& domainID) const; + am_Error_e getDomainOfSink(const am_sinkID_t sinkID, am_domainID_t& domainID) const; + am_Error_e getDomainOfCrossfader(const am_converterID_t crossfader, am_domainID_t& domainID) const; + am_Error_e getSoureState(const am_sourceID_t sourceID, am_SourceState_e& sourceState) const; + am_Error_e getDomainState(const am_domainID_t domainID, am_DomainState_e& state) const; + am_Error_e peekDomain(const std::string& name, am_domainID_t& domainID); + am_Error_e peekSink(const std::string& name, am_sinkID_t& sinkID); + am_Error_e peekSource(const std::string& name, am_sourceID_t& sourceID); + am_Error_e peekSinkClassID(const std::string& name, am_sinkClass_t& sinkClassID); + am_Error_e peekSourceClassID(const std::string& name, am_sourceClass_t& sourceClassID); + am_Error_e changeSourceDB(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_SoundProperty_s>& listSoundProperties, const std::vector<am_CustomAvailabilityReason_t>& listConnectionFormats, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties); + am_Error_e changeSinkDB(const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector<am_SoundProperty_s>& listSoundProperties, const std::vector<am_CustomAvailabilityReason_t>& listConnectionFormats, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties); + am_Error_e getListMainSinkNotificationConfigurations(const am_sinkID_t sinkID, std::vector<am_NotificationConfiguration_s>& listMainNotificationConfigurations); + am_Error_e getListMainSourceNotificationConfigurations(const am_sourceID_t sourceID, std::vector<am_NotificationConfiguration_s>& listMainNotificationConfigurations); + am_Error_e changeMainSinkNotificationConfigurationDB(const am_sinkID_t sinkID, const am_NotificationConfiguration_s mainNotificationConfiguration); + am_Error_e changeMainSourceNotificationConfigurationDB(const am_sourceID_t sourceID, const am_NotificationConfiguration_s mainNotificationConfiguration); + am_Error_e changeGatewayDB(const am_gatewayID_t gatewayID, const std::vector<am_CustomAvailabilityReason_t>& listSourceConnectionFormats, const std::vector<am_CustomAvailabilityReason_t>& listSinkConnectionFormats, const std::vector<bool>& convertionMatrix); + am_Error_e changeConverterDB(const am_converterID_t converterID, const std::vector<am_CustomConnectionFormat_t>& listSourceConnectionFormats, const std::vector<am_CustomConnectionFormat_t>& listSinkConnectionFormats, const std::vector<bool>& convertionMatrix); + am_Error_e changeSinkNotificationConfigurationDB(const am_sinkID_t sinkID,const am_NotificationConfiguration_s notificationConfiguration); + am_Error_e changeSourceNotificationConfigurationDB(const am_sourceID_t sourceID,const am_NotificationConfiguration_s notificationConfiguration); + + bool existMainConnection(const am_mainConnectionID_t mainConnectionID) const; + bool existCrossFader(const am_crossfaderID_t crossfaderID) const; + bool existConnection(const am_Connection_s & connection) const; + bool existConnectionID(const am_connectionID_t connectionID) const; + bool existSource(const am_sourceID_t sourceID) const; + bool existSourceNameOrID(const am_sourceID_t sourceID, const std::string& name) const; + bool existSourceName(const std::string& name) const; + bool existSink(const am_sinkID_t sinkID) const; + bool existSinkNameOrID(const am_sinkID_t sinkID, const std::string& name) const; + bool existSinkName(const std::string& name) const; + bool existDomain(const am_domainID_t domainID) const; + bool existGateway(const am_gatewayID_t gatewayID) const; + bool existConverter(const am_converterID_t converterID) const; + bool existSinkClass(const am_sinkClass_t sinkClassID) const; + bool existSourceClass(const am_sourceClass_t sourceClassID) const; + void registerObserver(CAmDatabaseObserver *iObserver); + bool sourceVisible(const am_sourceID_t sourceID) const; + bool sinkVisible(const am_sinkID_t sinkID) const; + bool isComponentConnected(const am_Gateway_s & gateway) const; + bool isComponentConnected(const am_Converter_s & converter) const; + void dump( std::ostream & output ) const; + am_Error_e enumerateSources(std::function<void(const am_Source_s & element)> cb) const; + am_Error_e enumerateSinks(std::function<void(const am_Sink_s & element)> cb) const; + am_Error_e enumerateGateways(std::function<void(const am_Gateway_s & element)> cb) const; + am_Error_e enumerateConverters(std::function<void(const am_Converter_s & element)> cb) const; + /** + * The following structures extend the base structures with the field 'reserved'. + */ + +#define AM_SUBCLASS_BEGIN(Subclass, Class) \ + typedef struct Subclass : public Class\ + { + +#define AM_SUBCLASS_CONSTR(Subclass, Class) \ + Subclass():Class() + +#define AM_SUBCLASS_CONSTR_BODY()\ + {}; + +#define AM_SUBCLASS_COPY_OP_START(Subclass, Class) \ + Subclass & operator=(const Subclass & anObject)\ + {\ + if (this != &anObject)\ + {\ + Class::operator=(anObject); + +#define AM_SUBCLASS_COPY_OP_END()\ + }\ + return *this;\ + }; + +#define AM_SUBCLASS_OP(Subclass, Class) \ + Subclass & operator=(const Class & anObject)\ + {\ + if (this != &anObject)\ + Class::operator=(anObject);\ + return *this;\ + }; + +#define AM_SUBCLASS_END(Typedef) \ + void getDescription (std::string & outString) const;\ + } Typedef; + +#define AM_TYPEDEF_SUBCLASS_RESERVED_FLAG_BEGIN(Subclass, Class)\ + AM_SUBCLASS_BEGIN(Subclass, Class)\ + bool reserved;\ + AM_SUBCLASS_CONSTR(Subclass, Class)\ + ,reserved(false)\ + AM_SUBCLASS_CONSTR_BODY()\ + AM_SUBCLASS_COPY_OP_START(Subclass, Class)\ + reserved = anObject.reserved;\ + AM_SUBCLASS_COPY_OP_END()\ + AM_SUBCLASS_OP(Subclass, Class)\ + +#define AM_TYPEDEF_SUBCLASS_SOUND_PROPERTIES_BEGIN(Subclass, Class)\ + AM_SUBCLASS_BEGIN(Subclass, Class)\ + bool reserved;\ + std::unordered_map<am_CustomSoundPropertyType_t, int16_t> cacheSoundProperties;\ + std::unordered_map<am_CustomMainSoundPropertyType_t, int16_t> cacheMainSoundProperties;\ + AM_SUBCLASS_CONSTR(Subclass, Class)\ + ,reserved(false), cacheSoundProperties(), cacheMainSoundProperties()\ + AM_SUBCLASS_CONSTR_BODY()\ + AM_SUBCLASS_COPY_OP_START(Subclass, Class)\ + reserved = anObject.reserved;\ + cacheSoundProperties = anObject.cacheSoundProperties;\ + cacheMainSoundProperties = anObject.cacheMainSoundProperties;\ + AM_SUBCLASS_COPY_OP_END()\ + AM_SUBCLASS_OP(Subclass, Class)\ + +#define AM_TYPEDEF_SUBCLASS_BEGIN(Subclass, Class)\ + AM_SUBCLASS_BEGIN(Subclass, Class)\ + AM_SUBCLASS_COPY_OP_START(Subclass, Class)\ + AM_SUBCLASS_COPY_OP_END()\ + AM_SUBCLASS_OP(Subclass, Class)\ + + + AM_TYPEDEF_SUBCLASS_RESERVED_FLAG_BEGIN(am_Domain_Database_s,am_Domain_s) + AM_SUBCLASS_END(CAmDomain) + + AM_TYPEDEF_SUBCLASS_SOUND_PROPERTIES_BEGIN(am_Sink_Database_s,am_Sink_s) + void getSinkType(am_SinkType_s & sinkType) const;\ + AM_SUBCLASS_END(CAmSink) + + AM_TYPEDEF_SUBCLASS_SOUND_PROPERTIES_BEGIN(am_Source_Database_s,am_Source_s) + void getSourceType(am_SourceType_s & sourceType) const;\ + AM_SUBCLASS_END(CAmSource) + + AM_TYPEDEF_SUBCLASS_RESERVED_FLAG_BEGIN(am_Connection_Database_s,am_Connection_s) + AM_SUBCLASS_END(CAmConnection) + + /** + * The following structures extend the base structures with print capabilities. + */ + AM_TYPEDEF_SUBCLASS_BEGIN(am_MainConnection_Database_s, am_MainConnection_s) + void getMainConnectionType(am_MainConnectionType_s & connectionType) const;\ + AM_SUBCLASS_END(CAmMainConnection) + + AM_TYPEDEF_SUBCLASS_BEGIN(am_SourceClass_Database_s, am_SourceClass_s) + AM_SUBCLASS_END(CAmSourceClass) + + AM_TYPEDEF_SUBCLASS_BEGIN(am_SinkClass_Database_s, am_SinkClass_s) + AM_SUBCLASS_END(CAmSinkClass) + + AM_TYPEDEF_SUBCLASS_BEGIN(am_Gateway_Database_s, am_Gateway_s) + AM_SUBCLASS_END(CAmGateway) + + AM_TYPEDEF_SUBCLASS_BEGIN(am_Converter_Database_s, am_Converter_s) + AM_SUBCLASS_END(CAmConverter) + + AM_TYPEDEF_SUBCLASS_BEGIN(am_Crossfader_Database_s, am_Crossfader_s) + AM_SUBCLASS_END(CAmCrossfader) + + private: + typedef std::unordered_map<am_domainID_t, CAmDomain> CAmMapDomain; + typedef std::unordered_map<am_sourceClass_t, CAmSourceClass> CAmMapSourceClass; + typedef std::unordered_map<am_sinkClass_t, CAmSinkClass> CAmMapSinkClass; + typedef std::unordered_map<am_sinkID_t, CAmSink> CAmMapSink; + typedef std::unordered_map<am_sourceID_t, CAmSource> CAmMapSource; + typedef std::unordered_map<am_gatewayID_t, CAmGateway> CAmMapGateway; + typedef std::unordered_map<am_converterID_t, CAmConverter> CAmMapConverter; + typedef std::unordered_map<am_crossfaderID_t, CAmCrossfader> CAmMapCrossfader; + typedef std::unordered_map<am_connectionID_t, CAmConnection> CAmMapConnection; + typedef std::unordered_map<am_mainConnectionID_t, CAmMainConnection> CAmMapMainConnection; + typedef std::vector<am_SystemProperty_s> CAmVectorSystemProperties; + /** + * The following structure groups the map objects needed for the implementation. + * Every map object is coupled with an identifier, which hold the current value. + * DYNAMIC_ID_BOUNDARY is used as initial value everywhere a dynamic id is considered . + * The IDs can be increased through the method increaseID(...), which follows the AudioManager logic. + * For more information about the static and dynamic IDs, please see the documentation. + */ + typedef struct CAmMappedData + { + /** + * The structure encapsulates the id boundary and the current id value. + * It defines a range within the id can vary. + */ + struct am_Identifier_s + { + int16_t mMin; //!< min possible value + int16_t mMax; //!< max possible value + int16_t mCurrentValue; //!< current value + + am_Identifier_s():mMin(DYNAMIC_ID_BOUNDARY), mMax(SHRT_MAX), mCurrentValue(mMin){}; + am_Identifier_s(const int16_t & min, const int16_t & max):mMin(min), mMax(max), mCurrentValue(mMin){assert(min<max);}; + }; + + am_Identifier_s mCurrentDomainID; //!< domain ID + am_Identifier_s mCurrentSourceClassesID; //!< source classes ID + am_Identifier_s mCurrentSinkClassesID; //!< sink classes ID + am_Identifier_s mCurrentSinkID; //!< sink ID + am_Identifier_s mCurrentSourceID; //!< source ID + am_Identifier_s mCurrentGatewayID; //!< gateway ID + am_Identifier_s mCurrentConverterID; //!< converter ID + am_Identifier_s mCurrentCrossfaderID; //!< crossfader ID + am_Identifier_s mCurrentConnectionID; //!< connection ID + am_Identifier_s mCurrentMainConnectionID; //!< mainconnection ID + + CAmVectorSystemProperties mSystemProperties; //!< vector with system properties + CAmMapDomain mDomainMap; //!< map for domain structures + CAmMapSourceClass mSourceClassesMap; //!< map for source classes structures + CAmMapSinkClass mSinkClassesMap; //!< map for sink classes structures + CAmMapSink mSinkMap; //!< map for sink structures + CAmMapSource mSourceMap; //!< map for source structures + CAmMapGateway mGatewayMap; //!< map for gateway structures + CAmMapConverter mConverterMap; //!< map for converter structures + CAmMapCrossfader mCrossfaderMap; //!< map for crossfader structures + CAmMapConnection mConnectionMap; //!< map for connection structures + CAmMapMainConnection mMainConnectionMap; //!< map for main connection structures + + CAmMappedData(): //For Domain, MainConnections, Connections we don't have static IDs. + mCurrentDomainID(DYNAMIC_ID_BOUNDARY, SHRT_MAX), + mCurrentSourceClassesID(DYNAMIC_ID_BOUNDARY, SHRT_MAX), + mCurrentSinkClassesID(DYNAMIC_ID_BOUNDARY, SHRT_MAX), + mCurrentSinkID(DYNAMIC_ID_BOUNDARY, SHRT_MAX), + mCurrentSourceID(DYNAMIC_ID_BOUNDARY, SHRT_MAX), + mCurrentGatewayID(DYNAMIC_ID_BOUNDARY, SHRT_MAX), + mCurrentConverterID(DYNAMIC_ID_BOUNDARY, SHRT_MAX), + mCurrentCrossfaderID(DYNAMIC_ID_BOUNDARY, SHRT_MAX), + mCurrentConnectionID(1, AM_MAX_CONNECTIONS), + mCurrentMainConnectionID(1, AM_MAX_MAIN_CONNECTIONS), + + mSystemProperties(), + mDomainMap(),mSourceClassesMap(), mSinkClassesMap(), mSinkMap(AM_MAP_CAPACITY), mSourceMap(AM_MAP_CAPACITY), + mGatewayMap(), mConverterMap(), mCrossfaderMap(), mConnectionMap(), mMainConnectionMap() + {}; + /** + * \brief Increases a given map ID. + * + * A common method implementing the logic for static and dynamic IDs except main connection ID. + * + * @param resultID Pointer to an output variable. + * @param sourceID Pointer to ID, which will be manipulated. + * @param desiredStaticID Not 0 for static IDs and 0 for dynamic IDs. + * Usually the static IDs are in interval [1 , DYNAMIC_ID_BOUNDARY]. Default is 0. + * @param preferedStaticIDBoundary A limit for a given dynamic ID. Default is DYNAMIC_ID_BOUNDARY. + * @return TRUE on successfully changed ID. + */ + bool increaseID(int16_t & resultID, am_Identifier_s & sourceID, int16_t const desiredStaticID); + /** + * \brief Increases the main connection ID. + * + * @param resultID Pointer to an output variable. + * @return TRUE on successfully changed ID. + */ + bool increaseMainConnectionID(int16_t & resultID); + + /** + * \brief Increases the connection ID. + * + * @param resultID Pointer to an output variable. + * @return TRUE on successfully changed ID. + */ + bool increaseConnectionID(int16_t & resultID); + + template <class TPrintObject> static void print (const TPrintObject & t, std::ostream & output) + { + std::string description; + t.getDescription( description ); + output << description; + } + template <typename TPrintMapKey,class TPrintMapObject> static void printMap (const std::unordered_map<TPrintMapKey, TPrintMapObject> & t, std::ostream & output) + { + typename std::unordered_map<TPrintMapKey, TPrintMapObject>::const_iterator iter = t.begin(); + for(; iter!=t.end(); iter++) + CAmMappedData::print(iter->second, output); + } + private: + template <typename TMapKey,class TMapObject> bool getNextConnectionID(int16_t & resultID, am_Identifier_s & sourceID, + const std::unordered_map<TMapKey, TMapObject> & map); + } CAmMappedData; + /* + * Helper methods. + */ + am_timeSync_t calculateMainConnectionDelay(const am_mainConnectionID_t mainConnectionID) const; //!< calculates a new main connection delay + int16_t calculateDelayForRoute(const std::vector<am_connectionID_t>& listConnectionID); + bool insertSinkDB(const am_Sink_s & sinkData, am_sinkID_t & sinkID); + bool insertCrossfaderDB(const am_Crossfader_s & crossfaderData, am_crossfaderID_t & crossfaderID); + bool insertGatewayDB(const am_Gateway_s & gatewayData, am_gatewayID_t & gatewayID); + bool insertConverterDB(const am_Converter_s & converteData, am_converterID_t & converterID); + bool insertSourceDB(const am_Source_s & sourceData, am_sourceID_t & sourceID); + bool insertSinkClassDB(const am_SinkClass_s & sinkClass, am_sinkClass_t & sinkClassID); + bool insertSourceClassDB(am_sourceClass_t & sourceClassID, const am_SourceClass_s & sourceClass); + const am_Sink_Database_s * sinkWithNameOrID(const am_sinkID_t sinkID, const std::string & name) const; + const am_Source_Database_s * sourceWithNameOrID(const am_sourceID_t sourceID, const std::string & name) const; + template <class Component> bool isConnected(const Component & comp) const + { + return std::find_if(mMappedData.mConnectionMap.begin(), mMappedData.mConnectionMap.end(),[&](const std::pair<am_connectionID_t, am_Connection_Database_s>& rConnection){ + return (rConnection.second.sinkID == comp.sinkID ||rConnection.second.sourceID ==comp.sourceID);})!=mMappedData.mConnectionMap.end(); + } + void filterDuplicateNotificationConfigurationTypes(std::vector<am_NotificationConfiguration_s> & list) + { + std::vector<am_NotificationConfiguration_s> oldList(list); + list.clear(); + std::for_each(oldList.begin(), oldList.end(), [&](am_NotificationConfiguration_s & provided) { + std::vector<am_NotificationConfiguration_s>::iterator found = + std::find_if(list.begin(), list.end(), [&](am_NotificationConfiguration_s & stored) { + if (provided.type == stored.type) { + stored = provided; + return true; + } + return false; + } ); + if (found == list.end()) + list.push_back(provided); + } ); + } + + CAmDatabaseObserver *mpDatabaseObserver; //!< pointer to the Observer + ListConnectionFormat mListConnectionFormat; //!< list of connection formats + CAmMappedData mMappedData; //!< Internal structure encapsulating all the maps used in this class +#ifdef UNIT_TEST + public: + void setConnectionIDRange(const int16_t & min, const int16_t & max) + { + mMappedData.mCurrentConnectionID.mMin = min; + mMappedData.mCurrentConnectionID.mMax = max; + } + void setMainConnectionIDRange(const int16_t & min, const int16_t & max) + { + mMappedData.mCurrentMainConnectionID.mMin = min; + mMappedData.mCurrentMainConnectionID.mMax = max; + } + void setSinkIDRange(const int16_t & min, const int16_t & max) + { + mMappedData.mCurrentSinkID.mMin = min; + mMappedData.mCurrentSinkID.mMax = max; + } +#endif +}; + +} + +#endif /* MAPHANDLER_H_ */ diff --git a/AudioManagerCore/include/CAmDatabaseObserver.h b/AudioManagerCore/include/CAmDatabaseObserver.h new file mode 100644 index 0000000..7d18be4 --- /dev/null +++ b/AudioManagerCore/include/CAmDatabaseObserver.h @@ -0,0 +1,87 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2012, BMW AG + * + * This file is part of GENIVI Project AudioManager. + * + * Contributions are licensed to the GENIVI Alliance under one or more + * Contribution License Agreements. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012 + * + * \file CAmDatabaseObserver.h + * For further information see http://www.genivi.org/. + * + */ + +#ifndef DATABASEOBSERVER_H_ +#define DATABASEOBSERVER_H_ + +#include "audiomanagertypes.h" +#include <queue> +#include "CAmSerializer.h" + +namespace am +{ + +class CAmTelnetServer; +class CAmCommandSender; +class CAmRoutingSender; +class CAmSocketHandler; + +/** + * This class observes the Database and notifies other classes about important events, mainly the CommandSender. + */ +class CAmDatabaseObserver +{ +public: + CAmDatabaseObserver(CAmCommandSender *iCommandSender, CAmRoutingSender *iRoutingSender, CAmSocketHandler *iSocketHandler); + CAmDatabaseObserver(CAmCommandSender *iCommandSender, CAmRoutingSender *iRoutingSender, CAmSocketHandler *iSocketHandler, CAmTelnetServer *iTelnetServer); + ~CAmDatabaseObserver(); + void numberOfSinkClassesChanged(); + void numberOfSourceClassesChanged(); + void newSink(const am_Sink_s& sink); + void newSource(const am_Source_s& source); + void newDomain(const am_Domain_s& domain); + void newGateway(const am_Gateway_s& gateway); + void newConverter(const am_Converter_s& coverter); + void newCrossfader(const am_Crossfader_s& crossfader); + void newMainConnection(const am_MainConnectionType_s& mainConnection); + void removedMainConnection(const am_mainConnectionID_t mainConnection); + void removedSink(const am_sinkID_t sinkID, const bool visible); + void removedSource(const am_sourceID_t sourceID, const bool visible); + void removeDomain(const am_domainID_t domainID); + void removeGateway(const am_gatewayID_t gatewayID); + void removeConverter(const am_converterID_t converterID); + void removeCrossfader(const am_crossfaderID_t crossfaderID); + void mainConnectionStateChanged(const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState); + void mainSinkSoundPropertyChanged(const am_sinkID_t sinkID, const am_MainSoundProperty_s& SoundProperty); + void mainSourceSoundPropertyChanged(const am_sourceID_t sourceID, const am_MainSoundProperty_s& SoundProperty); + void sinkAvailabilityChanged(const am_sinkID_t sinkID, const am_Availability_s& availability); + void sourceAvailabilityChanged(const am_sourceID_t sourceID, const am_Availability_s& availability); + void volumeChanged(const am_sinkID_t sinkID, const am_mainVolume_t volume); + void sinkMuteStateChanged(const am_sinkID_t sinkID, const am_MuteState_e muteState); + void systemPropertyChanged(const am_SystemProperty_s& SystemProperty); + void timingInformationChanged(const am_mainConnectionID_t mainConnection, const am_timeSync_t time); + void sinkUpdated(const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible); + void sourceUpdated(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible); + void sinkMainNotificationConfigurationChanged(const am_sinkID_t sinkID, const am_NotificationConfiguration_s mainNotificationConfiguration); + void sourceMainNotificationConfigurationChanged(const am_sourceID_t sourceID, const am_NotificationConfiguration_s mainNotificationConfiguration); + +private: + CAmCommandSender *mCommandSender; //!< pointer to the comandSender + CAmRoutingSender* mRoutingSender; //!< pointer to the routingSender + CAmTelnetServer* mTelnetServer; //!< pointer to the telnetserver + CAmSerializer mSerializer; //!< serializer to handle the CommandInterface via the mainloop +}; + +} + +#endif /* DATABASEOBSERVER_H_ */ diff --git a/AudioManagerCore/include/CAmGraph.h b/AudioManagerCore/include/CAmGraph.h new file mode 100644 index 0000000..ff4a09c --- /dev/null +++ b/AudioManagerCore/include/CAmGraph.h @@ -0,0 +1,630 @@ +/** + * 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 2014 + * + * \file CAmGraph.h + * For further information see http://www.genivi.org/. + * + */ + +#ifndef GRAPH_H +#define GRAPH_H + +#include <functional> +#include <iostream> +#include <vector> +#include <map> +#include <list> +#include <stack> +#include <queue> +#include <algorithm> +#include <limits.h> +#include <iomanip> +#include <cstring> +#include <set> + + +namespace am +{ + /** + * Graph element status. + */ + typedef enum:uint8_t + { + GES_NOT_VISITED, + GES_IN_PROGRESS, + GES_VISITED + }am_GraphElementStatus_e; + + /** + * Callback parameter telling on which position in the path we are. + */ + typedef enum:uint8_t + { + GRAPH_PATH_START, //at the beginning of the path + GRAPH_PATH_MIDDLE, //in middle of the path + GRAPH_PATH_END //at the end of the path + }am_GraphPathPosition_e; + + + /** + * This class is base class for nodes and vertices. + */ + class CAmGraphElement + { + am_GraphElementStatus_e mStatus; //!< item status + public: + CAmGraphElement(): mStatus(GES_NOT_VISITED) { }; + ~CAmGraphElement() { }; + /** + * Setter and getter. + */ + void setStatus(const am_GraphElementStatus_e s) { mStatus = s; }; + am_GraphElementStatus_e getStatus() const { return mStatus; }; + }; + + template <class NodeData> class CAmNode : public CAmGraphElement + { + uint16_t mIndex; //!< uint16_t index used for direct access + NodeData mData; //!< NodeData user data + public: + CAmNode(const NodeData & in):CAmGraphElement(), mIndex(0), mData(in) { }; + CAmNode(const NodeData & in, const uint16_t index):CAmGraphElement(), mIndex(index), mData(in) { }; + ~CAmNode() { }; + /** + * Setters and getters. + */ + NodeData & getData() { return mData; } + uint16_t getIndex() const { return mIndex; } + void setIndex(uint16_t index) { mIndex = index; } + }; + + template <class NodeData, class VertexData> class CAmVertex : public CAmGraphElement + { + CAmNode<NodeData>* mpNode; //!< CAmNode<NodeData>* pointer to a node + VertexData mVertexData; //!< VertexData vertex user data + uint16_t mWeight; //!< uint16_t a positive value used in the shortest path algorithms + public: + CAmVertex(CAmNode<NodeData> *aNode, const VertexData & vertexData, const uint16_t weight):CAmGraphElement(), + mpNode(aNode), mVertexData(vertexData), mWeight(weight) { }; + ~CAmVertex() { }; + /** + * Setters and getters. + */ + CAmNode<NodeData>* getNode() const { return mpNode; } + VertexData & getData() { return mVertexData; } + uint16_t getWeight() const { return mWeight; } + void setWeight(const uint16_t weight) { mWeight=weight; } + }; + + /** + * Class representing a directed or undirected graph. It contains nodes and connections. + * T, V are types for custom user data. + */ + template <class T, class V> class CAmGraph + { + typedef typename std::vector<CAmNode<T>*> CAmListNodePtrs; + typedef typename std::list<CAmVertex<T,V>> CAmListVertices; + typedef typename std::list<CAmVertex<T,V>>::iterator CAmListVerticesItr; + typedef typename std::list<CAmVertex<T,V>>::const_iterator CAmListVerticesItrConst; + typedef typename std::list<CAmListVertices> CAmNodesAdjList; + typedef typename std::list<CAmListVertices>::iterator CAmNodesAdjListItr; + typedef typename std::list<CAmListVertices>::const_iterator CAmNodesAdjListItrConst; + typedef typename std::list<CAmNode<T>> CAmListNodes; + typedef typename std::list<CAmNode<T>>::iterator CAmListNodesItr; + typedef typename std::list<CAmNode<T>>::const_iterator CAmListNodesItrConst; + typedef typename std::vector<CAmNode<T>*> CAmNodeReferenceList; + typedef typename std::vector<CAmListVertices*> CAmVertexReferenceList; + + CAmListNodes mStoreNodes; //!< CAmListNodes list with all nodes + CAmNodesAdjList mStoreAdjList; //!< CAmNodesAdjList adjacency list + CAmNodeReferenceList mPointersNodes; //!< CAmNodeReferenceList vector with pointers to nodes for direct access + CAmVertexReferenceList mPointersAdjList; //!< CAmVertexReferenceList vector with pointers to vertices for direct access + bool mIsCyclic; //!< bool the graph has cycles or not + + /** + * Updates the node indexes after adding or removing nodes. + * + * @param fromIndex updates all nodes from given index. + */ + void updateIndexes(const int16_t fromIndex) + { + if( fromIndex<mPointersNodes.size() ) + { + for(auto iter = mPointersNodes.begin()+fromIndex; iter!=mPointersNodes.end(); iter++) + (*iter)->setIndex(iter-mPointersNodes.begin()); + } + } + + + /** + * Finds the shortest path and the minimal weights from given node. + * + * @param node start node. + * @param minDistance vector with all result distances. + * @param previous vector with previous nodes. + */ + + typedef uint16_t vertex_t; + typedef uint16_t weight_t; + + void findShortestsPathsFromNode(const CAmNode<T> & node, std::vector<weight_t> &minDistance, std::vector<CAmNode<T> *> &previous) + { + typename CAmListVertices::const_iterator nIter; + CAmListVertices * neighbors; + weight_t dist, weight, v, distanceThroughU; + CAmNode<T>* pU; + CAmVertex<T,V> * pVertex; + CAmNode<T> *pDstNode; + + size_t n = mPointersAdjList.size(); + std::set<std::pair<weight_t, CAmNode<T>*> > vertexQueue; + + minDistance.clear(); + minDistance.resize(n, std::numeric_limits<weight_t>::max()); + minDistance[node.getIndex()] = 0; + previous.clear(); + previous.resize(n, NULL); + + vertexQueue.insert(std::make_pair(minDistance[node.getIndex()], (CAmNode<T>*)&node)); + + while (!vertexQueue.empty()) + { + dist = vertexQueue.begin()->first; + pU = vertexQueue.begin()->second; + vertexQueue.erase(vertexQueue.begin()); + //todo: terminate the search at this position if you want the path to a target node ( if(pU==target)break; ) + + // Visit each edge exiting u + neighbors = mPointersAdjList[pU->getIndex()]; + nIter = neighbors->begin(); + for (; nIter != neighbors->end(); nIter++) + { + pVertex = (CAmVertex<T,V> *)&(*nIter); + pDstNode = pVertex->getNode(); + + v = pDstNode->getIndex(); + weight = pVertex->getWeight(); + distanceThroughU = dist + weight; + if (distanceThroughU < minDistance[pDstNode->getIndex()]) + { + vertexQueue.erase(std::make_pair(minDistance[v], pDstNode)); + minDistance[v] = distanceThroughU; + previous[v] = pU; + vertexQueue.insert(std::make_pair(minDistance[v], pDstNode)); + } + } + } + } + + /** + * Constructs a path to given node after findShortestsPathsFromNode has been called. + * + * @param node end node. + * @param previous vector with previous nodes. + * @param result result path. + */ + void constructShortestPathTo(const CAmNode<T> & node, const std::vector<CAmNode<T> *> &previous, CAmListNodePtrs & result) + { + CAmNode<T> * vertex = (CAmNode<T> *)&node; + + int i=0; + while ( (vertex = previous[vertex->getIndex()])!=NULL ) + { + result.insert(result.begin(), vertex); + i++; + } + if(i) + result.push_back((CAmNode<T> *)&node); + } + + /** + * Calls a function with every node from this path after findShortestsPathsFromNode has been called. + * The construction of the path is delegated to the caller. + * + * @param node end node. + * @param previous vector with previous nodes. + * @param cb callback which is mostly used for constructing. + */ + void constructShortestPathTo(const CAmNode<T> & node, const std::vector<CAmNode<T> *> &previous, std::function<void(const am_GraphPathPosition_e pos, CAmNode<T> &)> cb) + { + CAmNode<T> * vertex = (CAmNode<T> *)&node; + CAmNode<T> * prev = vertex; + int i=0; + while ( (vertex = previous[vertex->getIndex()])!=NULL ) + { + cb(i==0?GRAPH_PATH_START:GRAPH_PATH_MIDDLE, *prev); + prev = vertex; + i++; + } + if(i) + cb(GRAPH_PATH_END, *prev); + } + + /** + * Generates list with all possible paths to given destination node after findShortestsPathsFromNode has been called. + * Finding paths is observed through the callback. The caller is informed after a new path has been found. + * + * @param dst end node. + * @param visited vector with current path. + * @param cb callback which is mostly used for constructing. + */ + void goThroughAllPaths(const CAmNode<T> & dst, std::vector<CAmNode<T>*> & visited, std::function<void(const CAmNodeReferenceList & path)> cb) + { + CAmListVertices * nodes = mPointersAdjList[visited.back()->getIndex()]; + CAmListVerticesItrConst vItr(nodes->begin()); + for (; vItr != nodes->end(); ++vItr) + { + const CAmVertex<T,V> & vertex = (*vItr); + if(vertex.getNode()->getStatus()!=GES_NOT_VISITED) + continue; + if (vertex.getNode()==&dst) + { + vertex.getNode()->setStatus(GES_IN_PROGRESS); + visited.push_back(vertex.getNode()); + //notify observer + cb(visited); + //remove last node from the list + auto last = visited.end()-1; + visited.erase(last); + vertex.getNode()->setStatus(GES_NOT_VISITED); + break; + } + } + vItr = nodes->begin(); + //bfs like loop + for (; vItr != nodes->end(); ++vItr) + { + const CAmVertex<T,V> & vertex = (*vItr); + if(vertex.getNode()->getStatus()!=GES_NOT_VISITED||vertex.getNode()==&dst) + continue; + vertex.getNode()->setStatus(GES_IN_PROGRESS); + visited.push_back(vertex.getNode()); + goThroughAllPaths(dst, visited, cb); + //remove last node from the list + auto last = visited.end()-1; + visited.erase(last); + vertex.getNode()->setStatus(GES_NOT_VISITED); + } + } + + public: + explicit CAmGraph(const std::vector<T> &v):mStoreNodes(), mStoreAdjList(), mPointersNodes(), mPointersAdjList() + { + typedef typename std::vector<T>::const_iterator inItr; + inItr itr(v.begin()); + + for (; itr != v.end(); ++itr) + { + addNode(*itr); + } + + mIsCyclic = false; + }; + CAmGraph():mStoreNodes(), mStoreAdjList(), mPointersNodes(), mPointersAdjList(), mIsCyclic(false){}; + ~CAmGraph(){} + + const CAmListNodes & getNodes() const + { + return mStoreNodes; + } + + const CAmVertexReferenceList & getVertexList() const + { + return mPointersAdjList; + } + + /** + * Returns pointer to a node which data is equal to the given. + * @return pointer to a node or NULL. + */ + const CAmNode<T>* findNode(const T & in) + { + typename CAmNodeReferenceList::const_iterator itr (mPointersNodes.begin()); + + for (; itr != mPointersNodes.end(); ++itr) + { + if ((*itr)->getData() == in) { + return (*itr); + } + } + return NULL; + } + + /** + * Returns pointer to a vertex which two ends are equal to the given nodes. + * @return pointer to a vertex or NULL. + */ + const CAmVertex<T,V>* findVertex(const CAmNode<T> & edge1, const CAmNode<T> & edge2) const + { + const CAmNode<T> * pEdge2 = (CAmNode<T> *)&edge2; + const CAmListVertices * list = mPointersAdjList[edge1.getIndex()]; + CAmListVerticesItrConst result = std::find_if(list->begin(), list->end(), [&](const CAmVertex<T,V> & refObject){ + return refObject.getNode()==pEdge2; + }); + if(result!=list->end()) + return (CAmVertex<T,V>*)&(*result); + + return NULL; + } + + bool hasCycles() const + { + return mIsCyclic; + } + + + /** + * Adds a new node to the graph with given user data. + * @return reference to the newly inserted node. + */ + CAmNode<T> & addNode(const T & in) + { + size_t index = mStoreNodes.size(); + mStoreNodes.emplace_back(in, index); + mStoreAdjList.emplace_back(); + mPointersNodes.push_back(&mStoreNodes.back()); + mPointersAdjList.push_back(&mStoreAdjList.back()); + return mStoreNodes.back(); + } + + /** + * Removes a vertex with two ends equal to the given nodes . + */ + void removeVertex(const CAmNode<T> & edge1, const CAmNode<T> & edge2) + { + const CAmListVertices * list = mPointersAdjList[edge1.getIndex()]; + CAmListVerticesItr iter = std::find_if(list->begin(), list->end(), [&edge2](const CAmVertex<T,V> & refVertex){ + return (refVertex.getNode()==&edge2); + }); + if(iter!=list->end()) + list->erase(iter); + } + + /** + * Removes all vertices to given node . + */ + void removeAllVerticesToNode(const CAmNode<T> & node) + { + auto comparator = [&node](const CAmVertex<T,V> & refVertex){ + return (refVertex.getNode()==&node); + }; + auto itr = mPointersAdjList.begin(); + for(;itr!=mPointersAdjList.end();itr++) + { + CAmListVertices * vertices = *itr; + auto iterVert = std::find_if(vertices->begin(), vertices->end(), comparator); + if(iterVert!=vertices->end()) + vertices->erase(iterVert); + } + } + + /** + * Removes a node with given user data . + */ + void removeNode(const T & in) + { + CAmNode<T> * node = findNode(in); + if(node!=NULL) + removeNode(*node); + } + + /** + * Removes the given node from the graph . + */ + void removeNode(const CAmNode<T> & node) + { + uint16_t index = node.getIndex(); + removeAllVerticesToNode(node); + mPointersAdjList.erase(mPointersAdjList.begin()+index); + mPointersNodes.erase(mPointersNodes.begin()+index); + auto iter = std::find_if(mStoreNodes.begin(), mStoreNodes.end(), [&node](const CAmNode<T> & otherNode){ + return &otherNode==&node; + }); + if(iter!=mStoreNodes.end()) + mStoreNodes.erase(iter); + updateIndexes(index); + } + + /** + * Connect first with last node and set user data and weight to the vertex. + */ + void connectNodes(const CAmNode<T> & first, const CAmNode<T> & last, const V & vertexData, const int16_t weight = 1) + { + CAmListVertices * list = mPointersAdjList[first.getIndex()]; + CAmNode<T> * node = mPointersNodes[last.getIndex()]; + list->emplace_back(node, vertexData, weight); + } + + /** + * Exists any vertex with two given ends. + * @return TRUE on successfully changed ID. + */ + bool isAnyVertex(const CAmNode<T> & edge1, const CAmNode<T> & edge2) const + { + return findVertex(edge1, edge2)!=NULL; + } + + /** + * Sets the status of all nodes and vertices to GES_NOT_VISITED. + */ + void reset() + { + // set all nodes to GES_NOT_VISITED + std::for_each(mPointersNodes.begin(), mPointersNodes.end(), [](CAmNode<T> * refNode){ + if(refNode->getStatus()!= GES_NOT_VISITED) + refNode->setStatus(GES_NOT_VISITED); + }); + // set all vertices to GES_NOT_VISITED + auto action = [](CAmVertex<T,V> & refVertex){ + if(refVertex.getStatus()!= GES_NOT_VISITED) + refVertex.setStatus(GES_NOT_VISITED); + }; + auto itr1(mPointersAdjList.begin()); + for (; itr1 != mPointersAdjList.end(); ++itr1) + { + CAmListVertices * vertices = *itr1; + std::for_each(vertices->begin(), vertices->end(), action); + } + } + + /** + * Clears all nodes and vertices. + */ + void clear() + { + mStoreNodes.clear(); + mStoreAdjList.clear(); + mPointersAdjList.clear(); + mPointersNodes.clear(); + mPointersAdjList.clear(); + } + + /** + * Goes through all nodes and vertices and calls the callback. + */ + void trace(std::function<void(const CAmNode<T> &, const std::vector<CAmVertex<T,V>*> &)> cb) + { + std::for_each(mPointersNodes.begin(), mPointersNodes.end(), [&](CAmNode<T> * refNode){ + CAmListVertices * vertices = this->mPointersAdjList[refNode->getIndex()]; + std::vector<CAmVertex<T,V>*> list; + std::for_each(vertices->begin(), vertices->end(), [&list](CAmVertex<T,V> & refVertex){ + list.push_back(&refVertex); + }); + cb(*refNode, list); + }); + } + + /** + * Finds the shortest path from given node to all nodes in listTargets. + * + * @param source start node. + * @param listTargets destination nodes. + * @param resultPath list with all shortest paths. + */ + void getShortestPath(const CAmNode<T> & source, const CAmListNodePtrs & listTargets, std::vector<CAmListNodePtrs> & resultPath ) + { + const size_t numberOfNodes = mPointersNodes.size(); + if(numberOfNodes==0) + return; + + std::vector<weight_t> min_distance; + std::vector<CAmNode<T>*> previous; + findShortestsPathsFromNode(source, min_distance, previous); + + for(auto it=listTargets.begin(); it!=listTargets.end(); it++) + { + CAmNode<T> *node = *it; + resultPath.emplace_back(); + CAmListNodePtrs & path = resultPath.back(); + constructShortestPathTo(*node, previous, path); + if(path.empty()) + { + typename std::vector<CAmListNodePtrs>::iterator iter = resultPath.end(); + resultPath.erase(--iter); + } + } + } + + /** + * Finds the shortest path between two nodes. + * + * @param source start node. + * @param destination destination node. + * @param resultPath list with the found shortest paths. + */ + void getShortestPath(const CAmNode<T> & source, const CAmNode<T> & destination, CAmListNodePtrs & resultPath ) + { + const size_t numberOfNodes = mPointersNodes.size(); + if(numberOfNodes==0) + return; + std::vector<weight_t> min_distance; + std::vector<CAmNode<T>*> previous; + findShortestsPathsFromNode(source, min_distance, previous); + constructShortestPathTo(destination, previous, resultPath); + } + + /** + * Finds the shortest path from given node to all nodes in listTargets. + * Delegates the construction of the path to the caller. + * + * @param source start node. + * @param listTargets destination nodes. + * @param cb callabck. + */ + void getShortestPath(const CAmNode<T> & source, + const CAmListNodePtrs & listTargets, + std::function<void(const am_GraphPathPosition_e, CAmNode<T> &)> cb ) + { + const size_t numberOfNodes = mPointersNodes.size(); + if(numberOfNodes==0) + return; + + std::vector<weight_t> min_distance; + std::vector<CAmNode<T>*> previous; + findShortestsPathsFromNode(source, min_distance, previous); + + for(auto it=listTargets.begin(); it!=listTargets.end(); it++) + { + CAmNode<T>* node = *it; + constructShortestPathTo(*node, previous, cb); + } + } + + /** + * Finds the shortest path between two given nodes. + * Delegates the construction of the path to the caller. + * + * @param source start node. + * @param destination destination node. + * @param cb callabck. + */ + void getShortestPath(const CAmNode<T> & source, + const CAmNode<T> & destination, + std::function<void(const am_GraphPathPosition_e, CAmNode<T> &)> cb ) + { + const size_t numberOfNodes = mPointersNodes.size(); + if(numberOfNodes==0) + return; + + std::vector<weight_t> min_distance; + std::vector<CAmNode<T>*> previous; + findShortestsPathsFromNode(source, min_distance, previous); + constructShortestPathTo(destination, previous, cb); + } + + /** + * Finds all possible paths between two given nodes. + * Delegates the construction of the path to the caller. + * + * @param src start node. + * @param dst destination node. + * @param cb callabck. + */ + void getAllPaths(const CAmNode<T> & src, const CAmNode<T> & dst, std::function<void(const CAmNodeReferenceList & path)> cb) + { + CAmNodeReferenceList visited; + visited.push_back((CAmNode<T>*)&src); + ((CAmNode<T>*)&src)->setStatus(GES_VISITED); + goThroughAllPaths(dst, visited, cb); + reset(); + } + }; + +} + +#endif diff --git a/AudioManagerCore/include/CAmLog.h b/AudioManagerCore/include/CAmLog.h new file mode 100644 index 0000000..35c6a41 --- /dev/null +++ b/AudioManagerCore/include/CAmLog.h @@ -0,0 +1,129 @@ +/** + * 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.h + * For further information see http://www.genivi.org/. + * + */ + +#ifndef CAMLOG_H_ +#define CAMLOG_H_ + +#include <iostream> +#include <iosfwd> +#include <stdio.h> +#include <stdexcept> +#include <fstream> +#include <stdlib.h> +#include <sstream> +#include <assert.h> + +/** + * Implements a basic logging mechanism that can be used to print debug information into a file or to the console. + * It can be used either as singleton through the appropriate method getDefaultLog() or as independent instantiated object. + * The default initializer sets the console as output for newly created objects. + * Example: CAmLogger << "Text"; //to print out through the singleton object directly to the console + */ + +#define DEFAULT_LOG_FOLDER "/tmp/" +#define DEFAULT_LOGFILE_PREFIX "am_dump_" +#define DEFAULT_LOGFILE_EXT ".log" + +#define DEL( aPointer ) delete aPointer, aPointer = NULL; + +/* */ +typedef enum { eCAmLogNone = 0, eCAmLogStdout = 1, eCAmLogFile = 2 } eCAmLogType; + +class CAmLog +{ +private: + /** + * Private classes which usually own (wrap) a stream object. They are responsible for creating and deleting it. + */ + class CAmLogger + { + protected: + std::ostream* mOutputStream; + public: + CAmLogger ():mOutputStream(NULL) {}; + virtual ~CAmLogger () { }; + virtual void log(const std::string& _s) + { + (*mOutputStream) << _s; + mOutputStream->flush(); + } + template <class T> + CAmLogger & operator << (const T & t) + { + (*mOutputStream) << t; + return (*this); + } + }; + + class CAmFileLogger : public CAmLogger + { + std::string mFilename; + public: + static void generateLogFilename(std::string &result); + explicit CAmFileLogger(const std::string& _s) : CAmLogger() + { + mFilename = _s; + mOutputStream = new std::ofstream(mFilename.c_str()); + } + ~CAmFileLogger(); + }; + + class CAmStdOutLogger : public CAmLogger + { + public: + CAmStdOutLogger() + { + mOutputStream = &std::cout; + } + }; + +private: + eCAmLogType mLogType; + CAmLogger* mLogger; + +protected: + void releaseLogger(); + void instantiateLogger( const eCAmLogType type); +public: + CAmLog(const eCAmLogType type ); + CAmLog(); + ~CAmLog(); + + static CAmLog *getDefaultLog(); + + void setLogType( const eCAmLogType type); + eCAmLogType getLogType() const; + + template <class T> + CAmLog & operator << (const T & t) + { + assert(mLogger!=NULL); + (*mLogger) << t; + return (*this); + } + }; + +#define CAmLogger (*CAmLog::getDefaultLog()) + + +#endif /* CAMLOG_H_ */ diff --git a/AudioManagerCore/include/CAmRouter.h b/AudioManagerCore/include/CAmRouter.h new file mode 100644 index 0000000..fe41049 --- /dev/null +++ b/AudioManagerCore/include/CAmRouter.h @@ -0,0 +1,317 @@ +/** + * 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.h + * For further information see http://www.genivi.org/. + * + */ + +#ifndef ROUTER_H_ +#define ROUTER_H_ + +#include <assert.h> +#include <vector> +#include <functional> +#include "audiomanagertypes.h" +#include "CAmGraph.h" +#include "IAmDatabaseHandler.h" + + +namespace am +{ +/** + * Optimal path search between a source and a sink is implemented with a graph which contains nodes - sinks, sources, gateways, converters. + * The nodes are identified by sinkID, sourceID, gatewayID, converterID. + * A possible connection between two nodes represents the facts that the nodes can be connected with one or more connectionFormats (Node[id=1] ---> Node[id=2]). + * It is assumption that the two nodes can be connected. The controller itself decides later whether the connection is possible or not. + * + */ + +/** + * Trace on/off. + */ +#if !defined(ROUTING_BUILD_CONNECTIONS) + #undef TRACE_GRAPH +#endif + +/** + * Default behavior is to do the search in one step without connections, which are identified during the search. + * Alternatively the search can be done in two steps. + */ +#if !defined(ROUTING_BUILD_CONNECTIONS) + #undef ROUTING_BUILD_CONNECTIONS +#endif + +#if defined(TRACE_GRAPH) +#if !defined(ROUTING_BUILD_CONNECTIONS) +#warning "You should define ROUTING_BUILD_CONNECTIONS in order to be able to see the connections in the trace." +#endif +#endif + +class CAmRouter; + +/** + * A structure used as user data in the graph nodes. + */ +struct am_RoutingNodeData_s +{ + typedef enum:uint8_t {SINK, SOURCE, GATEWAY, CONVERTER} am_NodeDataType_e; + am_NodeDataType_e type; //!< data type:sink, source, gateway or converter + union + { + am_Source_s *source; + am_Sink_s *sink; + am_Gateway_s *gateway; + am_Converter_s *converter; + } data; //!< union pointer to sink, source, gateway or converter + + am_RoutingNodeData_s():type(SINK) + {} + + bool operator==(const am_RoutingNodeData_s & anotherObject) const + { + bool result = false; + if(type==anotherObject.type) + { + result = true; + if(type==SINK) + result &= (data.sink->sinkID==anotherObject.data.sink->sinkID); + else if(type==SOURCE) + result &= (data.source->sourceID==anotherObject.data.source->sourceID); + else if(type==GATEWAY) + result &= (data.gateway->gatewayID==anotherObject.data.gateway->gatewayID); + else if(type==CONVERTER) + result &= (data.converter->converterID==anotherObject.data.converter->converterID); + } + return result; + }; + +#ifdef TRACE_GRAPH + void trace() const + { + if(type==SINK) + std::cout << "[SINK:" << data.sink->sinkID << ":" << data.sink->name << "(" << data.sink->domainID << ")" + << "]"; + else if(type==SOURCE) + std::cout << "[SOUR:" << data.source->sourceID << ":" << data.source->name << "(" << data.source->domainID << ")" + << "]"; + else if(type==GATEWAY) + std::cout << "[GATE:" << data.gateway->gatewayID << ":" << data.gateway->name << "(" << data.gateway->controlDomainID << ")" + << "]"; + else if(type==CONVERTER) + std::cout << "[CONV:" << data.converter->converterID << ":" << data.converter->name << "(" << data.converter->domainID << ")" + << "]"; + }; +#endif + + am_domainID_t domainID() const + { + if(type==SINK) + return data.sink->domainID; + else if(type==SOURCE) + return data.source->domainID; + else if(type==GATEWAY) + return data.gateway->controlDomainID; + else if(type==CONVERTER) + return data.converter->domainID; + return 0; + }; +}; + +typedef am_RoutingNodeData_s::am_NodeDataType_e CAmNodeDataType; +typedef CAmNode<am_RoutingNodeData_s> CAmRoutingNode; +typedef CAmGraph<am_RoutingNodeData_s, uint16_t> CAmRoutingGraph; +typedef CAmVertex<am_RoutingNodeData_s, uint16_t> CAmRoutingVertex; +typedef std::list<CAmRoutingVertex> CAmRoutingListVertices; +typedef std::vector<CAmRoutingListVertices*> CAmRoutingVertexReferenceList; + +class CAmControlSender; + + +/** + * Implements an autorouting algorithm for connecting sinks and sources via different audio domains. + */ +class CAmRouter +{ + IAmDatabaseHandler* mpDatabaseHandler; //!< pointer to database handler + CAmControlSender* mpControlSender; //!< pointer the controlsender - is used to retrieve information for the optimal route + bool mOnlyFreeConversionNodes; //!< bool flag whether only disconnected elements should be considered or not + CAmRoutingGraph mRoutingGraph; //!< graph object + std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListSources; //!< map with pointers to nodes with sources, used for quick access + std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListSinks; //!< map with pointers to nodes with sinks, used for quick access + std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListGateways; //!< map with pointers to nodes with gateways, used for quick access + std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListConverters;//!< map with pointers to nodes with converters, used for quick access + + am_Error_e determineConnectionFormatsForPath(am_Route_s & routeObjects, std::vector<CAmRoutingNode*> & nodes); + am_Error_e doConnectionFormatsForPath(am_Route_s & routeObjects, + std::vector<CAmRoutingNode*> & route, + std::vector<am_RoutingElement_s>::iterator routingElementIterator, + std::vector<CAmRoutingNode*>::iterator routeIterator); + + + /** + * Check whether given converter or gateway has been connected. + * + * @param comp converter or gateway . + */ + template <class Component> bool isComponentConnected(const Component & comp) + { + return mpDatabaseHandler->isComponentConnected(comp); + } + void generateAllPaths(const CAmRoutingNode & src, + const CAmRoutingNode & dst, + const bool includeCycles, + std::function<void(const std::vector<CAmRoutingNode*> & path)> cb); + void goThroughAllPaths(const CAmRoutingNode & dst, + std::vector<CAmRoutingNode*> & visited, + std::vector<am_domainID_t> & visitedDomains, + std::function<void(const std::vector<CAmRoutingNode*> & path)> cb); + +#ifdef ROUTING_BUILD_CONNECTIONS + /** + * Connects all converters to its sink and sources if possible. + * + */ + void constructConverterConnections(); + + /** + * Connects all gateways to its sink and sources if possible. + * + */ + void constructGatewayConnections(); + + /** + * Connects all sources to the sinks if possible. + * + */ + void constructSourceSinkConnections(); +#else + /** + * Construct a list with all vertices + */ + void getVerticesForNode(const CAmRoutingNode & node, CAmRoutingListVertices & list); + + /** + * Construct a list with all vertices from given source. + */ + void getVerticesForSource(const CAmRoutingNode & node, CAmRoutingListVertices & list); + + /** + * Construct a list with all vertices from given sink. + */ + void getVerticesForSink(const CAmRoutingNode & node, CAmRoutingListVertices & list); + + /** + * Construct a list with all vertices from given converter. + */ + void getVerticesForConverter(const CAmRoutingNode & node, CAmRoutingListVertices & list); + + /** + * Construct a list with all vertices from given gateway. + */ + void getVerticesForGateway(const CAmRoutingNode & node, CAmRoutingListVertices & list); +#endif + +public: + CAmRouter(IAmDatabaseHandler* iDatabaseHandler, CAmControlSender* iSender); + ~CAmRouter(); + + /** + * Finds all possible paths between given source and sink. + * + * @param onlyfree only disconnected elements should be included or not. + * @param sourceID starting point. + * @param sinkID ending point. + * @param returnList list with all possible paths + * @return E_OK on success(0 or more paths) or E_NOT_POSSIBLE on failure. + */ + am_Error_e getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s>& returnList); + am_Error_e getRoute(const bool onlyfree, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes); + + am_Error_e getAllPaths(CAmRoutingNode & aSource, CAmRoutingNode & aSink, + std::vector<am_Route_s> & resultPath, std::vector<std::vector<CAmRoutingNode*>> & resultNodesPath, +#if !defined(ROUTING_BUILD_CONNECTIONS) + __attribute__((unused)) +#endif + const bool includeCycles = false); +#ifdef ROUTING_BUILD_CONNECTIONS + void getShortestPath(const CAmRoutingNode & source, const CAmRoutingNode & destination, std::vector<CAmRoutingNode*> & resultPath); + void getShortestPath(CAmRoutingNode & aSource, CAmRoutingNode & aSink, am_Route_s & resultPath, std::vector<CAmRoutingNode*> & resultNodesPath); +#endif + + static bool getAllowedFormatsFromConvMatrix( const std::vector<bool> & convertionMatrix, + const std::vector<am_CustomConnectionFormat_t> & listSourceFormats, + const std::vector<am_CustomConnectionFormat_t> & listSinkFormats, + std::vector<am_CustomConnectionFormat_t> & sourceFormats, + std::vector<am_CustomConnectionFormat_t> & sinkFormats); + static void listPossibleConnectionFormats(std::vector<am_CustomConnectionFormat_t> & inListSourceFormats, + std::vector<am_CustomConnectionFormat_t> & inListSinkFormats, + std::vector<am_CustomConnectionFormat_t> & outListFormats); + static bool getRestrictedOutputFormats(const std::vector<bool> & convertionMatrix, + const std::vector<am_CustomConnectionFormat_t> & listSourceFormats, + const std::vector<am_CustomConnectionFormat_t> & listSinkFormats, + const am_CustomConnectionFormat_t connectionFormat, + std::vector<am_CustomConnectionFormat_t> & listFormats); + static void getSourceSinkPossibleConnectionFormats(std::vector<CAmRoutingNode*>::iterator iteratorSource, + std::vector<CAmRoutingNode*>::iterator iteratorSink, + std::vector<am_CustomConnectionFormat_t> & outConnectionFormats); + + static bool shouldGoInDomain(const std::vector<am_domainID_t> & visitedDomains, const am_domainID_t nodeDomainID); + + /** + * Returns a sink node with given sinkID. + * + * @param sinkID sink id. + * @return pointer to node or NULL. + */ + CAmRoutingNode* sinkNodeWithID(const am_sinkID_t sinkID); + CAmRoutingNode* sinkNodeWithID(const am_sinkID_t sinkID, const am_domainID_t domainID); + + /** + * Returns a source node with given sourceID. + * + * @param sourceID source id. + * @return pointer to node or NULL. + */ + CAmRoutingNode* sourceNodeWithID(const am_sourceID_t sourceID); + CAmRoutingNode* sourceNodeWithID(const am_sourceID_t sourceID, const am_domainID_t domainID); + + /** + * Returns a converter node for given sinkID. + * + * @param sinkID sink id. + * @param domainID domain id. + * @return pointer to node or NULL. + */ + CAmRoutingNode* converterNodeWithSinkID(const am_sinkID_t sinkID, const am_domainID_t domainID); + + /** + * Returns a gateway node for given sinkID. + * + * @param sinkID sink id. + * @return pointer to node or NULL. + */ + CAmRoutingNode* gatewayNodeWithSinkID(const am_sinkID_t sinkID); + + void load(const bool onlyFree); + void clear(); +}; +} /* namespace am */ +#endif /* ROUTER_H_ */ + diff --git a/AudioManagerCore/include/CAmRoutingReceiver.h b/AudioManagerCore/include/CAmRoutingReceiver.h new file mode 100644 index 0000000..82626c6 --- /dev/null +++ b/AudioManagerCore/include/CAmRoutingReceiver.h @@ -0,0 +1,127 @@ +/** + * 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.h + * For further information see http://www.genivi.org/. + * + */ + +#ifndef ROUTINGRECEIVER_H_ +#define ROUTINGRECEIVER_H_ + +#include "IAmRouting.h" + +namespace am +{ + +class CAmSocketHandler; +class CAmDbusWrapper; +class IAmDatabaseHandler; +class CAmRoutingSender; +class CAmControlSender; + +/** + * Implements the Receiving side of the RoutingPlugins. + */ +class CAmRoutingReceiver: public IAmRoutingReceive +{ +public: + CAmRoutingReceiver(IAmDatabaseHandler *iDatabaseHandler, CAmRoutingSender *iRoutingSender, CAmControlSender *iControlSender, CAmSocketHandler *iSocketHandler); + CAmRoutingReceiver(IAmDatabaseHandler *iDatabaseHandler, CAmRoutingSender *iRoutingSender, CAmControlSender *iControlSender, CAmSocketHandler *iSocketHandler, CAmDbusWrapper *iDBusWrapper); + ~CAmRoutingReceiver(); + void ackConnect(const am_Handle_s handle, const am_connectionID_t connectionID, const am_Error_e error); + void ackDisconnect(const am_Handle_s handle, const am_connectionID_t connectionID, const am_Error_e error); + void ackSetSinkVolumeChange(const am_Handle_s handle, const am_volume_t volume, const am_Error_e error); + void ackSetSourceVolumeChange(const am_Handle_s handle, const am_volume_t volume, const am_Error_e error); + void ackSetSourceState(const am_Handle_s handle, const am_Error_e error); + void ackSetSinkSoundProperties(const am_Handle_s handle, const am_Error_e error); + void ackSetSinkSoundProperty(const am_Handle_s handle, const am_Error_e error); + void ackSetSourceSoundProperties(const am_Handle_s handle, const am_Error_e error); + void ackSetSourceSoundProperty(const am_Handle_s handle, const am_Error_e error); + void ackCrossFading(const am_Handle_s handle, const am_HotSink_e hotSink, const am_Error_e error); + void ackSourceVolumeTick(const am_Handle_s handle, const am_sourceID_t sourceID, const am_volume_t volume); + void ackSinkVolumeTick(const am_Handle_s handle, const am_sinkID_t sinkID, const am_volume_t volume); + am_Error_e peekDomain(const std::string& name, am_domainID_t& domainID); + am_Error_e registerDomain(const am_Domain_s& domainData, am_domainID_t& domainID); + am_Error_e deregisterDomain(const am_domainID_t domainID); + am_Error_e registerGateway(const am_Gateway_s& gatewayData, am_gatewayID_t& gatewayID); + am_Error_e registerConverter(const am_Converter_s& converterData, am_converterID_t& converterID); + am_Error_e deregisterGateway(const am_gatewayID_t gatewayID); + am_Error_e deregisterConverter(const am_converterID_t converterID); + am_Error_e peekSink(const std::string& name, am_sinkID_t& sinkID); + am_Error_e registerSink(const am_Sink_s& sinkData, am_sinkID_t& sinkID); + am_Error_e deregisterSink(const am_sinkID_t sinkID); + am_Error_e peekSource(const std::string& name, am_sourceID_t& sourceID); + am_Error_e registerSource(const am_Source_s& sourceData, am_sourceID_t& sourceID); + am_Error_e deregisterSource(const am_sourceID_t sourceID); + am_Error_e registerCrossfader(const am_Crossfader_s& crossfaderData, am_crossfaderID_t& crossfaderID); + am_Error_e deregisterCrossfader(const am_crossfaderID_t crossfaderID); + am_Error_e peekSourceClassID(const std::string& name, am_sourceClass_t& sourceClassID); + am_Error_e peekSinkClassID(const std::string& name, am_sinkClass_t& sinkClassID); + void hookInterruptStatusChange(const am_sourceID_t sourceID, const am_InterruptState_e interruptState); + void hookDomainRegistrationComplete(const am_domainID_t domainID); + void hookSinkAvailablityStatusChange(const am_sinkID_t sinkID, const am_Availability_s& availability); + void hookSourceAvailablityStatusChange(const am_sourceID_t sourceID, const am_Availability_s& availability); + void hookDomainStateChange(const am_domainID_t domainID, const am_DomainState_e domainState); + void hookTimingInformationChanged(const am_connectionID_t connectionID, const am_timeSync_t delay); + void sendChangedData(const std::vector<am_EarlyData_s>& earlyData); + am_Error_e getDBusConnectionWrapper(CAmDbusWrapper*& dbusConnectionWrapper) const; + am_Error_e getSocketHandler(CAmSocketHandler*& socketHandler) const; + void getInterfaceVersion(std::string& version) const; + void confirmRoutingReady(const uint16_t handle, const am_Error_e error); + void confirmRoutingRundown(const uint16_t handle, const am_Error_e error); + am_Error_e 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) ; + am_Error_e 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); + am_Error_e 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) ; + am_Error_e 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) ; + void ackSetVolumes(const am_Handle_s handle, const std::vector<am_Volumes_s>& listvolumes, const am_Error_e error) ; + void ackSinkNotificationConfiguration(const am_Handle_s handle, const am_Error_e error) ; + void ackSourceNotificationConfiguration(const am_Handle_s handle, const am_Error_e error) ; + void hookSinkNotificationDataChange(const am_sinkID_t sinkID, const am_NotificationPayload_s& payload) ; + void hookSourceNotificationDataChange(const am_sourceID_t sourceID, const am_NotificationPayload_s& payload) ; + am_Error_e getDomainOfSink(const am_sinkID_t sinkID, am_domainID_t& domainID) const; + am_Error_e getDomainOfSource(const am_sourceID_t sourceID, am_domainID_t& domainID) const; + am_Error_e getDomainOfCrossfader(const am_crossfaderID_t crossfader, am_domainID_t& domainID) const; + + uint16_t getStartupHandle(); //!< returns a startup handle + uint16_t getRundownHandle(); //!< returns a rundown handle + + void waitOnStartup(bool startup); //!< tells the RoutingReceiver to start waiting for all handles to be confirmed + void waitOnRundown(bool rundown); //!< tells the RoutingReceiver to start waiting for all handles to be confirmed + +private: + IAmDatabaseHandler *mpDatabaseHandler; //!< pointer to the databaseHandler + CAmRoutingSender *mpRoutingSender; //!< pointer to the routingSender + CAmControlSender *mpControlSender; //!< pointer to the controlSender + CAmSocketHandler *mpSocketHandler; //!< pointer to sockethandler + CAmDbusWrapper *mpDBusWrapper; //!< pointer to dbuswrapper + + std::vector<uint16_t> mListStartupHandles; //!< list of handles that wait for a confirm + std::vector<uint16_t> mListRundownHandles; //!< list of handles that wait for a confirm + uint16_t handleCount; //!< counts all handles + bool mWaitStartup; //!< if true confirmation will be sent if list of handles = 0 + bool mWaitRundown; //!< if true confirmation will be sent if list of handles = 0 + + am_Error_e mLastStartupError; + am_Error_e mLastRundownError; + +}; + +} + +#endif /* ROUTINGRECEIVER_H_ */ diff --git a/AudioManagerCore/include/CAmRoutingSender.h b/AudioManagerCore/include/CAmRoutingSender.h new file mode 100644 index 0000000..4a23428 --- /dev/null +++ b/AudioManagerCore/include/CAmRoutingSender.h @@ -0,0 +1,155 @@ +/** + * 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.h + * For further information see http://www.genivi.org/. + * + */ + +#ifndef ROUTINGSENDER_H_ +#define ROUTINGSENDER_H_ + +#include "IAmRouting.h" +#include <map> + +#ifdef UNIT_TEST //this is needed to test RoutingSender +#include "../test/IAmRoutingBackdoor.h" +#endif + +namespace am +{ + +class CAmRoutingReceiver; + +/** + * Implements the RoutingSendInterface. Loads all plugins and dispatches calls to the plugins + */ +class CAmRoutingSender +{ +public: + CAmRoutingSender(const std::vector<std::string>& listOfPluginDirectories); + ~CAmRoutingSender(); + + am_Error_e removeHandle(const am_Handle_s& handle); + am_Error_e addDomainLookup(const am_Domain_s& domainData); + am_Error_e addSourceLookup(const am_Source_s& sourceData); + am_Error_e addSinkLookup(const am_Sink_s& sinkData); + am_Error_e addCrossfaderLookup(const am_Crossfader_s& crossfaderData); + am_Error_e removeDomainLookup(const am_domainID_t domainID); + am_Error_e removeSourceLookup(const am_sourceID_t sourceID); + am_Error_e removeSinkLookup(const am_sinkID_t sinkID); + am_Error_e removeCrossfaderLookup(const am_crossfaderID_t crossfaderID); + am_Error_e removeConnectionLookup(const am_connectionID_t connectionID); + + am_Error_e startupInterfaces(CAmRoutingReceiver* iRoutingReceiver); + void setRoutingReady(); + void setRoutingRundown(); + am_Error_e asyncAbort(const am_Handle_s& handle); + am_Error_e 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_Error_e asyncDisconnect(am_Handle_s& handle, const am_connectionID_t connectionID); + am_Error_e 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_Error_e 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_Error_e asyncSetSourceState(am_Handle_s& handle, const am_sourceID_t sourceID, const am_SourceState_e state); + am_Error_e asyncSetSinkSoundProperty(am_Handle_s& handle, const am_sinkID_t sinkID, const am_SoundProperty_s& soundProperty); + am_Error_e asyncSetSourceSoundProperties(am_Handle_s& handle, const std::vector<am_SoundProperty_s>& listSoundProperties, const am_sourceID_t sourceID); + am_Error_e asyncSetSinkSoundProperties(am_Handle_s& handle, const std::vector<am_SoundProperty_s>& listSoundProperties, const am_sinkID_t sinkID); + am_Error_e asyncSetSourceSoundProperty(am_Handle_s& handle, const am_sourceID_t sourceID, const am_SoundProperty_s& soundProperty); + am_Error_e 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_Error_e setDomainState(const am_domainID_t domainID, const am_DomainState_e domainState); + am_Error_e getListHandles(std::vector<am_Handle_s> & listHandles) const; + am_Error_e getListPlugins(std::vector<std::string>& interfaces) const; + void getInterfaceVersion(std::string& version) const; + am_Error_e asyncSetVolumes(am_Handle_s& handle, const std::vector<am_Volumes_s>& listVolumes); + am_Error_e asyncSetSinkNotificationConfiguration(am_Handle_s& handle, const am_sinkID_t sinkID, const am_NotificationConfiguration_s& notificationConfiguration); + am_Error_e asyncSetSourceNotificationConfiguration(am_Handle_s& handle, const am_sourceID_t sourceID, const am_NotificationConfiguration_s& notificationConfiguration); + am_Error_e resyncConnectionState(const am_domainID_t domainID, std::vector<am_Connection_s>& listOfExistingConnections); + + struct InterfaceNamePairs //!< is used to pair interfaces with busnames + { + IAmRoutingSend* routingInterface; //!< pointer to the routingInterface + std::string busName; //!< the busname + }; + + class am_handleData_c //!< is used to store data related to handles + { + public: + union + { + am_sinkID_t sinkID; + am_sourceID_t sourceID; + am_crossfaderID_t crossfaderID; + am_connectionID_t connectionID; + am_DataType_u volumeID; + }; + + union + { + am_SoundProperty_s soundPropery; + am_SourceState_e sourceState; + am_volume_t volume; + am_HotSink_e hotSink; + std::vector<am_SoundProperty_s>* soundProperties; + std::vector<am_Volumes_s>* listVolumes; + am_NotificationConfiguration_s* notificationConfiguration; + }; + + }; + + am_Error_e returnHandleData(const am_Handle_s handle,CAmRoutingSender::am_handleData_c& handleData) const; //!< returns the handle data associated with a handle + am_Error_e returnHandleDataAndRemove(const am_Handle_s handle,CAmRoutingSender::am_handleData_c& handleData); //!< returns the handle data associated with a handle and removes the handle + +#ifdef UNIT_TEST //this is needed to test RoutingSender + friend class IAmRoutingBackdoor; +#endif + +private: + struct comparator //!< is needed to sort the handles in the map + { + bool operator()(const am_Handle_s& a, const am_Handle_s& b) const + { + return (a.handle<b.handle || (a.handle==b.handle && a.handleType<b.handleType)); + } + }; + + am_Handle_s createHandle(const am_handleData_c& handleData, const am_Handle_e type); //!< creates a handle + void unloadLibraries(void); //!< unloads all loaded plugins + + typedef std::map<am_domainID_t, IAmRoutingSend*> DomainInterfaceMap; //!< maps domains to interfaces + typedef std::map<am_sinkID_t, IAmRoutingSend*> SinkInterfaceMap; //!< maps sinks to interfaces + typedef std::map<am_sourceID_t, IAmRoutingSend*> SourceInterfaceMap; //!< maps sources to interfaces + typedef std::map<am_crossfaderID_t, IAmRoutingSend*> CrossfaderInterfaceMap; //!< maps crossfaders to interfaces + typedef std::map<am_connectionID_t, IAmRoutingSend*> ConnectionInterfaceMap; //!< maps connections to interfaces + typedef std::map<uint16_t, IAmRoutingSend*> HandleInterfaceMap; //!< maps handles to interfaces + typedef std::map<am_Handle_s, am_handleData_c, comparator> HandlesMap; //!< maps handleData to handles + + int16_t mHandleCount; //!< is used to create handles + HandlesMap mlistActiveHandles; //!< list of all currently "running" handles. + std::vector<void*> mListLibraryHandles; //!< list of all loaded pluginInterfaces + std::vector<InterfaceNamePairs> mListInterfaces; //!< list of busname/interface relation + ConnectionInterfaceMap mMapConnectionInterface; //!< map of connection to interfaces + CrossfaderInterfaceMap mMapCrossfaderInterface; //!< map of crossfaders to interface + DomainInterfaceMap mMapDomainInterface; //!< map of domains to interfaces + SinkInterfaceMap mMapSinkInterface; //!< map of sinks to interfaces + SourceInterfaceMap mMapSourceInterface; //!< map of sources to interfaces + HandleInterfaceMap mMapHandleInterface; //!< map of handles to interfaces + CAmRoutingReceiver *mpRoutingReceiver; //!< pointer to routing receiver +}; + +} + +#endif /* ROUTINGSENDER_H_ */ diff --git a/AudioManagerCore/include/CAmTelnetMenuHelper.h b/AudioManagerCore/include/CAmTelnetMenuHelper.h new file mode 100644 index 0000000..7038cb3 --- /dev/null +++ b/AudioManagerCore/include/CAmTelnetMenuHelper.h @@ -0,0 +1,204 @@ +/** + * 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.h + * For further information see http://www.genivi.org/. + * + */ + +// Local header +#ifndef CAMTELNETMENUHELPER_H_ +#define CAMTELNETMENUHELPER_H_ + +// Standard header +#include <iostream> +#include <queue> +#include <map> +#include <string> +#include <sstream> +#include <vector> +#include <sys/socket.h> +#include "audiomanagertypes.h" + +namespace am +{ + +class CAmTelnetServer; +class IAmDatabaseHandler; +class CAmCommandSender; +class CAmRoutingSender; +class CAmControlSender; +class CAmCommandReceiver; +class CAmRoutingReceiver; +class CAmControlReceiver; + +class CAmRouter; +class CAmSocketHandler; + +/** + * helper class for CAmTelnetServer + */ +class CAmTelnetMenuHelper +{ +public: + + enum EMainState + { + eRootState = 0, eListState, eInfoState, eGetState, eSetState + }; + + CAmTelnetMenuHelper(CAmSocketHandler *iSocketHandler, CAmCommandSender *iCommandSender, CAmCommandReceiver *iCommandReceiver, CAmRoutingSender *iRoutingSender, CAmRoutingReceiver *iRoutingReceiver, CAmControlSender *iControlSender, CAmControlReceiver *iControlReceiver, IAmDatabaseHandler *iDatabasehandler, CAmRouter *iRouter, CAmTelnetServer *iTelnetServer); + + ~CAmTelnetMenuHelper(); + + void newSocketConnection(int filedescriptor); + + void socketConnectionsClosed(int filedescriptor); + + void enterCmdQueue(std::queue<std::string> &CmdQueue, int &filedescriptor); + +private: + + void createCommandMaps(); + void sendError(int & filedescriptor, std::string error_string); + void sendTelnetLine(int & filedescriptor, std::stringstream &line); + void sendCurrentCmdPrompt(int &filedescriptor); + + // COMMON commands + static void oneStepBackCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void oneStepBackCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void exitCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void exitCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void helpCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void helpCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + + // ROOT commands + static void rootGetCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void rootGetCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void rootSetCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void rootSetCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void rootListCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void rootListCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void rootInfoCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void rootInfoCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + + // LIST commands + static void listConnectionsCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void listConnectionsCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void listSourcesCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void listSourcesCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void listSinksCommands(std::queue<std::string> & CmdQueue, int & filedescriptor); + void listSinksCommandsExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void listCrossfaders(std::queue<std::string> & CmdQueue, int & filedescriptor); + void listCrossfadersExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void listDomainsCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void listDomainsCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void listGatewaysCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void listGatewaysCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void listPluginsCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void listPluginsCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void listMainConnectionsCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void listMainConnectionsCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void listMainSourcesCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void listMainSourcesCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void listMainSinksCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void listMainSinksCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + + // SET commands + static void setRoutingCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void setRoutingCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void setConnection(std::queue<std::string> & CmdQueue, int & filedescriptor); + void setConnectionExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void setDisconnectConnId(std::queue<std::string> & CmdQueue, int & filedescriptor); + void setDisconnectConnIdExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void setSourceSoundProperties(std::queue<std::string> & CmdQueue, int & filedescriptor); + void setSourceSoundPropertiesExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void setSinkSoundProperty(std::queue<std::string> & CmdQueue, int & filedescriptor); + void setSinkSoundPropertyExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void setSinkVolume(std::queue<std::string> & CmdQueue, int & filedescriptor); + void setSinkVolumeExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void setVolumeStep(std::queue<std::string> & CmdQueue, int & filedescriptor); + void setVolumeStepExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void setSinkMuteState(std::queue<std::string> & CmdQueue, int & filedescriptor); + void setSinkMuteStateExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void setSourceSoundProperty(std::queue<std::string> & CmdQueue, int & filedescriptor); + void setSourceSoundPropertyExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + + // GET commands + static void getRoutingCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void getRoutingCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void getSenderversionCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void getSenderversionCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void getReceiverversionCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void getReceiverversionCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + + // INFO commands + static void infoSystempropertiesCommand(std::queue<std::string> & CmdQueue, int & filedescriptor); + void infoSystempropertiesCommandExec(std::queue<std::string> & CmdQueue, int & filedescriptor); + static void infoDumpCommand(std::queue<std::string>& CmdQueue, int& filedescriptor); + void infoDumpCommandExec(std::queue<std::string>& CmdQueue, int& filedescriptor); + +private: + + typedef void (*pCommandPrototype)(std::queue<std::string>& msg, int & filedescriptor); + + struct sCommandPrototypeInfo + { + std::string info; + pCommandPrototype CommandPrototype; + + // default contructor to set NULL + sCommandPrototypeInfo() : + info(""), CommandPrototype(NULL) + { + } + + // a small contructor + sCommandPrototypeInfo(std::string MyInfo, pCommandPrototype MyCommandPrototype) : + info(MyInfo), CommandPrototype(MyCommandPrototype) + { + } + }; + + typedef std::map<std::string, sCommandPrototypeInfo> tCommandMap; + std::map<int, EMainState> mCurrentMainStateMap; //!< int filedescriptor of socket connection; EMainState state of current telnet session + + static CAmTelnetMenuHelper* instance; + CAmTelnetServer *mpTelenetServer; + CAmSocketHandler *mpSocketHandler; + CAmCommandSender *mpCommandSender; + CAmCommandReceiver *mpCommandReceiver; + CAmRoutingSender *mpRoutingSender; + CAmRoutingReceiver *mpRoutingReceiver; + CAmControlSender *mpControlSender; + CAmControlReceiver *mpControlReceiver; + IAmDatabaseHandler *mpDatabasehandler; + CAmRouter *mpRouter; + + tCommandMap mRootCommands; + tCommandMap mListCommands; + tCommandMap mGetCommands; + tCommandMap mSetCommands; + tCommandMap mInfoCommands; + +}; +// class CAmTelnetMenuHelper +}// namespace am + +#endif // CAMTELNETMENUHELPER_H_ diff --git a/AudioManagerCore/include/CAmTelnetServer.h b/AudioManagerCore/include/CAmTelnetServer.h new file mode 100644 index 0000000..0e4c510 --- /dev/null +++ b/AudioManagerCore/include/CAmTelnetServer.h @@ -0,0 +1,100 @@ +/** + * 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.h + * For further information see http://www.genivi.org/. + * + */ + +#ifndef TELNETSERVER_H_ +#define TELNETSERVER_H_ + +#include <queue> +#include <map> +#include "CAmSocketHandler.h" +#include "CAmTelnetMenuHelper.h" + +namespace am +{ + +class IAmDatabaseHandler; +class CAmCommandSender; +class CAmRoutingSender; +class CAmControlSender; +class CAmCommandReceiver; +class CAmRoutingReceiver; +class CAmControlReceiver; +class CAmRouter; +class CAmTelnetMenuHelper; + +/** + * Implements a telnetserver that can be used to connect to the audiomanager, retrieve some information and use it. For debugging purposes. + * For example, launch a telnet session on port 6060: + * \code telnet localhost 6060 \endcode + * more details can be found at the README + */ +class CAmTelnetServer +{ +public: + 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); + ~CAmTelnetServer(); + void connectSocket(const pollfd pfd, const sh_pollHandle_t handle, void* userData); + void disconnectClient(int filedescriptor); + void receiveData(const pollfd pfd, const sh_pollHandle_t handle, void* userData); + bool dispatchData(const sh_pollHandle_t handle, void* userData); + bool check(const sh_pollHandle_t handle, void* userData); + TAmShPollFired<CAmTelnetServer> telnetConnectFiredCB; + TAmShPollFired<CAmTelnetServer> telnetReceiveFiredCB; + TAmShPollDispatch<CAmTelnetServer> telnetDispatchCB; + TAmShPollCheck<CAmTelnetServer> telnetCheckCB; +private: + + typedef void (*CommandPrototype)(std::vector<std::string>& msg, int filedescriptor); + typedef std::map<std::string, CommandPrototype> mMapCommand_t; + + void sliceCommand(const std::string& string, std::string& command, std::queue<std::string>& msg); + mMapCommand_t createCommandMap(); + struct connection_s + { + int filedescriptor; + sh_pollHandle_t handle; + }; + + static CAmTelnetServer* mpInstance; + CAmSocketHandler *mpSocketHandler; + CAmCommandSender *mpCommandSender; + CAmCommandReceiver *mpCommandReceiver; + CAmRoutingSender *mpRoutingSender; + CAmRoutingReceiver *mpRoutingReceiver; + CAmControlSender *mpControlSender; + CAmControlReceiver *mpControlReceiver; + IAmDatabaseHandler *mpDatabasehandler; + CAmRouter *mpRouter; + sh_pollHandle_t mConnecthandle; + std::queue<std::string> mListMessages; + std::vector<connection_s> mListConnections; + int mConnectFD; + unsigned int mServerPort; + unsigned int mMaxConnections; + CAmTelnetMenuHelper mTelnetMenuHelper; + +}; + +} /* namespace am */ +#endif /* TELNETSERVER_H_ */ diff --git a/AudioManagerCore/include/IAmDatabaseHandler.h b/AudioManagerCore/include/IAmDatabaseHandler.h new file mode 100644 index 0000000..30c1aaf --- /dev/null +++ b/AudioManagerCore/include/IAmDatabaseHandler.h @@ -0,0 +1,200 @@ +/** + * 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 IAmDatabaseHandler.h + * For further information see http://www.genivi.org/. + * + */ + +#ifndef DATABASEHANDLERINTERFACE_H_ +#define DATABASEHANDLERINTERFACE_H_ + +#include "audiomanagertypes.h" +#include <map> +#include <vector> +#include <string> +#include <iostream> +#include <functional> +#include "audiomanagerconfig.h" + +namespace am +{ + +class CAmDatabaseObserver; +class CAmRoutingTree; +class CAmRoutingTreeItem; + + +//enum { DYNAMIC_ID_BOUNDARY = 100 }; //!< the value below is reserved for staticIDs, the value above will be assigned to dynamically registered items + +//todo: check the enum values before entering & changing in the database. +//todo: change asserts for dynamic boundary checks into failure answers.# +//todo: check autoincrement boundary and set to 16bit limits +//todo: If the sink is part of a gateway, the listconnectionFormats is copied to the gatewayInformation. Check this statement for sinks & sources +//todo: exchange last_insert_row id to be more safe +//todo: create test to ensure uniqueness of names throughout the database +//todo: enforce the uniqueness of names + +typedef std::map<am_gatewayID_t, std::vector<bool> > ListConnectionFormat; //!< type for list of connection formats + +/** + * This class handles and abstracts the database + */ + +class IAmDatabaseHandler +{ +public: + IAmDatabaseHandler () {}; + virtual ~IAmDatabaseHandler () {}; + virtual am_Error_e enterDomainDB(const am_Domain_s& domainData, am_domainID_t& domainID) = 0; + virtual am_Error_e enterMainConnectionDB(const am_MainConnection_s& mainConnectionData, am_mainConnectionID_t& connectionID) = 0; + virtual am_Error_e enterSinkDB(const am_Sink_s& sinkData, am_sinkID_t& sinkID) = 0; + virtual am_Error_e enterCrossfaderDB(const am_Crossfader_s& crossfaderData, am_crossfaderID_t& crossfaderID) = 0; + virtual am_Error_e enterGatewayDB(const am_Gateway_s& gatewayData, am_gatewayID_t& gatewayID) = 0; + virtual am_Error_e enterConverterDB(const am_Converter_s & converteData, am_converterID_t & converterID) = 0; + virtual am_Error_e enterSourceDB(const am_Source_s& sourceData, am_sourceID_t& sourceID) = 0; + virtual am_Error_e enterConnectionDB(const am_Connection_s& connection, am_connectionID_t& connectionID) = 0; + virtual am_Error_e enterSinkClassDB(const am_SinkClass_s& sinkClass, am_sinkClass_t& sinkClassID) = 0; + virtual am_Error_e enterSourceClassDB(am_sourceClass_t& sourceClassID, const am_SourceClass_s& sourceClass) = 0; + virtual am_Error_e enterSystemProperties(const std::vector<am_SystemProperty_s>& listSystemProperties) = 0; + virtual am_Error_e changeMainConnectionRouteDB(const am_mainConnectionID_t mainconnectionID, const std::vector<am_connectionID_t>& listConnectionID) = 0; + virtual am_Error_e changeMainConnectionStateDB(const am_mainConnectionID_t mainconnectionID, const am_ConnectionState_e connectionState) = 0; + virtual am_Error_e changeSinkMainVolumeDB(const am_mainVolume_t mainVolume, const am_sinkID_t sinkID) = 0; + virtual am_Error_e changeSinkAvailabilityDB(const am_Availability_s& availability, const am_sinkID_t sinkID) = 0; + virtual am_Error_e changDomainStateDB(const am_DomainState_e domainState, const am_domainID_t domainID) = 0; + virtual am_Error_e changeSinkMuteStateDB(const am_MuteState_e muteState, const am_sinkID_t sinkID) = 0; + virtual am_Error_e changeMainSinkSoundPropertyDB(const am_MainSoundProperty_s& soundProperty, const am_sinkID_t sinkID) = 0; + virtual am_Error_e changeMainSourceSoundPropertyDB(const am_MainSoundProperty_s& soundProperty, const am_sourceID_t sourceID) = 0; + virtual am_Error_e changeSourceSoundPropertyDB(const am_SoundProperty_s& soundProperty, const am_sourceID_t sourceID) = 0; + virtual am_Error_e changeSinkSoundPropertyDB(const am_SoundProperty_s& soundProperty, const am_sinkID_t sinkID) = 0; + virtual am_Error_e changeSourceAvailabilityDB(const am_Availability_s& availability, const am_sourceID_t sourceID) = 0; + virtual am_Error_e changeSystemPropertyDB(const am_SystemProperty_s& property) = 0; + virtual am_Error_e changeDelayMainConnection(const am_timeSync_t & delay, const am_mainConnectionID_t & connectionID) = 0; + virtual am_Error_e changeSinkClassInfoDB(const am_SinkClass_s& sinkClass) = 0; + virtual am_Error_e changeSourceClassInfoDB(const am_SourceClass_s& sourceClass) = 0; + virtual am_Error_e changeConnectionTimingInformation(const am_connectionID_t connectionID, const am_timeSync_t delay) = 0; + virtual am_Error_e changeConnectionFinal(const am_connectionID_t connectionID) = 0; + virtual am_Error_e changeSourceState(const am_sourceID_t sourceID, const am_SourceState_e sourceState) = 0; + virtual am_Error_e changeSinkVolume(const am_sinkID_t sinkID, const am_volume_t volume) = 0; + virtual am_Error_e changeSourceVolume(const am_sourceID_t sourceID, const am_volume_t volume) = 0; + virtual am_Error_e changeCrossFaderHotSink(const am_crossfaderID_t crossfaderID, const am_HotSink_e hotsink) = 0; + virtual am_Error_e removeMainConnectionDB(const am_mainConnectionID_t mainConnectionID) = 0; + virtual am_Error_e removeSinkDB(const am_sinkID_t sinkID) = 0; + virtual am_Error_e removeSourceDB(const am_sourceID_t sourceID) = 0; + virtual am_Error_e removeGatewayDB(const am_gatewayID_t gatewayID) = 0; + virtual am_Error_e removeConverterDB(const am_converterID_t converterID) = 0; + virtual am_Error_e removeCrossfaderDB(const am_crossfaderID_t crossfaderID) = 0; + virtual am_Error_e removeDomainDB(const am_domainID_t domainID) = 0; + virtual am_Error_e removeSinkClassDB(const am_sinkClass_t sinkClassID) = 0; + virtual am_Error_e removeSourceClassDB(const am_sourceClass_t sourceClassID) = 0; + virtual am_Error_e removeConnection(const am_connectionID_t connectionID) = 0; + virtual am_Error_e getSourceClassInfoDB(const am_sourceID_t sourceID, am_SourceClass_s& classInfo) const = 0; + virtual am_Error_e getSinkClassInfoDB(const am_sinkID_t sinkID, am_SinkClass_s& sinkClass) const = 0; + virtual am_Error_e getGatewayInfoDB(const am_gatewayID_t gatewayID, am_Gateway_s& gatewayData) const = 0; + virtual am_Error_e getConverterInfoDB(const am_converterID_t converterID, am_Converter_s& converterData) const = 0; + virtual am_Error_e getSinkInfoDB(const am_sinkID_t sinkID, am_Sink_s& sinkData) const = 0; + virtual am_Error_e getSourceInfoDB(const am_sourceID_t sourceID, am_Source_s& sourceData) const = 0; + virtual am_Error_e getCrossfaderInfoDB(const am_crossfaderID_t crossfaderID, am_Crossfader_s& crossfaderData) const = 0; + virtual am_Error_e getMainConnectionInfoDB(const am_mainConnectionID_t mainConnectionID, am_MainConnection_s& mainConnectionData) const = 0; + virtual am_Error_e getSinkMainVolume(const am_sinkID_t sinkID, am_mainVolume_t& mainVolume) const = 0; + virtual am_Error_e getSinkVolume(const am_sinkID_t sinkID, am_volume_t& volume) const = 0; + virtual am_Error_e getSourceVolume(const am_sourceID_t sourceID, am_volume_t& volume) const = 0; + virtual am_Error_e getSinkSoundPropertyValue(const am_sinkID_t sinkID, const am_CustomSoundPropertyType_t propertyType, int16_t& value) const = 0; + virtual am_Error_e getSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomSoundPropertyType_t propertyType, int16_t& value) const = 0; + virtual am_Error_e getListSinkSoundProperties(const am_sinkID_t sinkID, std::vector<am_SoundProperty_s>& listSoundproperties) const =0; + virtual am_Error_e getListSourceSoundProperties(const am_sourceID_t sourceID, std::vector<am_SoundProperty_s>& listSoundproperties) const =0; + virtual am_Error_e getMainSinkSoundPropertyValue(const am_sinkID_t sinkID, const am_CustomMainSoundPropertyType_t propertyType, int16_t& value) const = 0; + virtual am_Error_e getMainSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomMainSoundPropertyType_t propertyType, int16_t& value) const = 0; + virtual am_Error_e getListSinksOfDomain(const am_domainID_t domainID, std::vector<am_sinkID_t>& listSinkID) const = 0; + virtual am_Error_e getListSourcesOfDomain(const am_domainID_t domainID, std::vector<am_sourceID_t>& listSourceID) const = 0; + virtual am_Error_e getListCrossfadersOfDomain(const am_domainID_t domainID, std::vector<am_crossfaderID_t>& listGatewaysID) const = 0; + virtual am_Error_e getListGatewaysOfDomain(const am_domainID_t domainID, std::vector<am_gatewayID_t>& listGatewaysID) const = 0; + virtual am_Error_e getListConvertersOfDomain(const am_domainID_t domainID, std::vector<am_converterID_t>& listConvertersID) const = 0; + virtual am_Error_e getListMainConnections(std::vector<am_MainConnection_s>& listMainConnections) const = 0; + virtual am_Error_e getListDomains(std::vector<am_Domain_s>& listDomains) const = 0; + virtual am_Error_e getListConnections(std::vector<am_Connection_s>& listConnections) const = 0; + virtual am_Error_e getListSinks(std::vector<am_Sink_s>& listSinks) const = 0; + virtual am_Error_e getListSources(std::vector<am_Source_s>& lisSources) const = 0; + virtual am_Error_e getListSourceClasses(std::vector<am_SourceClass_s>& listSourceClasses) const = 0; + virtual am_Error_e getListCrossfaders(std::vector<am_Crossfader_s>& listCrossfaders) const = 0; + virtual am_Error_e getListGateways(std::vector<am_Gateway_s>& listGateways) const = 0; + virtual am_Error_e getListConverters(std::vector<am_Converter_s> & listConverters) const = 0; + virtual am_Error_e getListSinkClasses(std::vector<am_SinkClass_s>& listSinkClasses) const = 0; + virtual am_Error_e getListVisibleMainConnections(std::vector<am_MainConnectionType_s>& listConnections) const = 0; + virtual am_Error_e getListMainSinks(std::vector<am_SinkType_s>& listMainSinks) const = 0; + virtual am_Error_e getListMainSources(std::vector<am_SourceType_s>& listMainSources) const = 0; + virtual am_Error_e getListMainSinkSoundProperties(const am_sinkID_t sinkID, std::vector<am_MainSoundProperty_s>& listSoundProperties) const = 0; + virtual am_Error_e getListMainSourceSoundProperties(const am_sourceID_t sourceID, std::vector<am_MainSoundProperty_s>& listSourceProperties) const = 0; + virtual am_Error_e getListSystemProperties(std::vector<am_SystemProperty_s>& listSystemProperties) const = 0; + virtual am_Error_e getListSinkConnectionFormats(const am_sinkID_t sinkID, std::vector<am_CustomConnectionFormat_t> & listConnectionFormats) const = 0; + virtual am_Error_e getListSourceConnectionFormats(const am_sourceID_t sourceID, std::vector<am_CustomConnectionFormat_t> & listConnectionFormats) const = 0; + virtual am_Error_e getListGatewayConnectionFormats(const am_gatewayID_t gatewayID, std::vector<bool> & listConnectionFormat) const = 0; + virtual am_Error_e getTimingInformation(const am_mainConnectionID_t mainConnectionID, am_timeSync_t& delay) const = 0; + virtual am_Error_e getDomainOfSource(const am_sourceID_t sourceID, am_domainID_t& domainID) const = 0; + virtual am_Error_e getDomainOfSink(const am_sinkID_t sinkID, am_domainID_t& domainID) const = 0; + virtual am_Error_e getDomainOfCrossfader(const am_crossfaderID_t crossfader, am_domainID_t& domainID) const = 0; + virtual am_Error_e getSoureState(const am_sourceID_t sourceID, am_SourceState_e& sourceState) const = 0; + virtual am_Error_e getDomainState(const am_domainID_t domainID, am_DomainState_e& state) const = 0; + virtual am_Error_e peekDomain(const std::string& name, am_domainID_t& domainID) = 0; + virtual am_Error_e peekSink(const std::string& name, am_sinkID_t& sinkID) = 0; + virtual am_Error_e peekSource(const std::string& name, am_sourceID_t& sourceID) = 0; + virtual am_Error_e peekSinkClassID(const std::string& name, am_sinkClass_t& sinkClassID) = 0; + virtual am_Error_e peekSourceClassID(const std::string& name, am_sourceClass_t& sourceClassID) = 0; + virtual am_Error_e 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) = 0; + virtual am_Error_e 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) = 0; + virtual am_Error_e getListMainSinkNotificationConfigurations(const am_sinkID_t sinkID, std::vector<am_NotificationConfiguration_s>& listMainNotificationConfigurations) = 0; + virtual am_Error_e getListMainSourceNotificationConfigurations(const am_sourceID_t sourceID, std::vector<am_NotificationConfiguration_s>& listMainNotificationConfigurations) = 0; + virtual am_Error_e changeMainSinkNotificationConfigurationDB(const am_sinkID_t sinkID, const am_NotificationConfiguration_s mainNotificationConfiguration) = 0; + virtual am_Error_e changeMainSourceNotificationConfigurationDB(const am_sourceID_t sourceID, const am_NotificationConfiguration_s mainNotificationConfiguration) = 0; + virtual am_Error_e 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) = 0; + virtual am_Error_e changeConverterDB(const am_converterID_t converterID, const std::vector<am_CustomConnectionFormat_t>& listSourceConnectionFormats, const std::vector<am_CustomConnectionFormat_t>& listSinkConnectionFormats, const std::vector<bool>& convertionMatrix) = 0; + virtual am_Error_e changeSinkNotificationConfigurationDB(const am_sinkID_t sinkID,const am_NotificationConfiguration_s notificationConfiguration) = 0; + virtual am_Error_e changeSourceNotificationConfigurationDB(const am_sourceID_t sourceID,const am_NotificationConfiguration_s notificationConfiguration) = 0; + + virtual bool existMainConnection(const am_mainConnectionID_t mainConnectionID) const = 0; + virtual bool existCrossFader(const am_crossfaderID_t crossfaderID) const = 0; + virtual bool existConnection(const am_Connection_s & connection) const = 0; + virtual bool existConnectionID(const am_connectionID_t connectionID) const = 0; + virtual bool existSource(const am_sourceID_t sourceID) const = 0; + virtual bool existSourceNameOrID(const am_sourceID_t sourceID, const std::string& name) const = 0; + virtual bool existSourceName(const std::string& name) const = 0; + virtual bool existSink(const am_sinkID_t sinkID) const = 0; + virtual bool existSinkNameOrID(const am_sinkID_t sinkID, const std::string& name) const = 0; + virtual bool existSinkName(const std::string& name) const = 0; + virtual bool existDomain(const am_domainID_t domainID) const = 0; + virtual bool existGateway(const am_gatewayID_t gatewayID) const = 0; + virtual bool existSinkClass(const am_sinkClass_t sinkClassID) const = 0; + virtual bool existSourceClass(const am_sourceClass_t sourceClassID) const = 0; + virtual void registerObserver(CAmDatabaseObserver *iObserver) = 0; + virtual bool sourceVisible(const am_sourceID_t sourceID) const = 0; + virtual bool sinkVisible(const am_sinkID_t sinkID) const = 0; + virtual bool isComponentConnected(const am_Gateway_s & gateway) const = 0; + virtual bool isComponentConnected(const am_Converter_s & converter) const = 0; + virtual am_timeSync_t calculateMainConnectionDelay(const am_mainConnectionID_t mainConnectionID) const = 0; //!< calculates a new main connection delay + virtual void dump( std::ostream & output) const = 0 ; + virtual am_Error_e enumerateSources(std::function<void(const am_Source_s & element)> cb) const = 0 ; + virtual am_Error_e enumerateSinks(std::function<void(const am_Sink_s & element)> cb) const = 0 ; + virtual am_Error_e enumerateGateways(std::function<void(const am_Gateway_s & element)> cb) const = 0 ; + virtual am_Error_e enumerateConverters(std::function<void(const am_Converter_s & element)> cb) const = 0 ; + +}; + + +} + +#endif /* DATABASEHANDLERINTERFACE_H_ */ diff --git a/AudioManagerCore/include/TAmPluginTemplate.h b/AudioManagerCore/include/TAmPluginTemplate.h new file mode 100644 index 0000000..f000fbe --- /dev/null +++ b/AudioManagerCore/include/TAmPluginTemplate.h @@ -0,0 +1,91 @@ +/** + * 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 TAmPluginTemplate.h + * For further information see http://www.genivi.org/. + * + */ + +#ifndef PLUGINTEMPLATE_H_ +#define PLUGINTEMPLATE_H_ + +#include <dlfcn.h> +#include <libgen.h> +#include "CAmDltWrapper.h" + +namespace am +{ + +/** + * * This template tries to load a library and cast to a class + * @param libname the full path to the library to be loaded + * @param libraryHandle the handle to the library that gets returned + * @return returns the pointer to the class to be loaded + */ +template<class T> T* getCreateFunction(const std::string& libname, void*& libraryHandle) +{ + + logInfo("getCreateFunction : Trying to load library with name: ",libname); + + // cut off directories + char* fileWithPath = const_cast<char*>(libname.c_str()); + std::string libFileName = basename(fileWithPath); + + // cut off "lib" in front and cut off .so end" + std::string createFunctionName = libFileName.substr(3, libFileName.length() - 6) + "Factory"; + // open library + dlerror(); // Clear any existing error + libraryHandle = dlopen(libname.c_str(), RTLD_LAZY ); + const char* dlopen_error = dlerror(); + if (!libraryHandle || dlopen_error) + { + logError("getCreateFunction : dlopen failed",dlopen_error); + return (0); + } + + // get entry point from shared lib + dlerror(); // Clear any existing error + + union + { + void* voidPointer; + T* typedPointer; + } functionPointer; + + // Note: direct cast is not allowed by ISO C++. e.g. + // T* createFunction = reinterpret_cast<T*>(dlsym(libraryHandle, createFunctionName.c_str())); + // compiler warning: "forbids casting between pointer-to-function and pointer-to-object" + + functionPointer.voidPointer = dlsym(libraryHandle, createFunctionName.c_str()); + T* createFunction = functionPointer.typedPointer; + + const char* dlsym_error = dlerror(); + if (!createFunction || dlsym_error) + { + logError("getCreateFunction: Failed to load shared lib entry point",dlsym_error); + } + else + { + logInfo("getCreateFunction : loaded successfully plugin", createFunctionName); + } + return (createFunction); +} + +} + +#endif /* PLUGINTEMPLATE_H_ */ 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++; + } +} +} + diff --git a/AudioManagerCore/test/AmControlInterfaceTest/CAmControlInterfaceTest.cpp b/AudioManagerCore/test/AmControlInterfaceTest/CAmControlInterfaceTest.cpp new file mode 100644 index 0000000..9008ce6 --- /dev/null +++ b/AudioManagerCore/test/AmControlInterfaceTest/CAmControlInterfaceTest.cpp @@ -0,0 +1,673 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmControlInterfaceTest.h" +#include <algorithm> +#include <string> +#include <vector> +#include <set> +#include "CAmDltWrapper.h" +#include "CAmCommandLineSingleton.h" + +using namespace am; +using namespace testing; + +DLT_DECLARE_CONTEXT(AudioManager) +TCLAP::SwitchArg enableNoDLTDebug ("V","logDlt","print DLT logs to stdout or dlt-daemon default off",false); + +ACTION(returnResyncConnection) +{ + std::vector<am_Connection_s> listConnections; + am_Connection_s conn; + conn.sinkID=1; + conn.sourceID=1; + conn.connectionFormat=CF_GENIVI_ANALOG; + listConnections.push_back(conn); + arg1=listConnections; +} + +CAmControlInterfaceTest::CAmControlInterfaceTest() : + pSocketHandler(), // + plistCommandPluginDirs(), // + plistRoutingPluginDirs(), // + pDatabaseHandler(), // + pRoutingSender(plistRoutingPluginDirs), //RoutingReceiver + pCommandSender(plistCommandPluginDirs), // + pMockControlInterface(), // + pMockRoutingInterface(), // + pRoutingInterfaceBackdoor(), // + pCommandInterfaceBackdoor(), // + pControlInterfaceBackdoor(), // + pControlSender(), // + pRouter(&pDatabaseHandler,&pControlSender), // + pDatabaseObserver(&pCommandSender, &pRoutingSender, &pSocketHandler), // + pControlReceiver(&pDatabaseHandler, &pRoutingSender, &pCommandSender, &pSocketHandler, &pRouter), // + pRoutingReceiver(&pDatabaseHandler, &pRoutingSender, &pControlSender, &pSocketHandler) +{ + pDatabaseHandler.registerObserver(&pDatabaseObserver); + pControlInterfaceBackdoor.replaceController(&pControlSender, &pMockControlInterface); + pRoutingInterfaceBackdoor.injectInterface(&pRoutingSender, &pMockRoutingInterface, "mock"); + +} + +CAmControlInterfaceTest::~CAmControlInterfaceTest() +{ + CAmDltWrapper::instance()->unregisterContext(AudioManager); +} + +void CAmControlInterfaceTest::SetUp() +{ + +} + +void CAmControlInterfaceTest::TearDown() +{ +} + +TEST_F(CAmControlInterfaceTest,registerDomain) +{ + + am_Domain_s domain; + am_domainID_t domainID; + pCF.createDomain(domain); + + //When we run this test, we expect the call on the control interface + EXPECT_CALL(pMockControlInterface,hookSystemRegisterDomain(_,_)).WillRepeatedly(DoAll(SetArgReferee<1>(2), Return(E_OK))); + ASSERT_EQ(E_OK, pRoutingReceiver.registerDomain(domain,domainID)); + ASSERT_EQ(domainID, 2); +} + +TEST_F(CAmControlInterfaceTest,deregisterDomain) +{ + am_domainID_t domainID = 34; + + //When we run this test, we expect the call on the control interface + EXPECT_CALL(pMockControlInterface,hookSystemDeregisterDomain(34)).WillRepeatedly(Return(E_OK)); + ASSERT_EQ(E_OK, pRoutingReceiver.deregisterDomain(domainID)); +} + +TEST_F(CAmControlInterfaceTest,registerSink) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + pCF.createSink(sink); + + //When we run this test, we expect the call on the control interface + EXPECT_CALL(pMockControlInterface,hookSystemRegisterSink(_,_)).WillRepeatedly(DoAll(SetArgReferee<1>(2), Return(E_OK))); + ASSERT_EQ(E_OK, pRoutingReceiver.registerSink(sink,sinkID)); + ASSERT_EQ(sinkID, 2); +} + +TEST_F(CAmControlInterfaceTest,deregisterSink) +{ + am_sinkID_t sinkID = 12; + + //When we run this test, we expect the call on the control interface + EXPECT_CALL(pMockControlInterface,hookSystemDeregisterSink(12)).WillRepeatedly(Return(E_OK)); + ASSERT_EQ(E_OK, pRoutingReceiver.deregisterSink(sinkID)); +} + +TEST_F(CAmControlInterfaceTest,registerSource) +{ + am_Source_s source; + am_sourceID_t sourceID; + pCF.createSource(source); + + //When we run this test, we expect the call on the control interface + EXPECT_CALL(pMockControlInterface,hookSystemRegisterSource(_,_)).WillRepeatedly(DoAll(SetArgReferee<1>(2), Return(E_OK))); + ASSERT_EQ(E_OK, pRoutingReceiver.registerSource(source,sourceID)); + ASSERT_EQ(sourceID, 2); +} + +TEST_F(CAmControlInterfaceTest,deregisterSource) +{ + am_sourceID_t sourceID = 12; + + //When we run this test, we expect the call on the control interface + EXPECT_CALL(pMockControlInterface,hookSystemDeregisterSource(12)).WillRepeatedly(Return(E_OK)); + ASSERT_EQ(E_OK, pRoutingReceiver.deregisterSource(sourceID)); +} + +TEST_F(CAmControlInterfaceTest,registerGateway) +{ + am_Gateway_s gateway; + am_gatewayID_t gatewayID; + pCF.createGateway(gateway); + + //When we run this test, we expect the call on the control interface + EXPECT_CALL(pMockControlInterface,hookSystemRegisterGateway(_,_)).WillRepeatedly(DoAll(SetArgReferee<1>(2), Return(E_OK))); + ASSERT_EQ(E_OK, pRoutingReceiver.registerGateway(gateway,gatewayID)); + ASSERT_EQ(gatewayID, 2); +} + +TEST_F(CAmControlInterfaceTest,deregisterGateway) +{ + am_gatewayID_t gatewayID = 12; + + //When we run this test, we expect the call on the control interface + EXPECT_CALL(pMockControlInterface,hookSystemDeregisterGateway(12)).WillRepeatedly(Return(E_OK)); + ASSERT_EQ(E_OK, pRoutingReceiver.deregisterGateway(gatewayID)); +} + +TEST_F(CAmControlInterfaceTest,ackConnect) +{ + am_connectionID_t connectionID; + am_Sink_s sink; + am_sinkID_t sinkID; + am_Domain_s domain; + am_domainID_t domainID; + std::vector<am_Connection_s> connectionList; + std::vector<am_Handle_s> handlesList; + am_Handle_s handle; + pCF.createSink(sink); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + sink.sinkID = 2; + sink.domainID = DYNAMIC_ID_BOUNDARY; + + //prepare the stage + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + //when asyncConnect is called, we expect a call on the routingInterface + EXPECT_CALL(pMockRoutingInterface,asyncConnect(_,1,2,2,CF_GENIVI_STEREO)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.connect(handle,connectionID,CF_GENIVI_STEREO,2,2)); + + //The handle should have the correct type + ASSERT_EQ(handle.handleType, H_CONNECT); + ASSERT_EQ(handle.handle, 1); + ASSERT_EQ(connectionID, 1); + + //The list of handles shall have the handle inside + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_EQ(handlesList[0].handle, handle.handle); + ASSERT_EQ(handlesList[0].handleType, handle.handleType); + + //we check the list of connections - but it must be empty because the ack did not arrive yet + ASSERT_EQ(E_OK, pDatabaseHandler.getListConnections(connectionList)); + ASSERT_TRUE(connectionList.empty()); + + //finally we answer via the RoutingInterface and expect a call on the controlInterface + EXPECT_CALL(pMockControlInterface,cbAckConnect(_,E_OK)).Times(1); + pRoutingReceiver.ackConnect(handle, connectionID, E_OK); + + //the list of handles must be empty now + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_TRUE(handlesList.empty()); + + //but the connection must be in the connectionlist + ASSERT_EQ(E_OK, pDatabaseHandler.getListConnections(connectionList)); + ASSERT_TRUE(!connectionList.empty()); + + //no we try the same, but do expect a no_change answer directly and no call because connection already exists + //ASSERT_EQ(E_ALREADY_EXISTS, pControlReceiver.connect(handle,connectionID,CF_GENIVI_STEREO,2,2)); + //needed to be removed because logic changed here +} + +TEST_F(CAmControlInterfaceTest,ackDisconnect) +{ + am_connectionID_t connectionID; + am_Sink_s sink; + am_sinkID_t sinkID; + am_Domain_s domain; + am_domainID_t domainID; + std::vector<am_Connection_s> connectionList; + std::vector<am_Handle_s> handlesList; + am_Handle_s handle; + pCF.createSink(sink); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + sink.sinkID = 2; + sink.domainID = DYNAMIC_ID_BOUNDARY; + + //prepare the stage + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + //now we first need to connect, we expect a call on the routing interface + EXPECT_CALL(pMockRoutingInterface,asyncConnect(_,1,2,2,CF_GENIVI_STEREO)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.connect(handle,connectionID,CF_GENIVI_STEREO,2,2)); + + //answer with an ack to insert the connection in the database + EXPECT_CALL(pMockControlInterface,cbAckConnect(_,E_OK)).Times(1); + pRoutingReceiver.ackConnect(handle, connectionID, E_OK); + + //now we can start to disconnect and expect a call on the routing interface + EXPECT_CALL(pMockRoutingInterface,asyncDisconnect(_,1)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.disconnect(handle,1)); + + //during the disconnection, the connection is still in the list! + ASSERT_EQ(E_OK, pDatabaseHandler.getListConnections(connectionList)); + ASSERT_TRUE(!connectionList.empty()); + + //then we fire the ack and expect a call on the controlInterface + EXPECT_CALL(pMockControlInterface,cbAckDisconnect(_,E_OK)).Times(1); + pRoutingReceiver.ackDisconnect(handle, connectionID, E_OK); + + //make sure the handle is gone + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_TRUE(handlesList.empty()); + + //make sure the connection is gone + ASSERT_EQ(E_OK, pDatabaseHandler.getListConnections(connectionList)); + ASSERT_TRUE(connectionList.empty()); + + //Now let's try to disconnect what is not existing... + ASSERT_EQ(E_NON_EXISTENT, pControlReceiver.disconnect(handle,2)); +} + +TEST_F(CAmControlInterfaceTest,ackDisconnectFailAndRetry) +{ + logInfo("ackDisconnectFailAndRetry test started"); + am_connectionID_t connectionID; + am_Sink_s sink; + am_sinkID_t sinkID; + am_Domain_s domain; + am_domainID_t domainID; + std::vector<am_Connection_s> connectionList; + std::vector<am_Handle_s> handlesList; + am_Handle_s handle; + pCF.createSink(sink); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + sink.sinkID = 2; + sink.domainID = DYNAMIC_ID_BOUNDARY; + + //prepare the stage + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + //now we first need to connect, we expect a call on the routing interface + EXPECT_CALL(pMockRoutingInterface,asyncConnect(_,1,2,2,CF_GENIVI_STEREO)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.connect(handle,connectionID,CF_GENIVI_STEREO,2,2)); + + //answer with an ack to insert the connection in the database + EXPECT_CALL(pMockControlInterface,cbAckConnect(_,E_OK)).Times(1); + pRoutingReceiver.ackConnect(handle, connectionID, E_OK); + + //now we can start to disconnect and expect a call on the routing interface + EXPECT_CALL(pMockRoutingInterface,asyncDisconnect(_,1)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.disconnect(handle,1)); + + //during the disconnection, the connection is still in the list! + ASSERT_EQ(E_OK, pDatabaseHandler.getListConnections(connectionList)); + ASSERT_TRUE(!connectionList.empty()); + + //then we fire the ack and expect a call on the controlInterface + EXPECT_CALL(pMockControlInterface,cbAckDisconnect(_,E_NON_EXISTENT)).Times(1); + pRoutingReceiver.ackDisconnect(handle, connectionID+1, E_NON_EXISTENT); + + //make sure the handle is gone + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_TRUE(handlesList.empty()); + + //make sure the connection is still there + ASSERT_EQ(E_OK, pDatabaseHandler.getListConnections(connectionList)); + ASSERT_FALSE(connectionList.empty()); + + ASSERT_TRUE(pDatabaseHandler.existConnectionID(1)); + + //Now let's try to disconnect now + EXPECT_CALL(pMockRoutingInterface,asyncDisconnect(_,1)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.disconnect(handle,1)); + logInfo("ackDisconnectFailAndRetry test finished"); +} + +TEST_F(CAmControlInterfaceTest,setSourceState) +{ + + am_Source_s source; + am_sourceID_t sourceID; + am_Domain_s domain; + am_domainID_t domainID; + std::vector<am_Handle_s> handlesList; + am_Handle_s handle; + am_SourceState_e state; + pCF.createSource(source); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + source.sourceID = 2; + source.domainID = DYNAMIC_ID_BOUNDARY; + + //prepare the stage + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + + //we set the sourcestate and expect a call on the routingInterface + EXPECT_CALL(pMockRoutingInterface,asyncSetSourceState(_,2,SS_PAUSED)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.setSourceState(handle,source.sourceID,SS_PAUSED)); + + //we want our handle in the list and let the type be the right one + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_EQ(handlesList[0].handle, handle.handle); + ASSERT_EQ(handlesList[0].handleType, H_SETSOURCESTATE); + + //the state must be unchanged because did not get the ack + ASSERT_EQ(E_OK, pDatabaseHandler.getSoureState(source.sourceID,state)); + ASSERT_EQ(state, SS_ON); + + //now we sent out the ack and expect a call on the controlInterface + EXPECT_CALL(pMockControlInterface,cbAckSetSourceState(_,E_OK)).Times(1); + pRoutingReceiver.ackSetSourceState(handle, E_OK); + + //finally we need the sourcestate to be changed + ASSERT_EQ(E_OK, pDatabaseHandler.getSoureState(source.sourceID,state)); + ASSERT_EQ(state, SS_PAUSED); + + //make sure the handle is gone + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_TRUE(handlesList.empty()); + + //we try again but expect a no change error + //ASSERT_EQ(E_NO_CHANGE, pControlReceiver.setSourceState(handle,source.sourceID,SS_PAUSED)); + //needed to be removed because logic changed here +} + +TEST_F(CAmControlInterfaceTest,SetSinkVolumeChange) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + am_Domain_s domain; + am_domainID_t domainID; + am_volume_t volume; + std::vector<am_Handle_s> handlesList; + am_Handle_s handle; + pCF.createSink(sink); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + sink.sinkID = 2; + sink.domainID = DYNAMIC_ID_BOUNDARY; + sink.volume = 10; + + //setup environment, we need a domain and a sink + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + //set the volume and expect a call on the routing interface + EXPECT_CALL(pMockRoutingInterface,asyncSetSinkVolume(_,2,11,RAMP_GENIVI_DIRECT,23)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.setSinkVolume(handle,sinkID,11,RAMP_GENIVI_DIRECT,23)); + + //check the list of handles. The handle must be in there and have the right type + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_EQ(handlesList[0].handle, handle.handle); + ASSERT_EQ(handlesList[0].handleType, H_SETSINKVOLUME); + + //now we read out the volume, but we expect no change because the ack did not arrive yet + ASSERT_EQ(E_OK, pDatabaseHandler.getSinkVolume(sinkID,volume)); + ASSERT_EQ(sink.volume, volume); + + //lets send the answer and expect a call on the controlInterface + EXPECT_CALL(pMockControlInterface,cbAckSetSinkVolumeChange(_,11,E_OK)).Times(1); + pRoutingReceiver.ackSetSinkVolumeChange(handle, 11, E_OK); + + //finally, the new value must be in the database + ASSERT_EQ(E_OK, pDatabaseHandler.getSinkVolume(sinkID,volume)); + ASSERT_EQ(11, volume); + + //and the handle must be destroyed + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_TRUE(handlesList.empty()); + + //Now we try again, but the value is unchanged + //ASSERT_EQ(E_NO_CHANGE, pControlReceiver.setSinkVolume(handle,sinkID,11,RAMP_GENIVI_DIRECT,23)); + //needed to be removed because logic changed here +} + +TEST_F(CAmControlInterfaceTest,ackSetSourceVolumeChange) +{ + am_Source_s source; + am_sourceID_t sourceID; + am_Domain_s domain; + am_domainID_t domainID; + am_volume_t volume; + std::vector<am_Handle_s> handlesList; + am_Handle_s handle; + pCF.createSource(source); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + source.sourceID = 2; + source.domainID = DYNAMIC_ID_BOUNDARY; + source.volume = 12; + + //prepare the scene + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + + //change the sinkVolume, expect a call on the routingInterface + EXPECT_CALL(pMockRoutingInterface,asyncSetSourceVolume(_,2,11,RAMP_GENIVI_DIRECT,23)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.setSourceVolume(handle,source.sourceID,11,RAMP_GENIVI_DIRECT,23)); + + //check the list of handles. The handle must be in there and have the right type + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_EQ(handlesList[0].handle, handle.handle); + ASSERT_EQ(handlesList[0].handleType, H_SETSOURCEVOLUME); + + //now we read out the volume, but we expect no change because the ack did not arrive yet + ASSERT_EQ(E_OK, pDatabaseHandler.getSourceVolume(sourceID,volume)); + ASSERT_EQ(source.volume, volume); + + //lets send the answer and expect a call on the controlInterface + EXPECT_CALL(pMockControlInterface,cbAckSetSourceVolumeChange(_,11,E_OK)).Times(1); + pRoutingReceiver.ackSetSourceVolumeChange(handle, 11, E_OK); + + //finally, the new value must be in the database + ASSERT_EQ(E_OK, pDatabaseHandler.getSourceVolume(sourceID,volume)); + ASSERT_EQ(11, volume); + + //and the handle must be destroyed + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_TRUE(handlesList.empty()); + + //Now we try again, but the value is unchanged + //ASSERT_EQ(E_NO_CHANGE, pControlReceiver.setSourceVolume(handle,source.sourceID,11,RAMP_GENIVI_DIRECT,23)); + //needed to be removed because logic changed here +} + +TEST_F(CAmControlInterfaceTest,ackSetSinkSoundProperty) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + am_Domain_s domain; + am_domainID_t domainID; + std::vector<am_Handle_s> handlesList; + am_Handle_s handle; + am_SoundProperty_s soundProperty; + int16_t oldvalue; + pCF.createSink(sink); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + sink.sinkID = 2; + sink.domainID = DYNAMIC_ID_BOUNDARY; + soundProperty.type = SP_GENIVI_BASS; + soundProperty.value = 244; + + //setup environment, we need a domain and a sink + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + //change the soundproperty, expect a call on the routinginterface + EXPECT_CALL(pMockRoutingInterface,asyncSetSinkSoundProperty(_,2,_)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.setSinkSoundProperty(handle,sink.sinkID,soundProperty)); + + //check the list of handles. The handle must be in there and have the right type + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_EQ(handlesList[0].handle, handle.handle); + ASSERT_EQ(handlesList[0].handleType, H_SETSINKSOUNDPROPERTY); + + //read out this property. There is no change, because the ack did not arrive yet. + ASSERT_EQ(E_OK, pDatabaseHandler.getSinkSoundPropertyValue(2,SP_GENIVI_BASS,oldvalue)); + ASSERT_EQ(sink.listSoundProperties[0].value, oldvalue); + + //lets send the answer and expect a call on the controlInterface + EXPECT_CALL(pMockControlInterface,cbAckSetSinkSoundProperty(_,E_OK)).Times(1); + pRoutingReceiver.ackSetSinkSoundProperty(handle, E_OK); + + //finally, the new value must be in the database + ASSERT_EQ(E_OK, pDatabaseHandler.getSinkSoundPropertyValue(sinkID,SP_GENIVI_BASS,oldvalue)); + ASSERT_EQ(soundProperty.value, oldvalue); + + //and the handle must be destroyed + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_TRUE(handlesList.empty()); + + //Now we try again, but the value is unchanged + //ASSERT_EQ(E_NO_CHANGE, pControlReceiver.setSinkSoundProperty(handle,sink.sinkID,soundProperty)); + //needed to be removed because logic changed here +} + +TEST_F(CAmControlInterfaceTest,ackSetSourceSoundProperty) +{ + am_Source_s source; + am_sourceID_t sourceID; + am_Domain_s domain; + am_domainID_t domainID; + std::vector<am_Handle_s> handlesList; + am_Handle_s handle; + am_SoundProperty_s soundProperty; + int16_t oldvalue; + pCF.createSource(source); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + source.sourceID = 2; + source.domainID = DYNAMIC_ID_BOUNDARY; + soundProperty.type = SP_GENIVI_BASS; + soundProperty.value = 244; + + //prepare the scene + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + + //we trigger the change and wait for a call on the routinginterface + EXPECT_CALL(pMockRoutingInterface,asyncSetSourceSoundProperty(_,2,_)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.setSourceSoundProperty(handle,source.sourceID,soundProperty)); + + //check the list of handles. The handle must be in there and have the right type + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_EQ(handlesList[0].handle, handle.handle); + ASSERT_EQ(handlesList[0].handleType, H_SETSOURCESOUNDPROPERTY); + + //read out this property. There is no change, because the ack did not arrive yet. + ASSERT_EQ(E_OK, pDatabaseHandler.getSourceSoundPropertyValue(2,SP_GENIVI_BASS,oldvalue)); + ASSERT_EQ(source.listSoundProperties[0].value, oldvalue); + + //lets send the answer and expect a call on the controlInterface + EXPECT_CALL(pMockControlInterface,cbAckSetSourceSoundProperty(_,E_OK)).Times(1); + pRoutingReceiver.ackSetSourceSoundProperty(handle, E_OK); + + //finally, the new value must be in the database + ASSERT_EQ(E_OK, pDatabaseHandler.getSourceSoundPropertyValue(sourceID,SP_GENIVI_BASS,oldvalue)); + ASSERT_EQ(soundProperty.value, oldvalue); + + //and the handle must be destroyed + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_TRUE(handlesList.empty()); + + //Now we try again, but the value is unchanged + //ASSERT_EQ(E_NO_CHANGE, pControlReceiver.setSourceSoundProperty(handle,source.sourceID,soundProperty)); + //needed to be removed because logic changed here +} + +TEST_F(CAmControlInterfaceTest,crossFading) +{ + //todo: implement crossfading test +} + +TEST_F(CAmControlInterfaceTest,resyncConnectionsTest) +{ + am_Domain_s domain; + am_domainID_t domainID; + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + + //prepare the scene + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + + std::vector<am_Connection_s> listConnections; + + EXPECT_CALL(pMockRoutingInterface,resyncConnectionState(domainID,_)).WillOnce(DoAll(returnResyncConnection(), Return(E_OK))); + ASSERT_EQ(am_Error_e::E_OK,pControlReceiver.resyncConnectionState(domainID,listConnections)); + ASSERT_EQ(listConnections[0].sinkID,1); + ASSERT_EQ(listConnections[0].sourceID,1); + ASSERT_EQ(listConnections[0].connectionFormat,CF_GENIVI_ANALOG); +} + +TEST_F(CAmControlInterfaceTest,ackConnectNotPossible) +{ + am_connectionID_t connectionID; + am_Sink_s sink; + am_sinkID_t sinkID; + am_Domain_s domain; + am_domainID_t domainID; + std::vector<am_Connection_s> connectionList; + std::vector<am_Handle_s> handlesList; + am_Handle_s handle; + pCF.createSink(sink); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + sink.sinkID = 2; + sink.domainID = DYNAMIC_ID_BOUNDARY; + + //prepare the stage + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + //when asyncConnect is called, we expect a call on the routingInterface + EXPECT_CALL(pMockRoutingInterface,asyncConnect(_,1,2,2,CF_GENIVI_STEREO)).WillOnce(Return(E_COMMUNICATION)); + ASSERT_EQ(E_COMMUNICATION, pControlReceiver.connect(handle,connectionID,CF_GENIVI_STEREO,2,2)); + + //The list of handles shall be empty + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_TRUE(handlesList.empty()); + + + ASSERT_EQ(E_OK, pDatabaseHandler.getListConnections(connectionList)); + ASSERT_TRUE(connectionList.empty()); + +} + +int main(int argc, char **argv) +{ + try + { + TCLAP::CmdLine* cmd(CAmCommandLineSingleton::instanciateOnce("The team of the AudioManager wishes you a nice day!",' ',DAEMONVERSION,true)); + cmd->add(enableNoDLTDebug); + } + catch (TCLAP::ArgException &e) // catch any exceptions + { std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; } + CAmCommandLineSingleton::instance()->preparse(argc,argv); + CAmDltWrapper::instance(enableNoDLTDebug.getValue())->registerApp("AudioManagerDeamon", "AudioManagerDeamon"); + CAmDltWrapper::instance()->registerContext(AudioManager, "Main", "Main Context"); + logInfo("RoutingSendInterface Test started"); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/AudioManagerCore/test/AmControlInterfaceTest/CAmControlInterfaceTest.h b/AudioManagerCore/test/AmControlInterfaceTest/CAmControlInterfaceTest.h new file mode 100644 index 0000000..b7fa27a --- /dev/null +++ b/AudioManagerCore/test/AmControlInterfaceTest/CAmControlInterfaceTest.h @@ -0,0 +1,76 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#ifndef ROUTINGINTERFACETEST_H_ +#define ROUTINGINTERFACETEST_H_ + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +//#include "CAmDatabaseHandlerSQLite.h" +#include "CAmDatabaseHandlerMap.h" +#include "CAmControlReceiver.h" +#include "CAmRoutingReceiver.h" +#include "CAmDatabaseObserver.h" +#include "CAmControlSender.h" +#include "CAmRoutingSender.h" +#include "CAmRouter.h" +#include "../IAmRoutingBackdoor.h" +#include "../IAmCommandBackdoor.h" +#include "../IAmControlBackdoor.h" +#include "../CAmCommonFunctions.h" +#include "../MockIAmRoutingSend.h" +#include "../MockIAmControlSend.h" +#include "CAmSocketHandler.h" + +namespace am +{ + +class CAmControlInterfaceTest: public ::testing::Test +{ +public: + CAmControlInterfaceTest(); + ~CAmControlInterfaceTest(); + CAmSocketHandler pSocketHandler; + std::vector<std::string> plistCommandPluginDirs; + std::vector<std::string> plistRoutingPluginDirs; + CAmDatabaseHandlerMap pDatabaseHandler; + CAmRoutingSender pRoutingSender; + CAmCommandSender pCommandSender; + MockIAmControlSend pMockControlInterface; + MockIAmRoutingSend pMockRoutingInterface; + IAmRoutingBackdoor pRoutingInterfaceBackdoor; + IAmCommandBackdoor pCommandInterfaceBackdoor; + IAmControlBackdoor pControlInterfaceBackdoor; + CAmControlSender pControlSender; + CAmRouter pRouter; + CAmDatabaseObserver pDatabaseObserver; + CAmControlReceiver pControlReceiver; + CAmRoutingReceiver pRoutingReceiver; + CAmCommonFunctions pCF; + void SetUp(); + void TearDown(); +}; + +} + +#endif /* ROUTINGINTERFACETEST_H_ */ diff --git a/AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt b/AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt new file mode 100644 index 0000000..4f33ac5 --- /dev/null +++ b/AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt @@ -0,0 +1,52 @@ +# 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 +# +# For further information see http://www.genivi.org/. +# + +cmake_minimum_required(VERSION 3.0) + +project(AmControlInterfaceTest LANGUAGES CXX VERSION ${DAEMONVERSION}) + +INCLUDE_DIRECTORIES( + ${AUDIOMANAGER_CORE_INCLUDE} + ${GMOCK_INCLUDE_DIRS} + ${GTEST_INCLUDE_DIRS}) + + + file(GLOB CONTROL_INTERFACE_SRCS_CXX + "../CAmCommonFunctions.cpp" + "*.cpp" +) + +add_executable(AmControlInterfaceTest ${CONTROL_INTERFACE_SRCS_CXX}) + +TARGET_LINK_LIBRARIES(AmControlInterfaceTest + ${GTEST_LIBRARIES} + ${GMOCK_LIBRARIES} + AudioManagerCore +) + +add_test(AmControlInterfaceTest AmControlInterfaceTest) + +ADD_DEPENDENCIES(AmControlInterfaceTest AudioManagerCore) + +INSTALL(TARGETS AmControlInterfaceTest + DESTINATION ${TEST_EXECUTABLE_INSTALL_PATH} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + COMPONENT tests) + + + + diff --git a/AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt~ b/AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt~ new file mode 100644 index 0000000..5b71a59 --- /dev/null +++ b/AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt~ @@ -0,0 +1,50 @@ +# 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 +# +# For further information see http://www.genivi.org/. +# + +cmake_minimum_required(VERSION 3.0) + +project(AmControlInterfaceTest LANGUAGES CXX VERSION ${DAEMONVERSION}) + +INCLUDE_DIRECTORIES( + ${AUDIOMANAGER_CORE_INCLUDE} + ${GMOCK_INCLUDE_DIRS} + ${GTEST_INCLUDE_DIRS}) + + + file(GLOB CONTROL_INTERFACE_SRCS_CXX + "../CAmCommonFunctions.cpp" + "*.cpp" +) + +add_executable(AmControlInterfaceTest ${CONTROL_INTERFACE_SRCS_CXX}) + +TARGET_LINK_LIBRARIES(AmControlInterfaceTest + ${GTEST_LIBRARIES} + ${GMOCK_LIBRARIES} + AudioManagerCore +) + +ADD_DEPENDENCIES(AmControlInterfaceTest AudioManagerCore) + +INSTALL(TARGETS AmControlInterfaceTest + DESTINATION ${TEST_EXECUTABLE_INSTALL_PATH} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + COMPONENT tests) + + + + diff --git a/AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.cpp b/AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.cpp new file mode 100644 index 0000000..337ecb7 --- /dev/null +++ b/AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.cpp @@ -0,0 +1,3276 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmMapHandlerTest.h" +#include <algorithm> +#include <string> +#include <vector> +#include <set> +#include <ios> +#include "CAmDltWrapper.h" +#include "CAmCommandLineSingleton.h" + +using namespace am; +using namespace testing; + + +extern bool equalMainSoundProperty(const am_MainSoundProperty_s a, const am_MainSoundProperty_s b); +extern bool equalNotificationConfiguration(const am_NotificationConfiguration_s a, const am_NotificationConfiguration_s b); +extern bool equalClassProperties(const am_ClassProperty_s a, const am_ClassProperty_s b); +extern std::string int2string(int i); + +int16_t const TEST_MAX_CONNECTION_ID = 20; +int16_t const TEST_MAX_MAINCONNECTION_ID = 20; +int16_t const TEST_MAX_SINK_ID = 40; + +TCLAP::SwitchArg enableNoDLTDebug ("V","logDlt","print DLT logs to stdout or dlt-daemon default off",false); + + +CAmMapBasicTest::CAmMapBasicTest() : + plistRoutingPluginDirs(), // + plistCommandPluginDirs(), // + pSocketHandler(),// + pDatabaseHandler(), // + pRoutingSender(plistRoutingPluginDirs), // + pCommandSender(plistCommandPluginDirs), // + pRoutingInterfaceBackdoor(), // + pCommandInterfaceBackdoor(), // + pControlSender(), // + pRouter(&pDatabaseHandler, &pControlSender), // + pControlReceiver(&pDatabaseHandler, &pRoutingSender, &pCommandSender, &pSocketHandler, &pRouter), // + pCF() +{ +} + +CAmMapBasicTest::~CAmMapBasicTest() +{ +} + +void CAmMapBasicTest::createMainConnectionSetup(am_mainConnectionID_t & mainConnectionID, am_MainConnection_s & mainConnection) +{ + //fill the connection database + am_Connection_s connection; + am_Source_s source; + am_Sink_s sink; + std::vector<am_connectionID_t> connectionList; + + //we create 9 sources and sinks: + + for (uint16_t i = 1; i < 10; i++) + { + am_sinkID_t forgetSink; + am_sourceID_t forgetSource; + am_connectionID_t connectionID; + + pCF.createSink(sink); + sink.sinkID = i; + sink.name = "sink" + int2string(i); + sink.domainID = 4; + pCF.createSource(source); + source.sourceID = i; + source.name = "source" + int2string(i); + source.domainID = 4; + + connection.sinkID = i; + connection.sourceID = i; + connection.delay = -1; + connection.connectionFormat = CF_GENIVI_ANALOG; + connection.connectionID = 0; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,forgetSink)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,forgetSource)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterConnectionDB(connection,connectionID)); + ASSERT_EQ(E_OK, pDatabaseHandler.changeConnectionFinal(connectionID)); + connectionList.push_back(connectionID); + } + + //create a mainConnection + std::vector<am_MainConnection_s> mainConnectionList; + mainConnection.listConnectionID = connectionList; + mainConnection.mainConnectionID = 0; + mainConnection.sinkID = 1; + mainConnection.sourceID = 1; + mainConnection.connectionState = CS_CONNECTED; + mainConnection.delay = -1; + + //enter mainconnection in database + ASSERT_EQ(E_OK, pDatabaseHandler.enterMainConnectionDB(mainConnection,mainConnectionID)); + ASSERT_NE(0, mainConnectionID); + + //read out the mainconnections and check if they are equal to the data written. + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainConnections(mainConnectionList)); + std::vector<am_MainConnection_s>::iterator listIterator = mainConnectionList.begin(); + for (; listIterator < mainConnectionList.end(); ++listIterator) + { + if (listIterator->mainConnectionID == mainConnectionID) + { + ASSERT_EQ(listIterator->connectionState, mainConnection.connectionState); + ASSERT_EQ(listIterator->sinkID, mainConnection.sinkID); + ASSERT_EQ(listIterator->sourceID, mainConnection.sourceID); + ASSERT_EQ(listIterator->delay, mainConnection.delay); + ASSERT_TRUE(std::equal(listIterator->listConnectionID.begin(), listIterator->listConnectionID.end(), connectionList.begin())); + } + } +} + +void CAmMapBasicTest::SetUp() +{ + ::testing::FLAGS_gmock_verbose = "error"; +} + +void CAmMapBasicTest::TearDown() +{ + ::testing::FLAGS_gmock_verbose = "warning"; +} + + + +CAmMapHandlerTest::CAmMapHandlerTest() : + pMockInterface(), // + pObserver(&pCommandSender,&pRoutingSender, &pSocketHandler) +{ + pDatabaseHandler.registerObserver(&pObserver); + pDatabaseHandler.setConnectionIDRange(1, TEST_MAX_CONNECTION_ID); + pDatabaseHandler.setMainConnectionIDRange(1, TEST_MAX_MAINCONNECTION_ID); + pDatabaseHandler.setSinkIDRange(DYNAMIC_ID_BOUNDARY, DYNAMIC_ID_BOUNDARY+TEST_MAX_SINK_ID); + pCommandInterfaceBackdoor.injectInterface(&pCommandSender, &pMockInterface); +} + +CAmMapHandlerTest::~CAmMapHandlerTest() +{ +} + +TEST_F(CAmMapHandlerTest,getMainConnectionInfo) +{ + am_mainConnectionID_t mainConnectionID; + am_MainConnection_s mainConnection, mainConnectionT; + createMainConnectionSetup(mainConnectionID, mainConnection); + + ASSERT_EQ(E_OK, pDatabaseHandler.getMainConnectionInfoDB(mainConnectionID,mainConnectionT)); + ASSERT_TRUE(mainConnection.connectionState == mainConnectionT.connectionState); + ASSERT_TRUE(mainConnection.delay == mainConnectionT.delay); + ASSERT_TRUE(std::equal(mainConnection.listConnectionID.begin(),mainConnection.listConnectionID.end(),mainConnectionT.listConnectionID.begin())); + ASSERT_TRUE(mainConnection.sinkID == mainConnectionT.sinkID); + ASSERT_TRUE(mainConnection.sourceID == mainConnectionT.sourceID); + ASSERT_TRUE(mainConnectionID == mainConnectionT.mainConnectionID); +} + +TEST_F(CAmMapHandlerTest,getSinkInfo) +{ + //fill the connection database + am_Sink_s staticSink, firstDynamicSink, secondDynamicSink; + am_sinkID_t staticSinkID, firstDynamicSinkID, secondDynamicSinkID; + std::vector<am_Sink_s> sinkList; + + pCF.createSink(staticSink); + staticSink.sinkID = 4; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(staticSink,staticSinkID)) + << "ERROR: database error"; + ASSERT_EQ(staticSink.sinkID,staticSinkID) + << "ERROR: ID not the one given in staticSink"; + + pCF.createSink(firstDynamicSink); + firstDynamicSink.name = "firstdynamic"; + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(firstDynamicSink,firstDynamicSinkID)) + << "ERROR: database error"; + ASSERT_EQ(firstDynamicSinkID,DYNAMIC_ID_BOUNDARY) + << "ERROR: ID not the one given in firstDynamicSink"; + + pCF.createSink(secondDynamicSink); + secondDynamicSink.name = "seconddynamic"; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(secondDynamicSink,secondDynamicSinkID)) + << "ERROR: database error"; + ASSERT_NEAR(secondDynamicSinkID,DYNAMIC_ID_BOUNDARY,10) + << "ERROR: ID not the one given in secondDynamicSink"; + + //now read back and check the returns agains the given values + ASSERT_EQ(E_OK,pDatabaseHandler.getListSinks(sinkList)) + << "ERROR: database error"; + + std::vector<am_Sink_s>::iterator listIterator = sinkList.begin(); + for (; listIterator < sinkList.end(); ++listIterator) + { + if (listIterator->sinkID == staticSinkID) + { + ASSERT_TRUE(pCF.compareSink(listIterator, staticSink)); + } + + if (listIterator->sinkID == firstDynamicSinkID) + { + ASSERT_TRUE(pCF.compareSink(listIterator, firstDynamicSink)); + } + + if (listIterator->sinkID == secondDynamicSinkID) + { + ASSERT_TRUE(pCF.compareSink(listIterator, secondDynamicSink)); + } + } + + am_Sink_s sinkData; + ASSERT_EQ(E_OK, pDatabaseHandler.getSinkInfoDB(secondDynamicSinkID,sinkData)); + ASSERT_EQ(secondDynamicSink.available.availability, sinkData.available.availability); + ASSERT_EQ(secondDynamicSink.available.availabilityReason, sinkData.available.availabilityReason); + ASSERT_EQ(secondDynamicSink.sinkClassID, sinkData.sinkClassID); + ASSERT_EQ(secondDynamicSink.domainID, sinkData.domainID); + ASSERT_EQ(secondDynamicSink.visible, sinkData.visible); + ASSERT_EQ(0, secondDynamicSink.name.compare(sinkData.name)); + ASSERT_EQ(secondDynamicSink.volume, sinkData.volume); + ASSERT_TRUE(std::equal(secondDynamicSink.listConnectionFormats.begin(), secondDynamicSink.listConnectionFormats.end(), sinkData.listConnectionFormats.begin())); + ASSERT_TRUE(std::equal(secondDynamicSink.listMainSoundProperties.begin(), secondDynamicSink.listMainSoundProperties.end(), sinkData.listMainSoundProperties.begin(), equalMainSoundProperty)); + ASSERT_TRUE(std::equal(secondDynamicSink.listNotificationConfigurations.begin(), secondDynamicSink.listNotificationConfigurations.end(), sinkData.listNotificationConfigurations.begin(), equalNotificationConfiguration)); + ASSERT_TRUE(std::equal(secondDynamicSink.listMainNotificationConfigurations.begin(), secondDynamicSink.listMainNotificationConfigurations.end(), sinkData.listMainNotificationConfigurations.begin(), equalNotificationConfiguration)); +} + +TEST_F(CAmMapHandlerTest,getSourceInfo) +{ + //fill the connection database + am_Source_s staticSource, firstDynamicSource, secondDynamicSource; + am_sourceID_t staticSourceID, firstDynamicSourceID, secondDynamicSourceID; + std::vector<am_Source_s> sourceList; + + pCF.createSource(staticSource); + staticSource.sourceID = 4; + staticSource.name = "Static"; + + + ASSERT_EQ(E_OK,pDatabaseHandler.enterSourceDB(staticSource,staticSourceID)) + << "ERROR: database error"; + ASSERT_EQ(staticSource.sourceID,staticSourceID) + << "ERROR: ID not the one given in staticSource"; + + pCF.createSource(firstDynamicSource); + firstDynamicSource.name = "firstDynamicSource"; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterSourceDB(firstDynamicSource,firstDynamicSourceID)) + << "ERROR: database error"; + ASSERT_EQ(firstDynamicSourceID,DYNAMIC_ID_BOUNDARY) + << "ERROR: ID not the one given in firstDynamicSink"; + + + pCF.createSource(secondDynamicSource); + secondDynamicSource.name = "secondDynamicSource"; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterSourceDB(secondDynamicSource,secondDynamicSourceID)) + << "ERROR: database error"; + ASSERT_NEAR(secondDynamicSourceID,DYNAMIC_ID_BOUNDARY,10) + << "ERROR: ID not the one given in secondDynamicSink"; + + //now read back and check the returns agains the given values + ASSERT_EQ(E_OK,pDatabaseHandler.getListSources(sourceList)) + << "ERROR: database error"; + + std::vector<am_Source_s>::iterator listIterator = sourceList.begin(); + for (; listIterator < sourceList.end(); ++listIterator) + { + if (listIterator->sourceID == staticSourceID) + { + ASSERT_TRUE(pCF.compareSource(listIterator, staticSource)); + } + + if (listIterator->sourceID == firstDynamicSourceID) + { + ASSERT_TRUE(pCF.compareSource(listIterator, firstDynamicSource)); + } + + if (listIterator->sourceID == secondDynamicSourceID) + { + ASSERT_TRUE(pCF.compareSource(listIterator, secondDynamicSource)); + } + } + + am_Source_s sourceData; + ASSERT_EQ(E_OK, pDatabaseHandler.getSourceInfoDB(secondDynamicSourceID,sourceData)); + ASSERT_EQ(secondDynamicSource.available.availability, sourceData.available.availability); + ASSERT_EQ(secondDynamicSource.available.availabilityReason, sourceData.available.availabilityReason); + ASSERT_EQ(secondDynamicSource.sourceClassID, sourceData.sourceClassID); + ASSERT_EQ(secondDynamicSource.domainID, sourceData.domainID); + ASSERT_EQ(secondDynamicSource.interruptState, sourceData.interruptState); + ASSERT_EQ(secondDynamicSource.visible, sourceData.visible); + ASSERT_EQ(0, secondDynamicSource.name.compare(sourceData.name)); + ASSERT_EQ(secondDynamicSource.volume, sourceData.volume); + ASSERT_TRUE(std::equal(secondDynamicSource.listConnectionFormats.begin(), secondDynamicSource.listConnectionFormats.end(), sourceData.listConnectionFormats.begin())); + ASSERT_TRUE(std::equal(secondDynamicSource.listMainSoundProperties.begin(), secondDynamicSource.listMainSoundProperties.end(), sourceData.listMainSoundProperties.begin(), equalMainSoundProperty)); + ASSERT_TRUE(std::equal(secondDynamicSource.listMainNotificationConfigurations.begin(), secondDynamicSource.listMainNotificationConfigurations.end(), sourceData.listMainNotificationConfigurations.begin(), equalNotificationConfiguration)); + ASSERT_TRUE(std::equal(secondDynamicSource.listNotificationConfigurations.begin(), secondDynamicSource.listNotificationConfigurations.end(), sourceData.listNotificationConfigurations.begin(), equalNotificationConfiguration)); +} + +TEST_F(CAmMapHandlerTest, peekSourceID) +{ + + std::string sourceName("myClassID"); + am_sourceClass_t sourceClassID, peekID; + am_SourceClass_s sourceClass; + am_ClassProperty_s classProperty; + classProperty.classProperty = CP_GENIVI_SOURCE_TYPE; + classProperty.value = 13; + sourceClass.name = sourceName; + sourceClass.sourceClassID = 0; + sourceClass.listClassProperties.push_back(classProperty); + + //first we peek without an existing class + ASSERT_EQ(E_NON_EXISTENT, pDatabaseHandler.peekSourceClassID(sourceName,sourceClassID)); + + //now we enter the class into the database + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceClassDB(sourceClassID,sourceClass)); + + //first we peek without an existing class + ASSERT_EQ(E_OK, pDatabaseHandler.peekSourceClassID(sourceName,peekID)); + ASSERT_EQ(sourceClassID, peekID); +} + +TEST_F(CAmMapHandlerTest, peekSinkID) +{ + + std::string sinkName("myClassID"); + am_sinkClass_t sinkClassID, peekID; + am_SinkClass_s sinkClass; + am_ClassProperty_s classProperty; + classProperty.classProperty = CP_GENIVI_SOURCE_TYPE; + classProperty.value = 13; + sinkClass.name = sinkName; + sinkClass.sinkClassID = 0; + sinkClass.listClassProperties.push_back(classProperty); + + //first we peek without an existing class + ASSERT_EQ(E_NON_EXISTENT, pDatabaseHandler.peekSinkClassID(sinkName,sinkClassID)); + + //now we enter the class into the database + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkClassDB(sinkClass,sinkClassID)); + + //first we peek without an existing class + ASSERT_EQ(E_OK, pDatabaseHandler.peekSinkClassID(sinkName,peekID)); + ASSERT_EQ(sinkClassID, peekID); +} + +TEST_F(CAmMapHandlerTest,crossfaders) +{ + am_Crossfader_s crossfader; + am_crossfaderID_t crossfaderID; + am_Sink_s sinkA, sinkB; + am_Source_s source; + am_sourceID_t sourceID; + am_sinkID_t sinkAID, sinkBID; + pCF.createSink(sinkA); + pCF.createSink(sinkB); + sinkB.name = "sinkB"; + pCF.createSource(source); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sinkA,sinkAID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sinkB,sinkBID)); + + crossfader.crossfaderID = 0; + crossfader.hotSink = HS_SINKA; + crossfader.sinkID_A = sinkAID; + crossfader.sinkID_B = sinkBID; + crossfader.sourceID = sourceID; + crossfader.name = "Crossfader"; + crossfader.hotSink = HS_UNKNOWN; + + std::vector<am_Crossfader_s> listCrossfaders; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterCrossfaderDB(crossfader,crossfaderID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListCrossfaders(listCrossfaders)); + ASSERT_EQ(crossfader.sinkID_A, listCrossfaders[0].sinkID_A); + ASSERT_EQ(crossfader.sinkID_B, listCrossfaders[0].sinkID_B); + ASSERT_EQ(crossfader.sourceID, listCrossfaders[0].sourceID); + ASSERT_EQ(crossfader.hotSink, listCrossfaders[0].hotSink); + ASSERT_EQ(DYNAMIC_ID_BOUNDARY, listCrossfaders[0].crossfaderID); + ASSERT_EQ(crossfader.name.compare(listCrossfaders[0].name), 0); +} + +TEST_F(CAmMapHandlerTest,crossfadersGetFromDomain) +{ + + + + am_Crossfader_s crossfader; + am_crossfaderID_t crossfaderID; + am_Sink_s sinkA, sinkB; + am_Source_s source; + am_sourceID_t sourceID; + am_sinkID_t sinkAID, sinkBID; + am_domainID_t domainID; + am_Domain_s domain; + pCF.createSink(sinkA); + pCF.createSink(sinkB); + pCF.createDomain(domain); + sinkB.name = "sinkB"; + pCF.createSource(source); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + source.domainID = domainID; + sinkA.domainID = domainID; + sinkB.domainID = domainID; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sinkA,sinkAID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sinkB,sinkBID)); + + crossfader.crossfaderID = 0; + crossfader.hotSink = HS_SINKA; + crossfader.sinkID_A = sinkAID; + crossfader.sinkID_B = sinkBID; + crossfader.sourceID = sourceID; + crossfader.name = "Crossfader"; + crossfader.hotSink = HS_UNKNOWN; + + std::vector<am_crossfaderID_t> listCrossfaders; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterCrossfaderDB(crossfader,crossfaderID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListCrossfadersOfDomain(source.domainID,listCrossfaders)); + ASSERT_EQ(DYNAMIC_ID_BOUNDARY, listCrossfaders[0]); + +} + +TEST_F(CAmMapHandlerTest,sourceState) +{ + am_Source_s source; + am_sourceID_t sourceID; + std::vector<am_Source_s> listSources; + pCF.createSource(source); + source.sourceState = SS_OFF; + + //prepare the test + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + + //change the source state + ASSERT_EQ(E_OK, pDatabaseHandler.changeSourceState(sourceID,SS_ON)); + + //read out the changed values + ASSERT_EQ(E_OK, pDatabaseHandler.getListSources(listSources)); + ASSERT_EQ(listSources[0].sourceState, SS_ON); +} + +TEST_F(CAmMapHandlerTest,sinkVolumeChange) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + std::vector<am_Sink_s> listSinks; + pCF.createSink(sink); + sink.volume = 23; + + //prepare the test + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + //change the volume and check the read out + ASSERT_EQ(E_OK, pDatabaseHandler.changeSinkVolume(sinkID,34)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + ASSERT_EQ(listSinks[0].volume, 34); +} + +TEST_F(CAmMapHandlerTest,sourceVolumeChange) +{ + am_Source_s source; + am_sourceID_t sourceID; + std::vector<am_Source_s> listSources; + pCF.createSource(source); + source.volume = 23; + + //prepare test + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + + //change the volume and check the read out + ASSERT_EQ(E_OK, pDatabaseHandler.changeSourceVolume(sourceID,34)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSources(listSources)); + ASSERT_EQ(listSources[0].volume, 34); +} + +TEST_F(CAmMapHandlerTest, peekSource) +{ + std::vector<am_SourceType_s> listSourceTypes; + std::vector<am_Source_s> listSources; + am_sourceID_t sourceID, source2ID, source3ID; + am_Source_s source; + pCF.createSource(source); + + //peek a source that does not exits + + ASSERT_EQ(E_OK, pDatabaseHandler.peekSource(std::string("newsource"),sourceID)); + + //make sure it is not in the list + ASSERT_EQ(E_OK, pDatabaseHandler.getListSources(listSources)); + ASSERT_TRUE(listSources.empty()); + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainSources(listSourceTypes)); + ASSERT_TRUE(listSourceTypes.empty()); + ASSERT_EQ(sourceID, DYNAMIC_ID_BOUNDARY); + + //now enter the source with the same name and make sure it does not get a new ID + source.name = "newsource"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,source2ID)); + + ASSERT_EQ(E_OK, pDatabaseHandler.getListSources(listSources)); + ASSERT_EQ(sourceID, source2ID); + ASSERT_FALSE(listSources.empty()); + ASSERT_TRUE(listSources.at(0).sourceID==sourceID); + + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainSources(listSourceTypes)); + ASSERT_FALSE(listSourceTypes.empty()); + ASSERT_TRUE(listSourceTypes.at(0).sourceID==sourceID); + + //now we peek again. This time, the source exists + ASSERT_EQ(E_OK, pDatabaseHandler.peekSource(source.name,source3ID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSources(listSources)); + ASSERT_TRUE(listSources.size()==1); + + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainSources(listSourceTypes)); + ASSERT_TRUE(listSourceTypes.size()==1); + ASSERT_TRUE(listSourceTypes.at(0).sourceID==source3ID); + ASSERT_EQ(source3ID, source2ID); +} + +TEST_F(CAmMapHandlerTest, peekSourceDouble) +{ + std::vector<am_SourceType_s> listSourceTypes; + std::vector<am_Source_s> listSources; + am_sourceID_t sourceID; + am_sourceID_t source2ID; + am_sourceID_t source3ID; + am_Source_s source; + pCF.createSource(source); + + //peek a source that does not exits + + ASSERT_EQ(E_OK, pDatabaseHandler.peekSource(std::string("newsource"),sourceID)); + + //peek a second source that does not exits + + ASSERT_EQ(E_OK, pDatabaseHandler.peekSource(std::string("newsource2"),source2ID)); + + //make sure they are is not in the list + ASSERT_EQ(E_OK, pDatabaseHandler.getListSources(listSources)); + ASSERT_TRUE(listSources.empty()); + ASSERT_EQ(sourceID, DYNAMIC_ID_BOUNDARY); + source.name = "newsource"; + + //now enter the source with the same name than the first peek and make sure it does not get a new ID + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,source3ID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSources(listSources)); + ASSERT_EQ(sourceID, source3ID); + ASSERT_TRUE(listSources.size()==1); + ASSERT_TRUE(listSources[0].sourceID==sourceID); + + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainSources(listSourceTypes)); + ASSERT_TRUE(listSourceTypes.size()==1); + ASSERT_TRUE(listSourceTypes[0].sourceID==source3ID); +} + +TEST_F(CAmMapHandlerTest, peekSink) +{ + std::vector<am_SinkType_s> listSinkTypes; + std::vector<am_Sink_s> listSinks; + am_sinkID_t sinkID, sink2ID, sink3ID; + am_Sink_s sink; + pCF.createSink(sink); + + //peek a sink that does not exits + + ASSERT_EQ(E_OK, pDatabaseHandler.peekSink(std::string("newsink"),sinkID)); + + //make sure it is not in the list + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + ASSERT_TRUE(listSinks.empty()); + ASSERT_EQ(sinkID, DYNAMIC_ID_BOUNDARY); + sink.name = "newsink"; + + //now enter the source with the same name and make sure it does not get a new ID + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sink2ID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + ASSERT_EQ(sinkID, sink2ID); + ASSERT_TRUE(listSinks[0].sinkID==sinkID); + + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainSinks(listSinkTypes)); + ASSERT_FALSE(listSinkTypes.empty()); + ASSERT_TRUE(listSinkTypes.at(0).sinkID==sinkID); + + //now we peek again, this time, the sink exists + ASSERT_EQ(E_OK, pDatabaseHandler.peekSink(sink.name,sink3ID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + ASSERT_TRUE(listSinks.size()==1); + ASSERT_EQ(sink3ID, sink2ID); + + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainSinks(listSinkTypes)); + ASSERT_TRUE(listSinkTypes.size()==1); + ASSERT_TRUE(listSinkTypes.at(0).sinkID==sink3ID); +} + +TEST_F(CAmMapHandlerTest, peekSinkDouble) +{ + std::vector<am_SinkType_s> listSinkTypes; + std::vector<am_Sink_s> listSinks; + am_sinkID_t sinkID; + am_sinkID_t sink2ID; + am_sinkID_t sink3ID; + am_Sink_s sink; + pCF.createSink(sink); + + //peek a sink that does not exits + + ASSERT_EQ(E_OK, pDatabaseHandler.peekSink(std::string("newsink"),sinkID)); + + //peek again + + ASSERT_EQ(E_OK, pDatabaseHandler.peekSink(std::string("nextsink"),sink2ID)); + + //make sure they are is not in the list + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + ASSERT_TRUE(listSinks.empty()); + ASSERT_EQ(sinkID, DYNAMIC_ID_BOUNDARY); + sink.name = "newsink"; + + //now enter the sink with the same name than the first peek and make sure it does not get a new ID + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sink3ID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + ASSERT_EQ(sinkID, sink3ID); + ASSERT_TRUE(listSinks[0].sinkID==sinkID); + + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainSinks(listSinkTypes)); + ASSERT_TRUE(listSinkTypes.size()==1); + ASSERT_TRUE(listSinkTypes[0].sinkID==sink3ID); +} + +TEST_F(CAmMapHandlerTest,changeConnectionTimingInformationCheckMainConnection) +{ + am_mainConnectionID_t mainConnectionID; + am_MainConnection_s mainConnection; + std::vector<am_Connection_s> connectionList; + std::vector<am_MainConnectionType_s> mainList; + + //prepare the test, it is one mainconnection, so we expect one callback + createMainConnectionSetup(mainConnectionID, mainConnection); + + //first get all visible mainconnections and make sure, the delay is set to -1 for the first entry + ASSERT_EQ(E_OK, pDatabaseHandler.getListVisibleMainConnections(mainList)); + ASSERT_EQ(mainList[0].delay, -1); + + //no go through all connections and set the delay time to 24 for each connection + ASSERT_EQ(E_OK, pDatabaseHandler.getListConnections(connectionList)); + std::vector<am_Connection_s>::iterator iteratorConnectionList = connectionList.begin(); + for (; iteratorConnectionList < connectionList.end(); ++iteratorConnectionList) + { + ASSERT_EQ(E_OK, pDatabaseHandler.changeConnectionTimingInformation(iteratorConnectionList->connectionID,24)); + } + + //we read the result again and expect that the value is now different from -1 + ASSERT_EQ(E_OK, pDatabaseHandler.getListVisibleMainConnections(mainList)); + ASSERT_EQ(mainList[0].delay, 216); +} + +TEST_F(CAmMapHandlerTest,changeConnectionTimingInformation) +{ + am_Connection_s connection; + am_connectionID_t connectionID; + std::vector<am_Connection_s> connectionList; + pCF.createConnection(connection); + + //enter a connection + ASSERT_EQ(E_OK, pDatabaseHandler.enterConnectionDB(connection,connectionID)); + ASSERT_EQ(E_OK, pDatabaseHandler.changeConnectionFinal(connectionID)); + + //change the timing and check it + ASSERT_EQ(E_OK, pDatabaseHandler.changeConnectionTimingInformation(connectionID, 24)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListConnections(connectionList)); + ASSERT_TRUE(connectionList[0].delay == 24); +} + +TEST_F(CAmMapHandlerTest,getSinkClassOfSink) +{ + std::vector<am_SinkClass_s> sinkClassList; + std::vector<am_ClassProperty_s> classPropertyList; + am_SinkClass_s sinkClass, returnClass; + am_ClassProperty_s classProperty; + am_sinkClass_t sinkClassID; + am_Sink_s sink; + am_sinkID_t sinkID; + classProperty.classProperty = CP_GENIVI_SINK_TYPE; + classProperty.value = 1; + classPropertyList.push_back(classProperty); + classProperty.classProperty = CP_GENIVI_SOURCE_TYPE; + classProperty.value = 4; + classPropertyList.push_back(classProperty); + sinkClass.name = "test"; + sinkClass.sinkClassID = 4; + sinkClass.listClassProperties = classPropertyList; + pCF.createSink(sink); + sink.sinkClassID = 4; + + //prepare test + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + //enter a new sinkclass, read out again and check + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkClassDB(sinkClass,sinkClassID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinkClasses(sinkClassList)); + ASSERT_EQ(sinkClassList[0].name, sinkClass.name); + ASSERT_EQ(sinkClassList[0].sinkClassID, 4); + ASSERT_TRUE(std::equal(sinkClassList[0].listClassProperties.begin(),sinkClassList[0].listClassProperties.end(),classPropertyList.begin(),equalClassProperties)); + + ASSERT_EQ(E_OK, pDatabaseHandler.getSinkClassInfoDB(sinkID,returnClass)); + ASSERT_EQ(sinkClassList[0].name, returnClass.name); + ASSERT_EQ(sinkClassList[0].sinkClassID, returnClass.sinkClassID); + ASSERT_TRUE(std::equal(sinkClassList[0].listClassProperties.begin(),sinkClassList[0].listClassProperties.end(),returnClass.listClassProperties.begin(),equalClassProperties)); +} + +TEST_F(CAmMapHandlerTest,getSourceClassOfSource) +{ + std::vector<am_SourceClass_s> sourceClassList; + std::vector<am_ClassProperty_s> classPropertyList; + am_SourceClass_s sourceClass, sinkSourceClass; + am_ClassProperty_s classProperty; + am_sourceClass_t sourceClassID; + am_Source_s source; + am_sourceID_t sourceID; + classProperty.classProperty = CP_GENIVI_SINK_TYPE; + classProperty.value = 1; + classPropertyList.push_back(classProperty); + classProperty.classProperty = CP_GENIVI_SOURCE_TYPE; + classProperty.value = 4; + classPropertyList.push_back(classProperty); + sourceClass.name = "test"; + sourceClass.sourceClassID = 1; + sourceClass.listClassProperties = classPropertyList; + pCF.createSource(source); + + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceClassDB(sourceClassID,sourceClass)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSourceClasses(sourceClassList)); + ASSERT_EQ(sourceClassList[0].name, sourceClass.name); + ASSERT_EQ(sourceClassList[0].sourceClassID, 1); + ASSERT_TRUE(std::equal(sourceClassList[0].listClassProperties.begin(),sourceClassList[0].listClassProperties.end(),classPropertyList.begin(),equalClassProperties)); + ASSERT_EQ(E_OK, pDatabaseHandler.getSourceClassInfoDB(sourceID,sinkSourceClass)); + ASSERT_EQ(sourceClassList[0].name, sinkSourceClass.name); + ASSERT_EQ(sourceClassList[0].sourceClassID, sinkSourceClass.sourceClassID); + ASSERT_TRUE(std::equal(sourceClassList[0].listClassProperties.begin(),sourceClassList[0].listClassProperties.end(),sinkSourceClass.listClassProperties.begin(),equalClassProperties)); +} + +TEST_F(CAmMapHandlerTest,removeSourceClass) +{ + std::vector<am_SourceClass_s> sourceClassList; + std::vector<am_ClassProperty_s> classPropertyList; + am_SourceClass_s sourceClass; + am_ClassProperty_s classProperty; + am_sourceClass_t sourceClassID; + classProperty.classProperty = CP_GENIVI_SINK_TYPE; + classProperty.value = 1; + classPropertyList.push_back(classProperty); + classProperty.classProperty = CP_GENIVI_SOURCE_TYPE; + classProperty.value = 4; + classPropertyList.push_back(classProperty); + sourceClass.name = "test"; + sourceClass.sourceClassID = 3; + sourceClass.listClassProperties = classPropertyList; + + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceClassDB(sourceClassID,sourceClass)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSourceClasses(sourceClassList)); + ASSERT_EQ(sourceClassList[0].name, sourceClass.name); + ASSERT_EQ(sourceClassList[0].sourceClassID, 3); + ASSERT_TRUE(std::equal(sourceClassList[0].listClassProperties.begin(),sourceClassList[0].listClassProperties.end(),classPropertyList.begin(),equalClassProperties)); + ASSERT_EQ(E_OK, pDatabaseHandler.removeSourceClassDB(3)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSourceClasses(sourceClassList)); + ASSERT_TRUE(sourceClassList.empty()); +} + +TEST_F(CAmMapHandlerTest,updateSourceClass) +{ + std::vector<am_SourceClass_s> sourceClassList; + std::vector<am_ClassProperty_s> classPropertyList, changedPropertyList; + am_SourceClass_s sourceClass, changedClass; + am_ClassProperty_s classProperty; + am_sourceClass_t sourceClassID; + classProperty.classProperty = CP_GENIVI_SINK_TYPE; + classProperty.value = 1; + classPropertyList.push_back(classProperty); + classProperty.classProperty = CP_GENIVI_SOURCE_TYPE; + classProperty.value = 4; + classPropertyList.push_back(classProperty); + sourceClass.name = "test"; + sourceClass.sourceClassID = 0; + sourceClass.listClassProperties = classPropertyList; + changedClass = sourceClass; + changedClass.listClassProperties[1].value = 6; + changedPropertyList = changedClass.listClassProperties; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceClassDB(sourceClassID,sourceClass)); + changedClass.sourceClassID = sourceClassID; + ASSERT_EQ(E_OK, pDatabaseHandler.getListSourceClasses(sourceClassList)); + ASSERT_EQ(sourceClassList[0].name, sourceClass.name); + ASSERT_EQ(sourceClassList[0].sourceClassID, DYNAMIC_ID_BOUNDARY); + ASSERT_TRUE(std::equal(sourceClassList[0].listClassProperties.begin(),sourceClassList[0].listClassProperties.end(),classPropertyList.begin(),equalClassProperties)); + ASSERT_EQ(E_OK, pDatabaseHandler.changeSourceClassInfoDB(changedClass)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSourceClasses(sourceClassList)); + ASSERT_EQ(sourceClassList[0].name, sourceClass.name); + ASSERT_EQ(sourceClassList[0].sourceClassID, DYNAMIC_ID_BOUNDARY); + ASSERT_TRUE(std::equal(sourceClassList[0].listClassProperties.begin(),sourceClassList[0].listClassProperties.end(),changedPropertyList.begin(),equalClassProperties)); +} + +TEST_F(CAmMapHandlerTest,enterSourceClass) +{ + std::vector<am_SourceClass_s> sourceClassList; + std::vector<am_ClassProperty_s> classPropertyList; + am_SourceClass_s sourceClass; + am_ClassProperty_s classProperty; + am_sourceClass_t sourceClassID; + classProperty.classProperty = CP_GENIVI_SINK_TYPE; + classProperty.value = 1; + classPropertyList.push_back(classProperty); + classProperty.classProperty = CP_GENIVI_SOURCE_TYPE; + classProperty.value = 4; + classPropertyList.push_back(classProperty); + sourceClass.name = "test"; + sourceClass.sourceClassID = 0; + sourceClass.listClassProperties = classPropertyList; + + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceClassDB(sourceClassID,sourceClass)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSourceClasses(sourceClassList)); + ASSERT_EQ(sourceClassList[0].name, sourceClass.name); + ASSERT_EQ(sourceClassList[0].sourceClassID, DYNAMIC_ID_BOUNDARY); + ASSERT_TRUE(std::equal(sourceClassList[0].listClassProperties.begin(),sourceClassList[0].listClassProperties.end(),classPropertyList.begin(),equalClassProperties)); +} + +TEST_F(CAmMapHandlerTest,enterSourceClassStatic) +{ + std::vector<am_SourceClass_s> sourceClassList; + std::vector<am_ClassProperty_s> classPropertyList; + am_SourceClass_s sourceClass; + am_ClassProperty_s classProperty; + am_sourceClass_t sourceClassID; + classProperty.classProperty = CP_GENIVI_SINK_TYPE; + classProperty.value = 1; + classPropertyList.push_back(classProperty); + classProperty.classProperty = CP_GENIVI_SOURCE_TYPE; + classProperty.value = 4; + classPropertyList.push_back(classProperty); + sourceClass.name = "test"; + sourceClass.sourceClassID = 3; + sourceClass.listClassProperties = classPropertyList; + + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceClassDB(sourceClassID,sourceClass)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSourceClasses(sourceClassList)); + ASSERT_EQ(sourceClassList[0].name, sourceClass.name); + ASSERT_EQ(sourceClassList[0].sourceClassID, 3); + ASSERT_TRUE(std::equal(sourceClassList[0].listClassProperties.begin(),sourceClassList[0].listClassProperties.end(),classPropertyList.begin(),equalClassProperties)); +} + +TEST_F(CAmMapHandlerTest,removeSinkClass) +{ + std::vector<am_SinkClass_s> sinkClassList; + std::vector<am_ClassProperty_s> classPropertyList; + am_SinkClass_s sinkClass; + am_ClassProperty_s classProperty; + am_sinkClass_t sinkClassID; + classProperty.classProperty = CP_GENIVI_SINK_TYPE; + classProperty.value = 1; + classPropertyList.push_back(classProperty); + classProperty.classProperty = CP_GENIVI_SOURCE_TYPE; + classProperty.value = 4; + classPropertyList.push_back(classProperty); + sinkClass.name = "test"; + sinkClass.sinkClassID = 0; + sinkClass.listClassProperties = classPropertyList; + + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkClassDB(sinkClass,sinkClassID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinkClasses(sinkClassList)); + ASSERT_EQ(sinkClassList[0].name, sinkClass.name); + ASSERT_EQ(sinkClassList[0].sinkClassID, DYNAMIC_ID_BOUNDARY); + ASSERT_TRUE(std::equal(sinkClassList[0].listClassProperties.begin(),sinkClassList[0].listClassProperties.end(),classPropertyList.begin(),equalClassProperties)); + ASSERT_EQ(E_OK, pDatabaseHandler.removeSinkClassDB(sinkClassID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinkClasses(sinkClassList)); + ASSERT_TRUE(sinkClassList.empty()); +} + +TEST_F(CAmMapHandlerTest,updateSinkClass) +{ + std::vector<am_SinkClass_s> sinkClassList; + std::vector<am_ClassProperty_s> classPropertyList, changedPropertyList; + am_SinkClass_s sinkClass, changedClass; + am_ClassProperty_s classProperty; + am_sinkClass_t sinkClassID; + classProperty.classProperty = CP_GENIVI_SINK_TYPE; + classProperty.value = 1; + classPropertyList.push_back(classProperty); + classProperty.classProperty = CP_GENIVI_SOURCE_TYPE; + classProperty.value = 4; + classPropertyList.push_back(classProperty); + sinkClass.name = "test"; + sinkClass.sinkClassID = 0; + sinkClass.listClassProperties = classPropertyList; + changedClass = sinkClass; + changedClass.listClassProperties[1].value = 6; + changedPropertyList = changedClass.listClassProperties; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkClassDB(sinkClass,sinkClassID)); + changedClass.sinkClassID = sinkClassID; + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinkClasses(sinkClassList)); + ASSERT_EQ(sinkClassList[0].name, sinkClass.name); + ASSERT_EQ(sinkClassList[0].sinkClassID, DYNAMIC_ID_BOUNDARY); + ASSERT_TRUE(std::equal(sinkClassList[0].listClassProperties.begin(),sinkClassList[0].listClassProperties.end(),classPropertyList.begin(),equalClassProperties)); + ASSERT_EQ(E_OK, pDatabaseHandler.changeSinkClassInfoDB(changedClass)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinkClasses(sinkClassList)); + ASSERT_EQ(sinkClassList[0].name, sinkClass.name); + ASSERT_EQ(sinkClassList[0].sinkClassID, DYNAMIC_ID_BOUNDARY); + ASSERT_TRUE(std::equal(sinkClassList[0].listClassProperties.begin(),sinkClassList[0].listClassProperties.end(),changedPropertyList.begin(),equalClassProperties)); +} + +TEST_F(CAmMapHandlerTest,enterSinkClass) +{ + std::vector<am_SinkClass_s> sinkClassList; + std::vector<am_ClassProperty_s> classPropertyList; + am_SinkClass_s sinkClass; + am_ClassProperty_s classProperty; + am_sinkClass_t sinkClassID; + classProperty.classProperty = CP_GENIVI_SINK_TYPE; + classProperty.value = 1; + classPropertyList.push_back(classProperty); + classProperty.classProperty = CP_GENIVI_SOURCE_TYPE; + classProperty.value = 4; + classPropertyList.push_back(classProperty); + sinkClass.name = "test"; + sinkClass.sinkClassID = 0; + sinkClass.listClassProperties = classPropertyList; + + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkClassDB(sinkClass,sinkClassID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinkClasses(sinkClassList)); + ASSERT_EQ(sinkClassList[0].name, sinkClass.name); + ASSERT_EQ(sinkClassList[0].sinkClassID, DYNAMIC_ID_BOUNDARY); + ASSERT_TRUE(std::equal(sinkClassList[0].listClassProperties.begin(),sinkClassList[0].listClassProperties.end(),classPropertyList.begin(),equalClassProperties)); +} + +TEST_F(CAmMapHandlerTest,enterSinkClassStatic) +{ + std::vector<am_SinkClass_s> sinkClassList; + std::vector<am_ClassProperty_s> classPropertyList; + am_SinkClass_s sinkClass; + am_ClassProperty_s classProperty; + am_sinkClass_t sinkClassID; + classProperty.classProperty = CP_GENIVI_SINK_TYPE; + classProperty.value = 1; + classPropertyList.push_back(classProperty); + classProperty.classProperty = CP_GENIVI_SOURCE_TYPE; + classProperty.value = 4; + classPropertyList.push_back(classProperty); + sinkClass.name = "test"; + sinkClass.sinkClassID = 4; + sinkClass.listClassProperties = classPropertyList; + + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkClassDB(sinkClass,sinkClassID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinkClasses(sinkClassList)); + ASSERT_EQ(sinkClassList[0].name, sinkClass.name); + ASSERT_EQ(sinkClassList[0].sinkClassID, 4); + ASSERT_TRUE(std::equal(sinkClassList[0].listClassProperties.begin(),sinkClassList[0].listClassProperties.end(),classPropertyList.begin(),equalClassProperties)); +} + +TEST_F(CAmMapHandlerTest, changeSystemProperty) +{ + std::vector<am_SystemProperty_s> listSystemProperties, listReturn; + am_SystemProperty_s systemProperty; + + systemProperty.type = SYP_UNKNOWN; + systemProperty.value = 33; + listSystemProperties.push_back(systemProperty); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSystemProperties(listSystemProperties)); + systemProperty.value = 444; + ASSERT_EQ(E_OK, pDatabaseHandler.changeSystemPropertyDB(systemProperty)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSystemProperties(listReturn)); + ASSERT_EQ(listReturn[0].type, systemProperty.type); + ASSERT_EQ(listReturn[0].value, systemProperty.value); +} + +TEST_F(CAmMapHandlerTest, systemProperties) +{ + std::vector<am_SystemProperty_s> listSystemProperties, listReturn; + am_SystemProperty_s systemProperty; + + systemProperty.type = SYP_UNKNOWN; + systemProperty.value = 33; + listSystemProperties.push_back(systemProperty); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSystemProperties(listSystemProperties)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSystemProperties(listReturn)); + ASSERT_EQ(listReturn[0].type, systemProperty.type); + ASSERT_EQ(listReturn[0].value, systemProperty.value); +} + +TEST_F(CAmMapHandlerTest,enterSourcesCorrect) +{ + //fill the connection database + am_Source_s staticSource, firstDynamicSource, secondDynamicSource; + am_sourceID_t staticSourceID, firstDynamicSourceID, secondDynamicSourceID; + std::vector<am_Source_s> sourceList; + + pCF.createSource(staticSource); + staticSource.sourceID = 4; + staticSource.name = "Static"; + + + ASSERT_EQ(E_OK,pDatabaseHandler.enterSourceDB(staticSource,staticSourceID)) + << "ERROR: database error"; + ASSERT_EQ(staticSource.sourceID,staticSourceID) + << "ERROR: ID not the one given in staticSource"; + + pCF.createSource(firstDynamicSource); + firstDynamicSource.name = "firstDynamicSource"; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterSourceDB(firstDynamicSource,firstDynamicSourceID)) + << "ERROR: database error"; + ASSERT_EQ(firstDynamicSourceID,DYNAMIC_ID_BOUNDARY) + << "ERROR: ID not the one given in firstDynamicSink"; + + pCF.createSource(secondDynamicSource); + secondDynamicSource.name = "secondDynamicSource"; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterSourceDB(secondDynamicSource,secondDynamicSourceID)) + << "ERROR: database error"; + ASSERT_NEAR(secondDynamicSourceID,DYNAMIC_ID_BOUNDARY,10) + << "ERROR: ID not the one given in secondDynamicSink"; + + //now read back and check the returns agains the given values + ASSERT_EQ(E_OK,pDatabaseHandler.getListSources(sourceList)) + << "ERROR: database error"; + + std::vector<am_Source_s>::iterator listIterator = sourceList.begin(); + for (; listIterator < sourceList.end(); ++listIterator) + { + if (listIterator->sourceID == staticSourceID) + { + ASSERT_TRUE(pCF.compareSource(listIterator, staticSource)); + } + + if (listIterator->sourceID == firstDynamicSourceID) + { + ASSERT_TRUE(pCF.compareSource(listIterator, firstDynamicSource)); + } + + if (listIterator->sourceID == secondDynamicSourceID) + { + ASSERT_TRUE(pCF.compareSource(listIterator, secondDynamicSource)); + } + + } +} + +TEST_F(CAmMapHandlerTest, changeSinkMuteState) +{ + std::vector<am_Sink_s> listSinks; + am_Sink_s sink; + am_sinkID_t sinkID; + pCF.createSink(sink); + am_MuteState_e muteState = MS_MUTED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + ASSERT_EQ(E_OK, pDatabaseHandler.changeSinkMuteStateDB(muteState,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + ASSERT_EQ(muteState, listSinks[0].muteState); +} + +TEST_F(CAmMapHandlerTest, changeSourceMainSoundProperty) +{ + std::vector<am_Source_s> listSources; + am_Source_s source; + am_sourceID_t sourceID; + pCF.createSource(source); + am_MainSoundProperty_s property; + property.type = MSP_UNKNOWN; + property.value = 33; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + + ASSERT_EQ(E_OK, pDatabaseHandler.changeMainSourceSoundPropertyDB(property,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSources(listSources)); + + std::vector<am_MainSoundProperty_s>::iterator listIterator = listSources[0].listMainSoundProperties.begin(); + for (; listIterator < listSources[0].listMainSoundProperties.end(); ++listIterator) + { + if (listIterator->type == property.type) + ASSERT_EQ(listIterator->value, property.value); + } + int16_t value; + ASSERT_EQ(E_OK, pDatabaseHandler.getMainSourceSoundPropertyValue(sourceID, property.type, value)); + ASSERT_EQ(value, property.value); + + ASSERT_EQ(E_OK, pDatabaseHandler.changeMainSourceSoundPropertyDB({property.type, 34},sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getMainSourceSoundPropertyValue(sourceID, property.type, value)); + ASSERT_EQ(value, 34); + ASSERT_EQ(E_NON_EXISTENT, pDatabaseHandler.getMainSourceSoundPropertyValue(sourceID, 1000, value)); +} + +TEST_F(CAmMapHandlerTest, changeSinkMainSoundProperty) +{ + std::vector<am_Sink_s> listSinks; + am_Sink_s sink; + am_sinkID_t sinkID; + pCF.createSink(sink); + am_MainSoundProperty_s property; + property.type = MSP_UNKNOWN; + property.value = 33; + + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + ASSERT_EQ(E_OK, pDatabaseHandler.changeMainSinkSoundPropertyDB(property,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + std::vector<am_MainSoundProperty_s>::iterator listIterator = listSinks[0].listMainSoundProperties.begin(); + for (; listIterator < listSinks[0].listMainSoundProperties.end(); ++listIterator) + { + if (listIterator->type == property.type) + ASSERT_EQ(listIterator->value, property.value); + } + + int16_t value; + ASSERT_EQ(E_OK, pDatabaseHandler.getMainSinkSoundPropertyValue(sinkID, property.type, value)); + ASSERT_EQ(value, property.value); + + ASSERT_EQ(E_OK, pDatabaseHandler.changeMainSinkSoundPropertyDB({property.type, 34},sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getMainSinkSoundPropertyValue(sinkID, property.type, value)); + ASSERT_EQ(value, 34); + ASSERT_EQ(E_NON_EXISTENT, pDatabaseHandler.getMainSinkSoundPropertyValue(sinkID, 1000, value)); +} + +TEST_F(CAmMapHandlerTest, changeSourceSoundProperty) +{ + std::vector<am_Source_s> listSources; + am_Source_s source; + am_sourceID_t sourceID; + pCF.createSource(source); + am_SoundProperty_s property; + property.type = SP_GENIVI_MID; + property.value = 33; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + + ASSERT_EQ(E_OK, pDatabaseHandler.changeSourceSoundPropertyDB(property,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSources(listSources)); + + std::vector<am_SoundProperty_s>::iterator listIterator = listSources[0].listSoundProperties.begin(); + for (; listIterator < listSources[0].listSoundProperties.end(); ++listIterator) + { + if (listIterator->type == property.type) + ASSERT_EQ(listIterator->value, property.value); + } + int16_t value; + ASSERT_EQ(E_OK, pDatabaseHandler.getSourceSoundPropertyValue(sourceID, property.type, value)); + ASSERT_EQ(value, property.value); + + ASSERT_EQ(E_OK, pDatabaseHandler.changeSourceSoundPropertyDB({property.type, 34},sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getSourceSoundPropertyValue(sourceID, property.type, value)); + ASSERT_EQ(value, 34); + ASSERT_EQ(E_NON_EXISTENT, pDatabaseHandler.getSourceSoundPropertyValue(sourceID, 1000, value)); +} + +TEST_F(CAmMapHandlerTest, changeSinkSoundProperty) +{ + std::vector<am_Sink_s> listSinks; + am_Sink_s sink; + am_sinkID_t sinkID; + pCF.createSink(sink); + am_SoundProperty_s property; + property.type = SP_GENIVI_MID; + property.value = 33; + + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + ASSERT_EQ(E_OK, pDatabaseHandler.changeSinkSoundPropertyDB(property,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + std::vector<am_SoundProperty_s>::iterator listIterator = listSinks[0].listSoundProperties.begin(); + for (; listIterator < listSinks[0].listSoundProperties.end(); ++listIterator) + { + if (listIterator->type == property.type) + ASSERT_EQ(listIterator->value, property.value); + } + + int16_t value; + ASSERT_EQ(E_OK, pDatabaseHandler.getSinkSoundPropertyValue(sinkID, property.type, value)); + ASSERT_EQ(value, property.value); + + ASSERT_EQ(E_OK, pDatabaseHandler.changeSinkSoundPropertyDB({property.type, 34},sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getSinkSoundPropertyValue(sinkID, property.type, value)); + ASSERT_EQ(value, 34); + ASSERT_EQ(E_NON_EXISTENT, pDatabaseHandler.getSinkSoundPropertyValue(sinkID, 1000, value)); +} + +TEST_F(CAmMapHandlerTest, peekDomain) +{ + std::vector<am_Domain_s> listDomains; + am_Domain_s domain; + am_domainID_t domainID; + am_domainID_t domain2ID; + pCF.createDomain(domain); + ASSERT_EQ(E_OK, pDatabaseHandler.peekDomain(std::string("newdomain"),domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListDomains(listDomains)); + ASSERT_TRUE(listDomains.empty()); + ASSERT_EQ(domainID, DYNAMIC_ID_BOUNDARY); + domain.name = "newdomain"; + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domain2ID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListDomains(listDomains)); + ASSERT_EQ(domainID, domain2ID); + ASSERT_TRUE(listDomains[0].domainID==domainID); +} + +TEST_F(CAmMapHandlerTest, peekDomainFirstEntered) +{ + std::vector<am_Domain_s> listDomains; + am_Domain_s domain; + am_domainID_t domainID; + am_domainID_t domain2ID; + pCF.createDomain(domain); + domain.name = "newdomain"; + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.peekDomain(std::string("newdomain"),domain2ID)); + ASSERT_EQ(domainID, domain2ID); + ASSERT_EQ(E_OK, pDatabaseHandler.getListDomains(listDomains)); + ASSERT_TRUE(listDomains.size()==1); +} + +TEST_F(CAmMapHandlerTest, changeDomainState) +{ + std::vector<am_Domain_s> listDomains; + am_Domain_s domain; + am_domainID_t domainID; + pCF.createDomain(domain); + am_DomainState_e newState = DS_INDEPENDENT_STARTUP; + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.changDomainStateDB(newState,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListDomains(listDomains)); + ASSERT_EQ(newState, listDomains[0].state); +} + +TEST_F(CAmMapHandlerTest, changeMainConnectionState) +{ + am_mainConnectionID_t mainConnectionID; + am_MainConnection_s mainConnection; + std::vector<am_MainConnection_s> listMainConnections; + createMainConnectionSetup(mainConnectionID, mainConnection); + + ASSERT_EQ(E_OK, pDatabaseHandler.changeMainConnectionStateDB(1,CS_DISCONNECTING)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainConnections(listMainConnections)); + ASSERT_EQ(CS_DISCONNECTING, listMainConnections[0].connectionState); +} + +TEST_F(CAmMapHandlerTest, changeSinkAvailability) +{ + std::vector<am_Sink_s> listSinks; + am_Sink_s sink; + am_sinkID_t sinkID; + pCF.createSink(sink); + am_Availability_s availability; + availability.availability = A_UNKNOWN; + availability.availabilityReason = AR_GENIVI_TEMPERATURE; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.changeSinkAvailabilityDB(availability,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + ASSERT_EQ(availability.availability, listSinks[0].available.availability); + ASSERT_EQ(availability.availabilityReason, listSinks[0].available.availabilityReason); +} + +TEST_F(CAmMapHandlerTest, changeSourceAvailability) +{ + std::vector<am_Source_s> listSources; + am_Source_s source; + am_sourceID_t sourceID; + pCF.createSource(source); + am_Availability_s availability; + availability.availability = A_UNKNOWN; + availability.availabilityReason = AR_GENIVI_TEMPERATURE; + source.visible = true; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.changeSourceAvailabilityDB(availability,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSources(listSources)); + ASSERT_EQ(availability.availability, listSources[0].available.availability); + ASSERT_EQ(availability.availabilityReason, listSources[0].available.availabilityReason); +} + +TEST_F(CAmMapHandlerTest,changeMainConnectionRoute) +{ + am_mainConnectionID_t mainConnectionID; + am_MainConnection_s mainConnection; + std::vector<am_MainConnection_s> originalList; + std::vector<am_MainConnection_s> newList; + createMainConnectionSetup(mainConnectionID, mainConnection); + + //fill the connection database + am_Connection_s connection; + am_Source_s source; + am_Sink_s sink; + std::vector<am_connectionID_t> listConnectionID; + + uint16_t i = 1; + for (; i < 10; i++) + { + am_sinkID_t forgetSink; + am_sourceID_t forgetSource; + am_connectionID_t connectionID; + + connection.sinkID = i + 20; + connection.sourceID = i + 20; + connection.delay = -1; + connection.connectionFormat = CF_GENIVI_ANALOG; + connection.connectionID = 0; + + pCF.createSink(sink); + sink.sinkID = i + 20; + sink.name = "sink" + int2string(i + 20); + sink.domainID = 4; + pCF.createSource(source); + source.sourceID = i + 20; + source.name = "source" + int2string(i + 30); + source.domainID = 4; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,forgetSink)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,forgetSource)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterConnectionDB(connection,connectionID)); + listConnectionID.push_back(connectionID); + } + + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainConnections(originalList)); + ASSERT_EQ(E_OK, pDatabaseHandler.changeMainConnectionRouteDB(mainConnectionID,listConnectionID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainConnections(newList)); + ASSERT_FALSE(std::equal(newList[0].listConnectionID.begin(),newList[0].listConnectionID.end(),originalList[0].listConnectionID.begin())); +} + +TEST_F(CAmMapHandlerTest,changeMainSinkVolume) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + am_mainVolume_t newVol = 20; + std::vector<am_Sink_s> listSinks; + pCF.createSink(sink); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.changeSinkMainVolumeDB(newVol,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + ASSERT_EQ(listSinks[0].mainVolume, newVol); +} + +TEST_F(CAmMapHandlerTest,getMainSourceSoundProperties) +{ + am_Source_s source; + am_sourceID_t sourceID; + pCF.createSource(source); + std::vector<am_MainSoundProperty_s> mainSoundProperties = source.listMainSoundProperties; + std::vector<am_MainSoundProperty_s> listMainSoundProperties; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainSourceSoundProperties(sourceID,listMainSoundProperties)); + ASSERT_TRUE(std::equal(mainSoundProperties.begin(),mainSoundProperties.end(),listMainSoundProperties.begin(),equalMainSoundProperty)); +} + +TEST_F(CAmMapHandlerTest,getMainSinkSoundProperties) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + pCF.createSink(sink); + std::vector<am_MainSoundProperty_s> mainSoundProperties = sink.listMainSoundProperties; + std::vector<am_MainSoundProperty_s> listMainSoundProperties; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainSinkSoundProperties(sinkID,listMainSoundProperties)); + ASSERT_TRUE(std::equal(mainSoundProperties.begin(),mainSoundProperties.end(),listMainSoundProperties.begin(),equalMainSoundProperty)); +} + +TEST_F(CAmMapHandlerTest,getMainSources) +{ + am_Source_s source, source1, source2; + am_sourceID_t sourceID; + pCF.createSource(source); + pCF.createSource(source1); + pCF.createSource(source2); + source1.name = "source1"; + source2.name = "source2"; + bool equal = true; + source1.visible = false; + std::vector<am_SourceType_s> listMainSources; + std::vector<am_Source_s> listSources; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + source.sourceID = sourceID; + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source1,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source2,sourceID)); + source2.sourceID = sourceID; + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainSources(listMainSources)); + listSources.push_back(source); + listSources.push_back(source2); + std::vector<am_SourceType_s>::iterator listIterator = listMainSources.begin(); + for (; listIterator < listMainSources.end(); ++listIterator) + { + equal = equal && pCF.compareSinkMainSource(listIterator, listSources); + } + ASSERT_TRUE(equal); +} + +TEST_F(CAmMapHandlerTest,getMainSinks) +{ + am_Sink_s sink, sink1, sink2; + am_sinkID_t sinkID; + pCF.createSink(sink); + pCF.createSink(sink1); + pCF.createSink(sink2); + sink1.name = "sink1"; + sink2.name = "sink2"; + sink1.visible = false; + std::vector<am_SinkType_s> listMainSinks; + std::vector<am_Sink_s> listSinks; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + sink.sinkID = sinkID; + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink1,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink2,sinkID)); + sink2.sinkID = sinkID; + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainSinks(listMainSinks)); + listSinks.push_back(sink); + listSinks.push_back(sink2); + + std::vector<am_SinkType_s>::iterator listIterator = listMainSinks.begin(); + for (; listIterator < listMainSinks.end(); ++listIterator) + { + ASSERT_TRUE(pCF.compareSinkMainSink(listIterator, listSinks)); + } +} + +TEST_F(CAmMapHandlerTest,getVisibleMainConnections) +{ + am_mainConnectionID_t mainConnectionID; + am_MainConnection_s mainConnection; + createMainConnectionSetup(mainConnectionID, mainConnection); + + std::vector<am_MainConnectionType_s> listVisibleMainConnections; + std::vector<am_MainConnection_s> listMainConnections; + ASSERT_EQ(E_OK, pDatabaseHandler.getListVisibleMainConnections(listVisibleMainConnections)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListMainConnections(listMainConnections)); + ASSERT_EQ(listMainConnections[0].mainConnectionID, listVisibleMainConnections[0].mainConnectionID); + ASSERT_EQ(listMainConnections[0].connectionState, listVisibleMainConnections[0].connectionState); + ASSERT_EQ(listMainConnections[0].delay, listVisibleMainConnections[0].delay); + ASSERT_EQ(listMainConnections[0].sinkID, listVisibleMainConnections[0].sinkID); + ASSERT_EQ(listMainConnections[0].sourceID, listVisibleMainConnections[0].sourceID); +} + +TEST_F(CAmMapHandlerTest,getListSourcesOfDomain) +{ + am_Source_s source, source2; + am_Domain_s domain; + am_domainID_t domainID; + am_sourceID_t sourceID; + std::vector<am_sourceID_t> sourceList, sourceCheckList; + pCF.createSource(source); + source.sourceID = 1; + source.name = "testSource"; + source.domainID = DYNAMIC_ID_BOUNDARY; + pCF.createSource(source2); + source2.sourceID = 0; + source2.name = "testSource2"; + source2.domainID = 5; + pCF.createDomain(domain); + sourceCheckList.push_back(1); //sink.sinkID); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK,pDatabaseHandler.enterSourceDB(source,sourceID)) + << "ERROR: database error"; + ASSERT_EQ(E_OK,pDatabaseHandler.enterSourceDB(source2,sourceID)) + << "ERROR: database error"; + ASSERT_EQ(E_NON_EXISTENT,pDatabaseHandler.getListSourcesOfDomain(2,sourceList)) + << "ERROR: database error";ASSERT_TRUE(sourceList.empty()); + ASSERT_EQ(E_OK,pDatabaseHandler.getListSourcesOfDomain(DYNAMIC_ID_BOUNDARY,sourceList)) + << "ERROR: database error"; + ASSERT_TRUE(std::equal(sourceList.begin(),sourceList.end(),sourceCheckList.begin()) && !sourceList.empty()); +} + +TEST_F(CAmMapHandlerTest,getListSinksOfDomain) +{ + am_Sink_s sink, sink2; + am_Domain_s domain; + am_domainID_t domainID; + am_sinkID_t sinkID; + std::vector<am_sinkID_t> sinkList, sinkCheckList; + pCF.createSink(sink); + sink.sinkID = 1; + sink.domainID = DYNAMIC_ID_BOUNDARY; + pCF.createSink(sink2); + sink2.domainID = 5; + sink2.name = "sink2"; + pCF.createDomain(domain); + sinkCheckList.push_back(1); //sink.sinkID); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(sink,sinkID)) + << "ERROR: database error"; + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(sink2,sinkID)) + << "ERROR: database error"; + ASSERT_EQ(E_NON_EXISTENT,pDatabaseHandler.getListSinksOfDomain(DYNAMIC_ID_BOUNDARY+1,sinkList)) + << "ERROR: database error";ASSERT_TRUE(sinkList.empty()); + ASSERT_EQ(E_OK,pDatabaseHandler.getListSinksOfDomain(DYNAMIC_ID_BOUNDARY,sinkList)) + << "ERROR: database error"; + ASSERT_TRUE(std::equal(sinkList.begin(),sinkList.end(),sinkCheckList.begin()) && !sinkList.empty()); +} + +TEST_F(CAmMapHandlerTest,getListGatewaysOfDomain) +{ + am_Gateway_s gateway, gateway2; + am_gatewayID_t gatewayID1, gatewayID2; + am_domainID_t domainID; + am_Domain_s domain; + std::vector<am_gatewayID_t> gatewayList, gatewayCheckList; + + pCF.createDomain(domain); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + + pCF.createGateway(gateway); + gateway.gatewayID = 1; + gateway.name = "testGateway"; + gateway.controlDomainID = domainID; + gateway.sourceID = 1; + gateway.sinkID = 1; + gateway.domainSinkID = 1; + gateway.domainSourceID = 1; + ASSERT_EQ(E_OK,pDatabaseHandler.enterGatewayDB(gateway,gatewayID1)) + << "ERROR: database error"; + ASSERT_EQ(true, gatewayID1==1); + + pCF.createGateway(gateway2); + gateway2.gatewayID = 2; + gateway2.name = "testGateway2"; + gateway2.controlDomainID = 4; + gateway2.sourceID = 1; + gateway2.sinkID = 1; + gateway2.domainSinkID = 1; + gateway2.domainSourceID = 1; + ASSERT_EQ(E_OK,pDatabaseHandler.enterGatewayDB(gateway2,gatewayID2)) + << "ERROR: database error"; + ASSERT_EQ(true, gatewayID2==2); + gatewayCheckList.push_back(gatewayID1); + + am_Sink_s sink; + am_Source_s source; + am_sinkID_t sinkID; + am_sourceID_t sourceID; + pCF.createSink(sink); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + sink.sinkID = sinkID; + + pCF.createSource(source); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + source.sourceID = sourceID; + + ASSERT_EQ(E_NON_EXISTENT,pDatabaseHandler.getListGatewaysOfDomain(2,gatewayList)) + << "ERROR: database error"; + ASSERT_TRUE(gatewayList.empty()); + ASSERT_EQ(E_OK,pDatabaseHandler.getListGatewaysOfDomain(domainID,gatewayList)) + << "ERROR: database error"; + ASSERT_TRUE(std::equal(gatewayList.begin(),gatewayList.end(),gatewayCheckList.begin()) && !gatewayList.empty()); +} + +TEST_F(CAmMapHandlerTest,getListConvertersOfDomain) +{ + am_Converter_s converter, converter2; + am_converterID_t converterID1, converterID2; + am_domainID_t domainID; + am_Domain_s domain; + std::vector<am_converterID_t> converterList, converterCheckList; + + pCF.createDomain(domain); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + + pCF.createConverter(converter); + converter.converterID = 1; + converter.name = "testGateway"; + converter.sourceID = 1; + converter.sinkID = 1; + converter.domainID = domainID; + ASSERT_EQ(E_OK,pDatabaseHandler.enterConverterDB(converter,converterID1)) + << "ERROR: database error"; + ASSERT_EQ(true, converterID1==1); + + pCF.createConverter(converter2); + converter2.converterID = 2; + converter2.name = "testGateway2"; + converter2.domainID = 4; + converter2.sourceID = 1; + converter2.sinkID = 1; + ASSERT_EQ(E_OK,pDatabaseHandler.enterConverterDB(converter2,converterID2)) + << "ERROR: database error"; + ASSERT_EQ(true, converterID2==2); + converterCheckList.push_back(converterID1); + + am_Sink_s sink; + am_Source_s source; + am_sinkID_t sinkID; + am_sourceID_t sourceID; + pCF.createSink(sink); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + sink.sinkID = sinkID; + + pCF.createSource(source); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + source.sourceID = sourceID; + + ASSERT_EQ(E_NON_EXISTENT,pDatabaseHandler.getListConvertersOfDomain(4,converterList)) + << "ERROR: database error"; + ASSERT_TRUE(converterList.empty()); + ASSERT_EQ(E_OK,pDatabaseHandler.getListConvertersOfDomain(domainID,converterList)) + << "ERROR: database error"; + ASSERT_TRUE(std::equal(converterList.begin(),converterList.end(),converterCheckList.begin()) && !converterList.empty()); +} + +TEST_F(CAmMapHandlerTest,removeDomain) +{ + am_Domain_s domain; + am_domainID_t domainID; + std::vector<am_Domain_s> listDomains; + pCF.createDomain(domain); + ASSERT_EQ(E_OK,pDatabaseHandler.enterDomainDB(domain,domainID)) + << "ERROR: database error"; + ASSERT_EQ(E_OK,pDatabaseHandler.removeDomainDB(domainID)) + << "ERROR: database error"; + ASSERT_EQ(E_OK,pDatabaseHandler.getListDomains(listDomains)) + << "ERROR: database error"; + ASSERT_TRUE(listDomains.empty()); +} + +TEST_F(CAmMapHandlerTest,removeGateway) +{ + am_Gateway_s gateway; + am_gatewayID_t gatewayID; + std::vector<am_Gateway_s> listGateways; + pCF.createGateway(gateway); + am_Sink_s sink; + am_Source_s source; + am_sinkID_t sinkID; + am_sourceID_t sourceID; + pCF.createSink(sink); + pCF.createSource(source); + sink.sinkID = 1; + source.sourceID = 2; + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK,pDatabaseHandler.enterGatewayDB(gateway,gatewayID)) + << "ERROR: database error"; + ASSERT_EQ(E_OK,pDatabaseHandler.removeGatewayDB(gatewayID)) + << "ERROR: database error"; + ASSERT_EQ(E_OK,pDatabaseHandler.getListGateways(listGateways)) + << "ERROR: database error"; + ASSERT_TRUE(listGateways.empty()); +} + +TEST_F(CAmMapHandlerTest,removeConverter) +{ + am_Converter_s converter; + am_converterID_t converterID; + std::vector<am_Converter_s> listConverters; + pCF.createConverter(converter); + am_Sink_s sink; + am_Source_s source; + am_sinkID_t sinkID; + am_sourceID_t sourceID; + pCF.createSink(sink); + pCF.createSource(source); + sink.sinkID = 1; + source.sourceID = 2; + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK,pDatabaseHandler.enterConverterDB(converter,converterID)) + << "ERROR: database error"; + ASSERT_EQ(E_OK,pDatabaseHandler.removeConverterDB(converterID)) + << "ERROR: database error"; + ASSERT_EQ(E_OK,pDatabaseHandler.getListConverters(listConverters)) + << "ERROR: database error"; + ASSERT_TRUE(listConverters.empty()); +} + +TEST_F(CAmMapHandlerTest,removeSink) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + std::vector<am_Sink_s> listSinks; + pCF.createSink(sink); + + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(sink,sinkID)) + << "ERROR: database error"; + ASSERT_EQ(E_OK,pDatabaseHandler.removeSinkDB(sinkID)) + << "ERROR: database error"; + ASSERT_EQ(E_OK,pDatabaseHandler.getListSinks(listSinks)) + << "ERROR: database error"; + ASSERT_TRUE(listSinks.empty()); +} + +TEST_F(CAmMapHandlerTest,removeSource) +{ + //fill the connection database + am_Source_s source; + am_sourceID_t sourceID; + std::vector<am_Source_s> listSources; + pCF.createSource(source); + + ASSERT_EQ(E_OK,pDatabaseHandler.enterSourceDB(source,sourceID)) + << "ERROR: database error"; + ASSERT_EQ(E_OK,pDatabaseHandler.removeSourceDB(sourceID)) + << "ERROR: database error"; + ASSERT_EQ(E_OK,pDatabaseHandler.getListSources(listSources)) + << "ERROR: database error"; + ASSERT_TRUE(listSources.empty()); +} + +TEST_F(CAmMapHandlerTest, removeMainConnection) +{ + am_mainConnectionID_t mainConnectionID; + am_MainConnection_s mainConnection; + createMainConnectionSetup(mainConnectionID, mainConnection); + + ASSERT_EQ(E_OK,pDatabaseHandler.removeMainConnectionDB(mainConnectionID)) + << "ERROR: database error"; +} + +TEST_F(CAmMapHandlerTest,removeNonexistentMainConnectionFail) +{ + ASSERT_EQ(E_NON_EXISTENT,pDatabaseHandler.removeMainConnectionDB(34)) + << "ERROR: database error"; +} + +TEST_F(CAmMapHandlerTest,removeNonexistentSource) +{ + ASSERT_EQ(E_NON_EXISTENT,pDatabaseHandler.removeSourceDB(3)) + << "ERROR: database error"; +} + +TEST_F(CAmMapHandlerTest,removeNonexistentSink) +{ + ASSERT_EQ(E_NON_EXISTENT,pDatabaseHandler.removeSinkDB(2)) + << "ERROR: database error"; +} + +TEST_F(CAmMapHandlerTest,removeNonexistentGateway) +{ + ASSERT_EQ(E_NON_EXISTENT,pDatabaseHandler.removeGatewayDB(12)) + << "ERROR: database error"; +} + +TEST_F(CAmMapHandlerTest,removeNonexistentConverter) +{ + ASSERT_EQ(E_NON_EXISTENT,pDatabaseHandler.removeConverterDB(12)) + << "ERROR: database error"; +} + +TEST_F(CAmMapHandlerTest,registerGatewayCorrect) +{ + //initialize gateway + std::vector<am_Gateway_s> returnList; + am_Gateway_s gateway, gateway1, gateway2; + am_gatewayID_t gatewayID = 0, gatewayID1 = 0, gatewayID2 = 0; + + pCF.createGateway(gateway); + pCF.createGateway(gateway1); + gateway1.gatewayID = 20; + pCF.createGateway(gateway2); + am_Sink_s sink; + am_Source_s source; + am_sinkID_t sinkID; + am_sourceID_t sourceID; + pCF.createSink(sink); + pCF.createSource(source); + sink.sinkID = 1; + source.sourceID = 2; + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK,pDatabaseHandler.enterGatewayDB(gateway,gatewayID)) + << "ERROR: database error"; + ASSERT_EQ(DYNAMIC_ID_BOUNDARY,gatewayID) + << "ERROR: domainID zero"; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)) + << "ERROR: database error"; + ASSERT_EQ(gateway1.gatewayID,gatewayID1) + << "ERROR: domainID zero"; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterGatewayDB(gateway2,gatewayID2)) + << "ERROR: database error"; + ASSERT_EQ(DYNAMIC_ID_BOUNDARY+1,gatewayID2) + << "ERROR: domainID zero"; + + //now check if we read out the correct values + ASSERT_EQ(E_OK, pDatabaseHandler.getListGateways(returnList)); + std::vector<am_Gateway_s>::iterator listIterator = returnList.begin(); + + for (; listIterator < returnList.end(); ++listIterator) + { + if (listIterator->gatewayID == gatewayID) + { + ASSERT_TRUE(pCF.compareGateway(listIterator, gateway)); + } + + if (listIterator->gatewayID == gatewayID1) + { + ASSERT_TRUE(pCF.compareGateway(listIterator, gateway1)); + } + + if (listIterator->gatewayID == gatewayID2) + { + ASSERT_TRUE(pCF.compareGateway(listIterator, gateway2)); + } + } +} + +TEST_F(CAmMapHandlerTest,registerConverterCorrect) +{ + //initialize gateway + std::vector<am_Converter_s> returnList; + am_Converter_s gateway, gateway1, gateway2; + am_converterID_t gatewayID = 0, gatewayID1 = 0, gatewayID2 = 0; + + pCF.createConverter(gateway); + pCF.createConverter(gateway1); + gateway1.converterID = 20; + pCF.createConverter(gateway2); + am_Sink_s sink; + am_Source_s source; + am_sinkID_t sinkID; + am_sourceID_t sourceID; + pCF.createSink(sink); + pCF.createSource(source); + sink.sinkID = 1; + source.sourceID = 2; + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK,pDatabaseHandler.enterConverterDB(gateway,gatewayID)) + << "ERROR: database error"; + ASSERT_EQ(DYNAMIC_ID_BOUNDARY,gatewayID) + << "ERROR: domainID zero"; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterConverterDB(gateway1,gatewayID1)) + << "ERROR: database error"; + ASSERT_EQ(gateway1.converterID,gatewayID1) + << "ERROR: domainID zero"; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterConverterDB(gateway2,gatewayID2)) + << "ERROR: database error"; + ASSERT_EQ(DYNAMIC_ID_BOUNDARY+1,gatewayID2) + << "ERROR: domainID zero"; + + //now check if we read out the correct values + ASSERT_EQ(E_OK, pDatabaseHandler.getListConverters(returnList)); + std::vector<am_Converter_s>::iterator listIterator = returnList.begin(); + + for (; listIterator < returnList.end(); ++listIterator) + { + if (listIterator->converterID == gatewayID) + { + ASSERT_TRUE(pCF.compareConverter(listIterator, gateway)); + } + + if (listIterator->converterID == gatewayID1) + { + ASSERT_TRUE(pCF.compareConverter(listIterator, gateway1)); + } + + if (listIterator->converterID == gatewayID2) + { + ASSERT_TRUE(pCF.compareConverter(listIterator, gateway2)); + } + } +} + +TEST_F(CAmMapHandlerTest,getGatewayInfo) +{ + + + //initialize gateway + std::vector<am_Gateway_s> returnList; + am_Gateway_s gateway, gateway1, gateway2; + am_gatewayID_t gatewayID = 0, gatewayID1 = 0, gatewayID2 = 0; + + pCF.createGateway(gateway); + pCF.createGateway(gateway1); + gateway1.gatewayID = 20; + pCF.createGateway(gateway2); + am_Sink_s sink; + am_Source_s source; + am_sinkID_t sinkID; + am_sourceID_t sourceID; + pCF.createSink(sink); + pCF.createSource(source); + sink.sinkID = 1; + source.sourceID = 2; + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK,pDatabaseHandler.enterGatewayDB(gateway,gatewayID)) + << "ERROR: database error"; + ASSERT_EQ(DYNAMIC_ID_BOUNDARY,gatewayID) + << "ERROR: domainID zero"; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)) + << "ERROR: database error"; + ASSERT_EQ(gateway1.gatewayID,gatewayID1) + << "ERROR: domainID zero"; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterGatewayDB(gateway2,gatewayID2)) + << "ERROR: database error"; + ASSERT_EQ(DYNAMIC_ID_BOUNDARY+1,gatewayID2) + << "ERROR: domainID zero"; + + //now check if we read out the correct values + ASSERT_EQ(E_OK, pDatabaseHandler.getListGateways(returnList)); + std::vector<am_Gateway_s>::iterator listIterator = returnList.begin(); + + for (; listIterator < returnList.end(); ++listIterator) + { + if (listIterator->gatewayID == gatewayID) + { + ASSERT_TRUE(pCF.compareGateway(listIterator, gateway)); + } + + if (listIterator->gatewayID == gatewayID1) + { + ASSERT_TRUE(pCF.compareGateway(listIterator, gateway1)); + } + + if (listIterator->gatewayID == gatewayID2) + { + ASSERT_TRUE(pCF.compareGateway(listIterator, gateway2)); + } + } + + am_Gateway_s gatewayInfo; + ASSERT_EQ(E_OK, pDatabaseHandler.getGatewayInfoDB(20,gatewayInfo)); + ASSERT_TRUE(pCF.compareGateway1(gateway1,gatewayInfo)); + +} + +TEST_F(CAmMapHandlerTest,getConverterInfo) +{ + //initialize gateway + std::vector<am_Converter_s> returnList; + am_Converter_s gateway, gateway1, gateway2; + am_converterID_t gatewayID = 0, gatewayID1 = 0, gatewayID2 = 0; + + pCF.createConverter(gateway); + pCF.createConverter(gateway1); + gateway1.converterID = 20; + pCF.createConverter(gateway2); + am_Sink_s sink; + am_Source_s source; + am_sinkID_t sinkID; + am_sourceID_t sourceID; + pCF.createSink(sink); + pCF.createSource(source); + sink.sinkID = 1; + source.sourceID = 2; + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK,pDatabaseHandler.enterConverterDB(gateway,gatewayID)) + << "ERROR: database error"; + ASSERT_EQ(DYNAMIC_ID_BOUNDARY,gatewayID) + << "ERROR: domainID zero"; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterConverterDB(gateway1,gatewayID1)) + << "ERROR: database error"; + ASSERT_EQ(gateway1.converterID,gatewayID1) + << "ERROR: domainID zero"; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterConverterDB(gateway2,gatewayID2)) + << "ERROR: database error"; + ASSERT_EQ(DYNAMIC_ID_BOUNDARY+1,gatewayID2) + << "ERROR: domainID zero"; + + //now check if we read out the correct values + ASSERT_EQ(E_OK, pDatabaseHandler.getListConverters(returnList)); + std::vector<am_Converter_s>::iterator listIterator = returnList.begin(); + + for (; listIterator < returnList.end(); ++listIterator) + { + if (listIterator->converterID == gatewayID) + { + ASSERT_TRUE(pCF.compareConverter(listIterator, gateway)); + } + + if (listIterator->converterID == gatewayID1) + { + ASSERT_TRUE(pCF.compareConverter(listIterator, gateway1)); + } + + if (listIterator->converterID == gatewayID2) + { + ASSERT_TRUE(pCF.compareConverter(listIterator, gateway2)); + } + } + + am_Converter_s gatewayInfo; + ASSERT_EQ(E_OK, pDatabaseHandler.getConverterInfoDB(20,gatewayInfo)); + ASSERT_TRUE(pCF.compareConverter1(gateway1,gatewayInfo)); + +} + +TEST_F(CAmMapHandlerTest,enterSinkThatAlreadyExistFail) +{ + //fill the connection database + am_Sink_s staticSink, SecondSink; + am_sinkID_t staticSinkID, SecondSinkID; + + pCF.createSink(staticSink); + staticSink.sinkID = 43; + staticSink.name = "Static"; + + + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(staticSink,staticSinkID)) + << "ERROR: database error"; + ASSERT_EQ(staticSink.sinkID,staticSinkID) + << "ERROR: ID not the one given in staticSink"; + + pCF.createSink(SecondSink); + SecondSink.sinkID = 43; + SecondSink.name = "SecondSink"; + + ASSERT_EQ(E_ALREADY_EXISTS,pDatabaseHandler.enterSinkDB(SecondSink,SecondSinkID)) + << "ERROR: database error"; +} + +TEST_F(CAmMapHandlerTest,enterSourcesThatAlreadyExistFail) +{ + //fill the connection database + am_Source_s staticSource, SecondSource; + am_sourceID_t staticSourceID, SecondSourceID; + pCF.createSource(staticSource); + staticSource.sourceID = 4; + + + ASSERT_EQ(E_OK,pDatabaseHandler.enterSourceDB(staticSource,staticSourceID)) + << "ERROR: database error"; + ASSERT_EQ(staticSource.sourceID,staticSourceID) + << "ERROR: ID not the one given in staticSource"; + + pCF.createSource(SecondSource); + SecondSource.sourceID = 4; + + ASSERT_EQ(E_ALREADY_EXISTS,pDatabaseHandler.enterSourceDB(SecondSource,SecondSourceID)) + << "ERROR: database error"; +} + +TEST_F(CAmMapHandlerTest,registerDomainCorrect) +{ + //initialize domain + std::vector<am_Domain_s> returnList; + am_Domain_s domain; + am_domainID_t domainID = 0; + pCF.createDomain(domain); + + ASSERT_EQ(E_OK,pDatabaseHandler.enterDomainDB(domain,domainID)) + << "ERROR: database error"; + ASSERT_NE(0,domainID) + << "ERROR: domainID zero"; + + //now check if we read out the correct values + ASSERT_EQ(E_OK, pDatabaseHandler.getListDomains(returnList)); + bool equal = true; + std::vector<am_Domain_s>::iterator listIterator = returnList.begin(); + for (; listIterator < returnList.end(); ++listIterator) + { + if (listIterator->domainID == domainID) + { + equal = equal && (listIterator->name.compare(domain.name) == 0) && (listIterator->busname.compare(domain.busname) == 0) && (listIterator->complete == domain.complete) && (listIterator->early == domain.early) && (listIterator->state == domain.state); + } + } + ASSERT_EQ(true, equal); +} + +TEST_F(CAmMapHandlerTest,registerDomainPredefined) +{ + //initialize domain + std::vector<am_Domain_s> returnList; + am_Domain_s domain; + am_domainID_t domainID = 10; + pCF.createDomain(domain); + + ASSERT_EQ(E_OK,pDatabaseHandler.enterDomainDB(domain,domainID)) + << "ERROR: database error"; + ASSERT_NE(10,domainID) + << "ERROR: domainID not predefined one"; + + //now check if we read out the correct values + ASSERT_EQ(E_OK, pDatabaseHandler.getListDomains(returnList)); + std::vector<am_Domain_s>::iterator listIterator = returnList.begin(); + for (; listIterator < returnList.end(); ++listIterator) + { + if (listIterator->domainID == domainID) + { + ASSERT_EQ(0, listIterator->name.compare(domain.name)); + ASSERT_EQ(0, listIterator->busname.compare(domain.busname)); + ASSERT_EQ(domain.complete, listIterator->complete); + ASSERT_EQ(domain.early, listIterator->early); + ASSERT_EQ(domain.state, listIterator->state); + } + } +} + +TEST_F(CAmMapHandlerTest,registerConnectionCorrect) +{ + am_Connection_s connection; + am_connectionID_t connectionID; + std::vector<am_Connection_s> returnList; + pCF.createConnection(connection); + + ASSERT_EQ(E_OK,pDatabaseHandler.enterConnectionDB(connection,connectionID)) + << "ERROR: database error";; + ASSERT_NE(0,connectionID) + << "ERROR: connectionID zero"; + + //now check if we read out the correct values + ASSERT_EQ(E_OK, pDatabaseHandler.changeConnectionFinal(connectionID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListConnections(returnList)); + std::vector<am_Connection_s>::iterator listIterator = returnList.begin(); + for (; listIterator < returnList.end(); ++listIterator) + { + if (listIterator->connectionID == connectionID) + { + ASSERT_EQ(connection.sourceID, listIterator->sourceID); + ASSERT_EQ(connection.sinkID, listIterator->sinkID); + ASSERT_EQ(connection.delay, listIterator->delay); + ASSERT_EQ(connection.connectionFormat, listIterator->connectionFormat); + } + } +} + +TEST_F(CAmMapHandlerTest,enterMainConnectionCorrect) +{ + am_mainConnectionID_t mainConnectionID; + am_MainConnection_s mainConnection; + createMainConnectionSetup(mainConnectionID, mainConnection); +} + +TEST_F(CAmMapHandlerTest,enterSinksCorrect) +{ + //fill the connection database + am_Sink_s staticSink, firstDynamicSink, secondDynamicSink; + am_sinkID_t staticSinkID, firstDynamicSinkID, secondDynamicSinkID; + std::vector<am_Sink_s> sinkList; + + pCF.createSink(staticSink); + staticSink.sinkID = 4; + + + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(staticSink,staticSinkID)) + << "ERROR: database error"; + ASSERT_EQ(staticSink.sinkID,staticSinkID) + << "ERROR: ID not the one given in staticSink"; + + pCF.createSink(firstDynamicSink); + firstDynamicSink.name = "firstdynamic"; + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(firstDynamicSink,firstDynamicSinkID)) + << "ERROR: database error"; + ASSERT_EQ(firstDynamicSinkID,DYNAMIC_ID_BOUNDARY) + << "ERROR: ID not the one given in firstDynamicSink"; + + pCF.createSink(secondDynamicSink); + secondDynamicSink.name = "seconddynamic"; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(secondDynamicSink,secondDynamicSinkID)) + << "ERROR: database error"; + ASSERT_NEAR(secondDynamicSinkID,DYNAMIC_ID_BOUNDARY,10) + << "ERROR: ID not the one given in secondDynamicSink"; + + //now read back and check the returns agains the given values + ASSERT_EQ(E_OK,pDatabaseHandler.getListSinks(sinkList)) + << "ERROR: database error"; + + std::vector<am_Sink_s>::iterator listIterator = sinkList.begin(); + for (; listIterator < sinkList.end(); ++listIterator) + { + if (listIterator->sinkID == staticSinkID) + { + ASSERT_TRUE(pCF.compareSink(listIterator, staticSink)); + } + + if (listIterator->sinkID == firstDynamicSinkID) + { + ASSERT_TRUE(pCF.compareSink(listIterator, firstDynamicSink)); + } + + if (listIterator->sinkID == secondDynamicSinkID) + { + ASSERT_TRUE(pCF.compareSink(listIterator, secondDynamicSink)); + } + } +} + +TEST_F(CAmMapHandlerTest,enterNotificationConfigurationCorrect) +{ + am_Sink_s testSinkData, readoutData; + pCF.createSink(testSinkData); + testSinkData.sinkID = 4; + am_sinkID_t sinkID; + std::vector<am_Sink_s> listSinks; + + am_NotificationConfiguration_s notify; + notify.type=NT_UNKNOWN; + notify.status=NS_CHANGE; + notify.parameter=25; + testSinkData.listNotificationConfigurations.push_back(notify); + + //enter the sink in the database + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(testSinkData,sinkID)) + << "ERROR: database error"; + + //read it again + ASSERT_EQ(E_OK,pDatabaseHandler.getListSinks(listSinks)) + << "ERROR: database error"; + + ASSERT_EQ(listSinks.begin()->listNotificationConfigurations[2].parameter,notify.parameter); + ASSERT_EQ(listSinks.begin()->listNotificationConfigurations[2].status,notify.status); + ASSERT_EQ(listSinks.begin()->listNotificationConfigurations[2].type,notify.type); + + ASSERT_EQ(E_OK,pDatabaseHandler.getSinkInfoDB(testSinkData.sinkID,readoutData)) + << "ERROR: database error"; + + ASSERT_EQ(readoutData.listNotificationConfigurations[2].parameter,notify.parameter); + ASSERT_EQ(readoutData.listNotificationConfigurations[2].status,notify.status); + ASSERT_EQ(readoutData.listNotificationConfigurations[2].type,notify.type); + +} + +TEST_F(CAmMapHandlerTest,enterMainNotificationConfigurationCorrect) +{ + am_Sink_s testSinkData; + pCF.createSink(testSinkData); + testSinkData.sinkID = 4; + am_sinkID_t sinkID; + std::vector<am_Sink_s> listSinks; + + am_NotificationConfiguration_s notify; + notify.type=NT_UNKNOWN; + notify.status=NS_CHANGE; + notify.parameter=25; + + testSinkData.listMainNotificationConfigurations.push_back(notify); + + //enter the sink in the database + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(testSinkData,sinkID)) + << "ERROR: database error"; + + //read it again + ASSERT_EQ(E_OK,pDatabaseHandler.getListSinks(listSinks)) + << "ERROR: database error"; + + ASSERT_EQ(listSinks.begin()->listMainNotificationConfigurations[2].parameter,notify.parameter); + ASSERT_EQ(listSinks.begin()->listMainNotificationConfigurations[2].status,notify.status); + ASSERT_EQ(listSinks.begin()->listMainNotificationConfigurations[2].type,notify.type); +} + +TEST_F(CAmMapHandlerTest,removeNotificationsSink) +{ + am_Sink_s testSinkData; + pCF.createSink(testSinkData); + testSinkData.sinkID = 4; + am_sinkID_t sinkID; + std::vector<am_Sink_s> listSinks; + + am_NotificationConfiguration_s notify; + notify.type=NT_UNKNOWN; + notify.status=NS_CHANGE; + notify.parameter=25; + + testSinkData.listMainNotificationConfigurations.push_back(notify); + + //enter the sink in the database + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(testSinkData,sinkID)) + << "ERROR: database error"; + + //read it again + ASSERT_EQ(E_OK,pDatabaseHandler.getListSinks(listSinks)) + << "ERROR: database error"; + + ASSERT_EQ(listSinks.begin()->listMainNotificationConfigurations[2].parameter,notify.parameter); + ASSERT_EQ(listSinks.begin()->listMainNotificationConfigurations[2].status,notify.status); + ASSERT_EQ(listSinks.begin()->listMainNotificationConfigurations[2].type,notify.type); + + //now we remove the sink + ASSERT_EQ(E_OK,pDatabaseHandler.removeSinkDB(sinkID)); +} + +TEST_F(CAmMapHandlerTest,removeNotificationsSource) +{ + am_Source_s testSourceData; + pCF.createSource(testSourceData); + testSourceData.sourceID = 4; + am_sourceID_t sourceID; + std::vector<am_Source_s> listSources; + + am_NotificationConfiguration_s notify; + notify.type=NT_UNKNOWN; + notify.status=NS_CHANGE; + notify.parameter=25; + + testSourceData.listMainNotificationConfigurations.push_back(notify); + + //enter the sink in the database + ASSERT_EQ(E_OK,pDatabaseHandler.enterSourceDB(testSourceData,sourceID)) + << "ERROR: database error"; + + //read it again + ASSERT_EQ(E_OK,pDatabaseHandler.getListSources(listSources)) + << "ERROR: database error"; + + ASSERT_EQ(listSources.begin()->listMainNotificationConfigurations[2].parameter,notify.parameter); + ASSERT_EQ(listSources.begin()->listMainNotificationConfigurations[2].status,notify.status); + ASSERT_EQ(listSources.begin()->listMainNotificationConfigurations[2].type,notify.type); + + //now we remove the sink + ASSERT_EQ(E_OK,pDatabaseHandler.removeSourceDB(sourceID)); +} + +TEST_F(CAmMapHandlerTest,getMainNotificationsSink) +{ + am_Sink_s testSinkData; + pCF.createSink(testSinkData); + testSinkData.sinkID = 4; + am_sinkID_t sinkID; + std::vector<am_Sink_s> listSinks; + std::vector<am_NotificationConfiguration_s>returnList; + + am_NotificationConfiguration_s notify; + notify.type=NT_UNKNOWN; + notify.status=NS_CHANGE; + notify.parameter=25; + + testSinkData.listMainNotificationConfigurations.push_back(notify); + + am_NotificationConfiguration_s notify1; + notify1.type=NT_UNKNOWN; + notify1.status=NS_PERIODIC; + notify1.parameter=5; + + testSinkData.listMainNotificationConfigurations.push_back(notify1); + + //enter the sink in the database + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(testSinkData,sinkID)) + << "ERROR: database error"; + + //read it again + ASSERT_EQ(E_OK,pDatabaseHandler.getListMainSinkNotificationConfigurations(sinkID,returnList)) + << "ERROR: database error"; + + std::equal(testSinkData.listMainNotificationConfigurations.begin(),testSinkData.listMainNotificationConfigurations.end(),returnList.begin(),equalNotificationConfiguration); + +} + +TEST_F(CAmMapHandlerTest,getMainNotificationsSources) +{ + am_Source_s testSourceData; + pCF.createSource(testSourceData); + testSourceData.sourceID = 4; + am_sourceID_t sourceID; + std::vector<am_Source_s> listSources; + std::vector<am_NotificationConfiguration_s>returnList; + + am_NotificationConfiguration_s notify; + notify.type=NT_UNKNOWN; + notify.status=NS_CHANGE; + notify.parameter=25; + + testSourceData.listMainNotificationConfigurations.push_back(notify); + + am_NotificationConfiguration_s notify1; + notify1.type=NT_UNKNOWN; + notify1.status=NS_PERIODIC; + notify1.parameter=5; + + testSourceData.listMainNotificationConfigurations.push_back(notify1); + + //enter the sink in the database + ASSERT_EQ(E_OK,pDatabaseHandler.enterSourceDB(testSourceData,sourceID)) + << "ERROR: database error"; + + //read it again + ASSERT_EQ(E_OK,pDatabaseHandler.getListMainSourceNotificationConfigurations(sourceID,returnList)) + << "ERROR: database error"; + + std::equal(testSourceData.listMainNotificationConfigurations.begin(),testSourceData.listMainNotificationConfigurations.end(),returnList.begin(),equalNotificationConfiguration); + +} + +TEST_F(CAmMapHandlerTest,changeMainNotificationsSources) +{ + am_Source_s testSourceData; + pCF.createSource(testSourceData); + testSourceData.sourceID = 4; + am_sourceID_t sourceID; + std::vector<am_Source_s> listSources; + std::vector<am_NotificationConfiguration_s>returnList,returnList1; + + //enter the sink in the database + ASSERT_EQ(E_OK,pDatabaseHandler.enterSourceDB(testSourceData,sourceID)) + << "ERROR: database error"; + + //read it again + ASSERT_EQ(E_OK,pDatabaseHandler.getListMainSourceNotificationConfigurations(sourceID,returnList)) + << "ERROR: database error"; + + ASSERT_EQ(true, std::equal(testSourceData.listMainNotificationConfigurations.begin(), + testSourceData.listMainNotificationConfigurations.end(), + returnList.begin(), + equalNotificationConfiguration)); + + //change notification which is not available + am_NotificationConfiguration_s notify; + notify.type=NT_UNKNOWN; + notify.status=NS_CHANGE; + notify.parameter=10; + ASSERT_EQ(E_NO_CHANGE,pDatabaseHandler.changeMainSourceNotificationConfigurationDB(sourceID,notify)); + //change a setting + notify.type=NT_TEST_2; + ASSERT_EQ(E_OK,pDatabaseHandler.changeMainSourceNotificationConfigurationDB(sourceID,notify)); + + ASSERT_EQ(E_OK,pDatabaseHandler.getListMainSourceNotificationConfigurations(sourceID,returnList1)) + << "ERROR: database error"; + + ASSERT_EQ(returnList1[1].parameter,notify.parameter); + ASSERT_EQ(returnList1[1].status,notify.status); + ASSERT_EQ(returnList1[1].type,notify.type); + +} + +TEST_F(CAmMapHandlerTest,changeMainNotificationsSink) +{ + am_Sink_s testSinkData; + pCF.createSink(testSinkData); + testSinkData.sinkID = 4; + am_sinkID_t sinkID; + std::vector<am_Sink_s> listSinks; + std::vector<am_NotificationConfiguration_s>returnList,returnList1; + + //enter the sink in the database + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(testSinkData,sinkID)) + << "ERROR: database error"; + + //read it again + ASSERT_EQ(E_OK,pDatabaseHandler.getListMainSinkNotificationConfigurations(sinkID,returnList)) + << "ERROR: database error"; + + std::equal(testSinkData.listMainNotificationConfigurations.begin(),testSinkData.listMainNotificationConfigurations.end(),returnList.begin(),equalNotificationConfiguration); + + //change notification which is not available + am_NotificationConfiguration_s notify; + notify.type=NT_UNKNOWN; + notify.status=NS_CHANGE; + notify.parameter=27; + ASSERT_EQ(E_NO_CHANGE,pDatabaseHandler.changeMainSinkNotificationConfigurationDB(sinkID,notify)) + << "ERROR: database error"; + //change a setting + notify.type=NT_TEST_2; + ASSERT_EQ(E_OK,pDatabaseHandler.changeMainSinkNotificationConfigurationDB(sinkID,notify)) + << "ERROR: database error"; + + ASSERT_EQ(E_OK,pDatabaseHandler.getListMainSinkNotificationConfigurations(sinkID,returnList1)) + << "ERROR: database error"; + + ASSERT_EQ(returnList1[1].parameter,notify.parameter); + ASSERT_EQ(returnList1[1].status,notify.status); + ASSERT_EQ(returnList1[1].type,notify.type); +} + +TEST_F(CAmMapHandlerTest, peekDomain_2) +{ + std::vector<am_Domain_s> listDomains; + am_Domain_s domain; + am_domainID_t domainID; + am_domainID_t domain2ID; + pCF.createDomain(domain); + ASSERT_EQ(E_OK,pDatabaseHandler.peekDomain(std::string("newdomain"),domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListDomains(listDomains)); + ASSERT_TRUE(listDomains.empty()); + ASSERT_EQ(domainID, DYNAMIC_ID_BOUNDARY); + + domain.name = "anotherdomain"; + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domain2ID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListDomains(listDomains)); + ASSERT_EQ(domain2ID, DYNAMIC_ID_BOUNDARY+1); + + domain.name = "newdomain"; + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domain2ID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListDomains(listDomains)); + ASSERT_EQ(domainID, domain2ID); // FAILS, ID is 2 instead of 1 + bool containsDomainID = std::find_if(listDomains.begin(), listDomains.end(), [&](const am_Domain_s & ref) { + return ref.domainID==domainID; + })!=listDomains.end(); + ASSERT_TRUE(containsDomainID); +} + +TEST_F(CAmMapHandlerTest, connectionIDBoundary) +{ + am_Sink_s sink; + am_Source_s source; + am_Connection_s connection; + connection.delay = -1; + connection.connectionFormat = CF_GENIVI_ANALOG; + connection.connectionID = 0; + am_sinkID_t forgetSink; + am_sourceID_t forgetSource; + am_connectionID_t connectionID; + for (uint16_t i = 1; i < TEST_MAX_SINK_ID; i++) + { + pCF.createSink(sink); + sink.sinkID = 0; + sink.name = "sink" + int2string(i); + sink.domainID = 4; + pCF.createSource(source); + source.sourceID = 0; + source.name = "source" + int2string(i); + source.domainID = 4; + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink, forgetSink)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source, forgetSource)); + connection.sinkID = forgetSink; + connection.sourceID = forgetSource; + if( i < TEST_MAX_CONNECTION_ID ) + { + ASSERT_EQ(E_OK, pDatabaseHandler.enterConnectionDB(connection,connectionID)); + ASSERT_EQ(E_OK, pDatabaseHandler.changeConnectionFinal(connectionID)); + ASSERT_EQ(i, connectionID); + } + } + std::vector<am_Connection_s> connectionList; + ASSERT_EQ(E_OK, pDatabaseHandler.getListConnections(connectionList)); + ASSERT_EQ(TEST_MAX_CONNECTION_ID-1, static_cast<int>(connectionList.size())); + ASSERT_EQ(E_UNKNOWN, pDatabaseHandler.enterConnectionDB(connection,connectionID)); + logInfo("here"); + ASSERT_EQ(0, connectionID); + + ASSERT_EQ(E_OK, pDatabaseHandler.removeConnection(10)); + ASSERT_EQ(E_OK, pDatabaseHandler.removeConnection(12)); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterConnectionDB(connection,connectionID)); + ASSERT_EQ(10, connectionID); + connection.sinkID = 77; + connection.sourceID = 77; + ASSERT_EQ(E_OK, pDatabaseHandler.enterConnectionDB(connection,connectionID)); + ASSERT_EQ(12, connectionID); + ASSERT_EQ(E_UNKNOWN, pDatabaseHandler.enterConnectionDB(connection,connectionID)); + ASSERT_EQ(0, connectionID); +} + +TEST_F(CAmMapHandlerTest, mainConnectionIDBoundary) +{ + am_Sink_s sink; + am_Source_s source; + am_Connection_s connection; + connection.delay = -1; + connection.connectionFormat = CF_GENIVI_ANALOG; + connection.connectionID = 0; + am_sinkID_t forgetSink; + am_sourceID_t forgetSource; + am_connectionID_t connectionID; + std::vector<am_connectionID_t> connectionIDList; + for (uint16_t i = 1; i < TEST_MAX_SINK_ID; i++) + { + pCF.createSink(sink); + sink.sinkID = 0; + sink.name = "sink" + int2string(i); + sink.domainID = 4; + pCF.createSource(source); + source.sourceID = 0; + source.name = "source" + int2string(i); + source.domainID = 4; + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink, forgetSink)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source, forgetSource)); + connection.sinkID = forgetSink; + connection.sourceID = forgetSource; + if( i < TEST_MAX_CONNECTION_ID ) + { + ASSERT_EQ(E_OK, pDatabaseHandler.enterConnectionDB(connection,connectionID)); + ASSERT_EQ(E_OK, pDatabaseHandler.changeConnectionFinal(connectionID)); + ASSERT_EQ(i, connectionID); + connectionIDList.push_back(i); + } + } + std::vector<am_Connection_s> connectionList; + ASSERT_EQ(E_OK, pDatabaseHandler.getListConnections(connectionList)); + ASSERT_EQ(TEST_MAX_CONNECTION_ID-1, static_cast<int>(connectionList.size())); + + //create a mainConnection + + am_MainConnection_s mainConnection; + am_mainConnectionID_t mainConnectionID; + mainConnection.listConnectionID = connectionIDList; + mainConnection.mainConnectionID = 0; + mainConnection.connectionState = CS_CONNECTED; + mainConnection.delay = -1; + + for (uint16_t i = 1; i < TEST_MAX_MAINCONNECTION_ID; i++) + { + mainConnection.sinkID = DYNAMIC_ID_BOUNDARY + i; + mainConnection.sourceID = DYNAMIC_ID_BOUNDARY + i; + ASSERT_EQ(E_OK, pDatabaseHandler.enterMainConnectionDB(mainConnection,mainConnectionID)); + ASSERT_EQ(i, mainConnectionID); + } + ASSERT_EQ(E_OK, pDatabaseHandler.removeMainConnectionDB(10)); + ASSERT_EQ(E_OK, pDatabaseHandler.removeMainConnectionDB(12)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterMainConnectionDB(mainConnection,mainConnectionID)); + ASSERT_EQ(10, mainConnectionID); + mainConnection.sinkID = 77; + mainConnection.sourceID = 77; + ASSERT_EQ(E_OK, pDatabaseHandler.enterMainConnectionDB(mainConnection,mainConnectionID)); + ASSERT_EQ(12, mainConnectionID); + ASSERT_EQ(E_UNKNOWN, pDatabaseHandler.enterMainConnectionDB(mainConnection,mainConnectionID)); + ASSERT_EQ(0, mainConnectionID); +} + +TEST_F(CAmMapHandlerTest, increaseID) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + for (uint16_t i = 0; i < TEST_MAX_SINK_ID; i++) + { + pCF.createSink(sink); + sink.sinkID = 0; + sink.name = "sink" + int2string(i); + sink.domainID = 4; + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink, sinkID)); + ASSERT_EQ(DYNAMIC_ID_BOUNDARY+i, sinkID); + } + ASSERT_EQ(E_UNKNOWN, pDatabaseHandler.enterSinkDB(sink, sinkID)); + + ASSERT_EQ(E_OK, pDatabaseHandler.removeSinkDB(DYNAMIC_ID_BOUNDARY+10)); + ASSERT_EQ(E_OK, pDatabaseHandler.removeSinkDB(DYNAMIC_ID_BOUNDARY+12)); + + ASSERT_EQ(E_UNKNOWN, pDatabaseHandler.enterSinkDB(sink, sinkID)); + ASSERT_EQ(E_UNKNOWN, pDatabaseHandler.enterSinkDB(sink, sinkID)); + ASSERT_EQ(E_UNKNOWN, pDatabaseHandler.enterSinkDB(sink, sinkID)); +} + + +CAmMapHandlerObserverCallbacksTest::CAmMapHandlerObserverCallbacksTest() : + mMockObserver(&pCommandSender, &pRoutingSender, &pSocketHandler) +{ + pDatabaseHandler.registerObserver(&mMockObserver); +} + +CAmMapHandlerObserverCallbacksTest::~CAmMapHandlerObserverCallbacksTest() +{ +} + +MATCHER_P(IsDomainDataEqualTo, value, "") { + auto lh = arg; + return lh.domainID == value.domainID && + lh.name == value.name && + lh.nodename == value.nodename && + lh.early == value.early && + lh.complete == value.complete && + lh.state == value.state; +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, peek_enter_removeDomain) +{ + std::vector<am_Domain_s> listDomains; + am_Domain_s domain; + am_domainID_t domainID; + am_domainID_t domain2ID; + pCF.createDomain(domain); + ASSERT_EQ(E_OK,pDatabaseHandler.peekDomain(std::string("newdomain"), domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListDomains(listDomains)); + ASSERT_TRUE(listDomains.empty()); + ASSERT_EQ(domainID, DYNAMIC_ID_BOUNDARY); + + domain.name = "anotherdomain"; + const am_Domain_s expDomain1 = {DYNAMIC_ID_BOUNDARY+1, domain.name, domain.busname, domain.nodename, domain.early, domain.complete, domain.state}; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newDomain(IsDomainDataEqualTo(expDomain1))).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domain2ID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListDomains(listDomains)); + ASSERT_EQ(domain2ID, DYNAMIC_ID_BOUNDARY+1); + EXPECT_TRUE(Mock::VerifyAndClearExpectations(MockDatabaseObserver::getMockObserverObject())); + domain.name = "newdomain"; + const am_Domain_s expDomain2 = {DYNAMIC_ID_BOUNDARY, domain.name, domain.busname, domain.nodename, domain.early, domain.complete, domain.state}; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newDomain(IsDomainDataEqualTo(expDomain2))).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domain2ID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListDomains(listDomains)); + ASSERT_EQ(domainID, domain2ID); // FAILS, ID is 2 instead of 1 + bool containsDomainID = std::find_if(listDomains.begin(), listDomains.end(), [&](const am_Domain_s & ref) { + return ref.domainID==domainID; + })!=listDomains.end(); + ASSERT_TRUE(containsDomainID); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), removeDomain(domainID)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.removeDomainDB(domainID))<< "ERROR: database error"; + EXPECT_TRUE(Mock::VerifyAndClearExpectations(MockDatabaseObserver::getMockObserverObject())); +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, peek_enter_update_removeSource) +{ + std::vector<am_Source_s> listSources; + am_sourceID_t sourceID; + am_sourceID_t source2ID; + am_sourceID_t source3ID; + am_Source_s source; + pCF.createSource(source); + + //peek a source that does not exits + + ASSERT_EQ(E_OK, pDatabaseHandler.peekSource(std::string("newsource"),sourceID)); + + //peek a second source that does not exits + + ASSERT_EQ(E_OK, pDatabaseHandler.peekSource(std::string("newsource2"),source2ID)); + + //make sure they are is not in the list + ASSERT_EQ(E_OK, pDatabaseHandler.getListSources(listSources)); + ASSERT_TRUE(listSources.empty()); + ASSERT_EQ(sourceID, DYNAMIC_ID_BOUNDARY); + + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSource(Field(&am_Source_s::sourceID, DYNAMIC_ID_BOUNDARY+2))).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,source3ID)); + ASSERT_EQ(source3ID, DYNAMIC_ID_BOUNDARY+2); + + source.name = "newsource"; + //now enter the source with the same name than the first peek and make sure it does not get a new ID + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSource(Field(&am_Source_s::sourceID, DYNAMIC_ID_BOUNDARY))).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,source3ID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSources(listSources)); + ASSERT_EQ(sourceID, source3ID); + bool containsSourceID = std::find_if(listSources.begin(), listSources.end(), [&](const am_Source_s & ref) { + return ref.sourceID==sourceID; + })!=listSources.end(); + ASSERT_TRUE(containsSourceID); + + std::vector<am_SoundProperty_s> listSoundProperties; + std::vector<am_CustomAvailabilityReason_t> listConnectionFormats; + std::vector<am_MainSoundProperty_s> listMainSoundProperties; +#ifndef WITH_DATABASE_CHANGE_CHECK + //check no change + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sourceUpdated(sourceID, _, _, _)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.changeSourceDB(sourceID, source.sourceClassID, listSoundProperties, listConnectionFormats, listMainSoundProperties))<< "ERROR: database error"; +#else + //check no change + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sourceUpdated(sourceID, _, _, _)).Times(0); + ASSERT_EQ(E_OK,pDatabaseHandler.changeSourceDB(sourceID, source.sourceClassID, listSoundProperties, listConnectionFormats, listMainSoundProperties))<< "ERROR: database error"; + //check change of class id + source.sourceClassID++; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sourceUpdated(sourceID, source.sourceClassID, _, _)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.changeSourceDB(sourceID, source.sourceClassID, listSoundProperties, listConnectionFormats, listMainSoundProperties))<< "ERROR: database error"; + //check change of main sound properties + am_MainSoundProperty_s mainSoundProperties; + mainSoundProperties.type = MSP_GENIVI_TREBLE; + mainSoundProperties.value = 0; + listMainSoundProperties.push_back(mainSoundProperties); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sourceUpdated(sourceID, _, _, _)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.changeSourceDB(sourceID, source.sourceClassID, listSoundProperties, listConnectionFormats, listMainSoundProperties))<< "ERROR: database error"; +#endif + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), removedSource(sourceID, _)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.removeSourceDB(sourceID))<< "ERROR: database error"; + EXPECT_TRUE(Mock::VerifyAndClearExpectations(MockDatabaseObserver::getMockObserverObject())); +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, peek_enter_update_removeSink) +{ + std::vector<am_Sink_s> listSinks; + am_sinkID_t sinkID; + am_sinkID_t sink2ID; + am_sinkID_t sink3ID; + am_Sink_s sink; + pCF.createSink(sink); + + //peek a sink that does not exits + + ASSERT_EQ(E_OK, pDatabaseHandler.peekSink(std::string("newsink"),sinkID)); + + //peek again + + ASSERT_EQ(E_OK, pDatabaseHandler.peekSink(std::string("nextsink"),sink2ID)); + + //make sure they are is not in the list + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + ASSERT_TRUE(listSinks.empty()); + ASSERT_EQ(sinkID, DYNAMIC_ID_BOUNDARY); + + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSink(Field(&am_Sink_s::sinkID, DYNAMIC_ID_BOUNDARY+2))).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sink3ID)); + ASSERT_EQ(sink3ID, DYNAMIC_ID_BOUNDARY+2); + + sink.name = "newsink"; + //now enter the sink with the same name than the first peek and make sure it does not get a new ID + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSink(Field(&am_Sink_s::sinkID, DYNAMIC_ID_BOUNDARY))).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sink3ID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + ASSERT_EQ(sinkID, sink3ID); + bool containsSourceID = std::find_if(listSinks.begin(), listSinks.end(), [&](const am_Sink_s & ref) { + return ref.sinkID==sinkID; + })!=listSinks.end(); + ASSERT_TRUE(containsSourceID); + + std::vector<am_SoundProperty_s> listSoundProperties; + std::vector<am_CustomAvailabilityReason_t> listConnectionFormats; + std::vector<am_MainSoundProperty_s> listMainSoundProperties; +#ifndef WITH_DATABASE_CHANGE_CHECK + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sinkUpdated(sinkID, _, _, _)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.changeSinkDB(sinkID, sink.sinkClassID, listSoundProperties, listConnectionFormats, listMainSoundProperties))<< "ERROR: database error"; +#else + //check no change + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sinkUpdated(sinkID, _, _, _)).Times(0); + ASSERT_EQ(E_OK,pDatabaseHandler.changeSinkDB(sinkID, sink.sinkClassID, listSoundProperties, listConnectionFormats, listMainSoundProperties))<< "ERROR: database error"; + //check change of class id + sink.sinkClassID++; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sinkUpdated(sinkID, sink.sinkClassID, _, _)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.changeSinkDB(sinkID, sink.sinkClassID, listSoundProperties, listConnectionFormats, listMainSoundProperties))<< "ERROR: database error"; + //check change of main sound properties + am_MainSoundProperty_s mainSoundProperties; + mainSoundProperties.type = MSP_GENIVI_TREBLE; + mainSoundProperties.value = 0; + listMainSoundProperties.push_back(mainSoundProperties); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sinkUpdated(sinkID, _, _, _)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.changeSinkDB(sinkID, sink.sinkClassID, listSoundProperties, listConnectionFormats, listMainSoundProperties))<< "ERROR: database error"; +#endif + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), removedSink(sinkID, _)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.removeSinkDB(sinkID))<< "ERROR: database error"; + EXPECT_TRUE(Mock::VerifyAndClearExpectations(MockDatabaseObserver::getMockObserverObject())); +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, peekSourceClassID) +{ + std::string sourceName("myClassID"); + am_sourceClass_t sourceClassID, peekID; + am_SourceClass_s sourceClass; + am_ClassProperty_s classProperty; + classProperty.classProperty = CP_GENIVI_SOURCE_TYPE; + classProperty.value = 13; + sourceClass.name = sourceName; + sourceClass.sourceClassID = 0; + sourceClass.listClassProperties.push_back(classProperty); + + //first we peek without an existing class + ASSERT_EQ(E_NON_EXISTENT, pDatabaseHandler.peekSourceClassID(sourceName,sourceClassID)); + + //now we enter the class into the database + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), numberOfSourceClassesChanged()).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceClassDB(sourceClassID,sourceClass)); + + //first we peek without an existing class + ASSERT_EQ(E_OK, pDatabaseHandler.peekSourceClassID(sourceName,peekID)); + ASSERT_EQ(sourceClassID, peekID); +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, peekSinkClassID) +{ + std::string sinkName("myClassID"); + am_sinkClass_t sinkClassID, peekID; + am_SinkClass_s sinkClass; + am_ClassProperty_s classProperty; + classProperty.classProperty = CP_GENIVI_SOURCE_TYPE; + classProperty.value = 13; + sinkClass.name = sinkName; + sinkClass.sinkClassID = 0; + sinkClass.listClassProperties.push_back(classProperty); + + //first we peek without an existing class + ASSERT_EQ(E_NON_EXISTENT, pDatabaseHandler.peekSinkClassID(sinkName,sinkClassID)); + + //now we enter the class into the database + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), numberOfSinkClassesChanged()).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkClassDB(sinkClass,sinkClassID)); + + //first we peek without an existing class + ASSERT_EQ(E_OK, pDatabaseHandler.peekSinkClassID(sinkName,peekID)); + ASSERT_EQ(sinkClassID, peekID); +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, enter_removeGateway) +{ + //initialize gateway + std::vector<am_Gateway_s> returnList; + am_Gateway_s gateway, gateway1, gateway2; + am_gatewayID_t gatewayID = 0, gatewayID1 = 0, gatewayID2 = 0; + pCF.createGateway(gateway); + pCF.createGateway(gateway1); + gateway1.gatewayID = 20; + pCF.createGateway(gateway2); + am_Sink_s sink; + am_Source_s source; + am_sinkID_t sinkID; + am_sourceID_t sourceID; + pCF.createSink(sink); + pCF.createSource(source); + sink.sinkID = 1; + source.sourceID = 2; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSink(_)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSource(_)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newGateway(Field(&am_Gateway_s::gatewayID, DYNAMIC_ID_BOUNDARY))).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.enterGatewayDB(gateway,gatewayID))<< "ERROR: database error"; + ASSERT_EQ(DYNAMIC_ID_BOUNDARY,gatewayID)<< "ERROR: domainID zero"; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newGateway(Field(&am_Gateway_s::gatewayID, 20))).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1))<< "ERROR: database error"; + ASSERT_EQ(gateway1.gatewayID,gatewayID1)<< "ERROR: domainID zero"; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newGateway(Field(&am_Gateway_s::gatewayID, DYNAMIC_ID_BOUNDARY+1))).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.enterGatewayDB(gateway2,gatewayID2))<< "ERROR: database error"; + ASSERT_EQ(DYNAMIC_ID_BOUNDARY+1,gatewayID2)<< "ERROR: domainID zero"; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), removeGateway(gatewayID2)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.removeGatewayDB(gatewayID2))<< "ERROR: database error"; +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, enter_removeConverter) +{ + //initialize gateway + std::vector<am_Converter_s> returnList; + am_Converter_s gateway, gateway1, gateway2; + am_converterID_t gatewayID = 0, gatewayID1 = 0, gatewayID2 = 0; + pCF.createConverter(gateway); + pCF.createConverter(gateway1); + gateway1.converterID = 20; + pCF.createConverter(gateway2); + am_Sink_s sink; + am_Source_s source; + am_sinkID_t sinkID; + am_sourceID_t sourceID; + pCF.createSink(sink); + pCF.createSource(source); + sink.sinkID = 1; + source.sourceID = 2; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSink(_)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSource(_)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newConverter(Field(&am_Converter_s::converterID, DYNAMIC_ID_BOUNDARY))).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.enterConverterDB(gateway,gatewayID))<< "ERROR: database error"; + ASSERT_EQ(DYNAMIC_ID_BOUNDARY,gatewayID)<< "ERROR: domainID zero"; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newConverter(Field(&am_Converter_s::converterID, 20))).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.enterConverterDB(gateway1,gatewayID1))<< "ERROR: database error"; + ASSERT_EQ(gateway1.converterID,gatewayID1)<< "ERROR: domainID zero"; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newConverter(Field(&am_Converter_s::converterID, DYNAMIC_ID_BOUNDARY+1))).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.enterConverterDB(gateway2,gatewayID2))<< "ERROR: database error"; + ASSERT_EQ(DYNAMIC_ID_BOUNDARY+1,gatewayID2)<< "ERROR: domainID zero"; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), removeConverter(gatewayID2)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.removeConverterDB(gatewayID2))<< "ERROR: database error"; +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, enter_removeCrossfader) +{ + am_Crossfader_s crossfader; + am_crossfaderID_t crossfaderID; + am_Sink_s sinkA, sinkB; + am_Source_s source; + am_sourceID_t sourceID; + am_sinkID_t sinkAID, sinkBID; + pCF.createSink(sinkA); + pCF.createSink(sinkB); + sinkB.name = "sinkB"; + pCF.createSource(source); + + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSource(_)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSink(_)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sinkA,sinkAID)); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSink(_)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sinkB,sinkBID)); + + crossfader.crossfaderID = 0; + crossfader.hotSink = HS_SINKA; + crossfader.sinkID_A = sinkAID; + crossfader.sinkID_B = sinkBID; + crossfader.sourceID = sourceID; + crossfader.name = "Crossfader"; + crossfader.hotSink = HS_UNKNOWN; + + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newCrossfader(Field(&am_Crossfader_s::crossfaderID, DYNAMIC_ID_BOUNDARY))).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterCrossfaderDB(crossfader,crossfaderID)); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), removeCrossfader(crossfaderID)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.removeCrossfaderDB(crossfaderID))<< "ERROR: database error"; +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, enter_update_removeMainConnection) +{ + am_mainConnectionID_t mainConnectionID; + am_MainConnection_s mainConnection; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSink(_)).Times(9); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSource(_)).Times(9); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newMainConnection(Field(&am_MainConnectionType_s::mainConnectionID, 1))).Times(1); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), mainConnectionStateChanged(1, CS_CONNECTED)).Times(1); +#ifndef WITH_DATABASE_CHANGE_CHECK + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), timingInformationChanged(1, _)).Times(1); +#else + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), timingInformationChanged(1, _)).Times(0); +#endif + createMainConnectionSetup(mainConnectionID, mainConnection); + + //change delay of first connection + am_timeSync_t delay = 20; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), timingInformationChanged(mainConnectionID, 20)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.changeConnectionTimingInformation(mainConnection.listConnectionID[0], delay)); +#ifdef WITH_DATABASE_CHANGE_CHECK + ASSERT_EQ(E_NO_CHANGE, pDatabaseHandler.changeConnectionTimingInformation(mainConnection.listConnectionID[0], delay)); +#endif + + //change delay of route + delay = 40; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), timingInformationChanged(mainConnectionID, 40)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.changeDelayMainConnection(delay, mainConnectionID)); +#ifdef WITH_DATABASE_CHANGE_CHECK + ASSERT_EQ(E_NO_CHANGE, pDatabaseHandler.changeDelayMainConnection(delay, mainConnectionID)); +#endif + + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), removedMainConnection(1)).Times(1); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), mainConnectionStateChanged(1, _)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.removeMainConnectionDB(mainConnectionID)) << "ERROR: database error"; +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, changeSinkAvailability) +{ + std::vector<am_Sink_s> listSinks; + am_Sink_s sink; + am_sinkID_t sinkID; + pCF.createSink(sink); + am_Availability_s availability; + availability.availability = A_UNKNOWN; + availability.availabilityReason = AR_GENIVI_TEMPERATURE; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSink(_)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sinkAvailabilityChanged(_, _)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.changeSinkAvailabilityDB(availability,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + ASSERT_EQ(availability.availability, listSinks[0].available.availability); + ASSERT_EQ(availability.availabilityReason, listSinks[0].available.availabilityReason); + +#ifdef WITH_DATABASE_CHANGE_CHECK + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sinkAvailabilityChanged(_, _)).Times(1); + ASSERT_EQ(E_NO_CHANGE, pDatabaseHandler.changeSinkAvailabilityDB(availability,sinkID)); + availability.availability = A_AVAILABLE; + availability.availabilityReason = AR_GENIVI_TEMPERATURE; + ASSERT_EQ(E_OK, pDatabaseHandler.changeSinkAvailabilityDB(availability,sinkID)); +#endif +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, changeSourceAvailability) +{ + std::vector<am_Source_s> listSources; + am_Source_s source; + am_sourceID_t sourceID; + pCF.createSource(source); + am_Availability_s availability; + availability.availability = A_UNKNOWN; + availability.availabilityReason = AR_GENIVI_TEMPERATURE; + source.visible = true; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSource(_)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sourceAvailabilityChanged(_, _)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.changeSourceAvailabilityDB(availability,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSources(listSources)); + ASSERT_EQ(availability.availability, listSources[0].available.availability); + ASSERT_EQ(availability.availabilityReason, listSources[0].available.availabilityReason); + +#ifdef WITH_DATABASE_CHANGE_CHECK + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sourceAvailabilityChanged(_, _)).Times(1); + ASSERT_EQ(E_NO_CHANGE, pDatabaseHandler.changeSourceAvailabilityDB(availability,sourceID)); + availability.availability = A_AVAILABLE; + availability.availabilityReason = AR_GENIVI_TEMPERATURE; + ASSERT_EQ(E_OK, pDatabaseHandler.changeSourceAvailabilityDB(availability,sourceID)); +#endif +} + +TEST_F(CAmMapHandlerObserverCallbacksTest,changeMainSinkVolume) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + am_mainVolume_t newVol = 20; + std::vector<am_Sink_s> listSinks; + pCF.createSink(sink); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSink(_)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), volumeChanged(sinkID, newVol)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.changeSinkMainVolumeDB(newVol,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + ASSERT_EQ(listSinks[0].mainVolume, newVol); + +#ifdef WITH_DATABASE_CHANGE_CHECK + am_mainVolume_t incVol = 21; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), volumeChanged( sinkID, incVol)).Times(1); + ASSERT_EQ(E_NO_CHANGE, pDatabaseHandler.changeSinkMainVolumeDB(newVol,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.changeSinkMainVolumeDB(incVol,sinkID)); +#endif +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, changeSinkMuteState) +{ + std::vector<am_Sink_s> listSinks; + am_Sink_s sink; + am_sinkID_t sinkID; + pCF.createSink(sink); + am_MuteState_e muteState = MS_MUTED; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSink(_)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sinkMuteStateChanged(sinkID, muteState)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.changeSinkMuteStateDB(muteState,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSinks(listSinks)); + ASSERT_EQ(muteState, listSinks[0].muteState); + +#ifdef WITH_DATABASE_CHANGE_CHECK + am_MuteState_e newMuteState = MS_UNMUTED; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sinkMuteStateChanged(sinkID, newMuteState)).Times(1); + ASSERT_EQ(E_NO_CHANGE, pDatabaseHandler.changeSinkMuteStateDB(muteState,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.changeSinkMuteStateDB(newMuteState,sinkID)); +#endif +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, changeSystemProperty) +{ + std::vector<am_SystemProperty_s> listSystemProperties, listReturn; + am_SystemProperty_s systemProperty; + + systemProperty.type = SYP_UNKNOWN; + systemProperty.value = 33; + listSystemProperties.push_back(systemProperty); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSystemProperties(listSystemProperties)); + systemProperty.value = 444; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), systemPropertyChanged(_)).Times(1); + ASSERT_EQ(E_OK, pDatabaseHandler.changeSystemPropertyDB(systemProperty)); + ASSERT_EQ(E_OK, pDatabaseHandler.getListSystemProperties(listReturn)); + ASSERT_EQ(listReturn[0].type, systemProperty.type); + ASSERT_EQ(listReturn[0].value, systemProperty.value); + +#ifdef WITH_DATABASE_CHANGE_CHECK + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), systemPropertyChanged(_)).Times(1); + ASSERT_EQ(E_NO_CHANGE, pDatabaseHandler.changeSystemPropertyDB(systemProperty)); + systemProperty.value = 33; + ASSERT_EQ(E_OK, pDatabaseHandler.changeSystemPropertyDB(systemProperty)); +#endif +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, changeMainNotificationsSink) +{ + am_Sink_s testSinkData; + pCF.createSink(testSinkData); + testSinkData.sinkID = 4; + am_sinkID_t sinkID; + std::vector<am_Sink_s> listSinks; + std::vector<am_NotificationConfiguration_s>returnList; + + am_NotificationConfiguration_s notify; + notify.type=NT_TEST_1; + notify.status=NS_CHANGE; + notify.parameter=25; + + testSinkData.listMainNotificationConfigurations.push_back(notify); + + am_NotificationConfiguration_s notify1; + notify1.type=NT_TEST_1; + notify1.status=NS_PERIODIC; + notify1.parameter=5; + + testSinkData.listMainNotificationConfigurations.push_back(notify1); + + am_NotificationConfiguration_s notify2; + notify2.type=NT_TEST_2; + notify2.status=NS_CHANGE; + notify2.parameter=27; + + testSinkData.listMainNotificationConfigurations.push_back(notify2); + + //enter the sink in the database + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSink(_)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.enterSinkDB(testSinkData,sinkID)) + << "ERROR: database error"; + ASSERT_EQ(E_OK,pDatabaseHandler.getListMainSinkNotificationConfigurations(sinkID, returnList)) + << "ERROR: database error"; + ASSERT_EQ(2, returnList.size()) << "ERROR: database error"; + + //change a setting + notify2.parameter++; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sinkMainNotificationConfigurationChanged(sinkID, _)).Times(1); +#ifdef WITH_DATABASE_CHANGE_CHECK + ASSERT_EQ(E_NO_CHANGE,pDatabaseHandler.changeMainSinkNotificationConfigurationDB(sinkID,notify1)); +#endif + ASSERT_EQ(E_OK,pDatabaseHandler.changeMainSinkNotificationConfigurationDB(sinkID,notify2)); +} + +TEST_F(CAmMapHandlerObserverCallbacksTest, changeMainNotificationsSources) +{ + + am_Source_s testSourceData; + pCF.createSource(testSourceData); + testSourceData.sourceID = 4; + am_sourceID_t sourceID; + std::vector<am_Source_s> listSources; + std::vector<am_NotificationConfiguration_s>returnList; + + am_NotificationConfiguration_s notify; + notify.type=NT_TEST_1; + notify.status=NS_CHANGE; + notify.parameter=25; + + testSourceData.listMainNotificationConfigurations.push_back(notify); + + am_NotificationConfiguration_s notify1; + notify1.type=NT_TEST_1; + notify1.status=NS_PERIODIC; + notify1.parameter=5; + + testSourceData.listMainNotificationConfigurations.push_back(notify1); + + am_NotificationConfiguration_s notify2; + notify2.type=NT_TEST_2; + notify2.status=NS_CHANGE; + notify2.parameter=10; + + testSourceData.listMainNotificationConfigurations.push_back(notify2); + + //enter the sink in the database + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), newSource(_)).Times(1); + ASSERT_EQ(E_OK,pDatabaseHandler.enterSourceDB(testSourceData,sourceID)) + << "ERROR: database error"; + ASSERT_EQ(E_OK,pDatabaseHandler.getListMainSourceNotificationConfigurations(sourceID,returnList)) + << "ERROR: database error"; + ASSERT_EQ(2, returnList.size()) << "ERROR: database error"; + + //change a setting + notify2.parameter++; + EXPECT_CALL(*MockDatabaseObserver::getMockObserverObject(), sourceMainNotificationConfigurationChanged(sourceID, _)).Times(1); +#ifdef WITH_DATABASE_CHANGE_CHECK + ASSERT_EQ(E_NO_CHANGE,pDatabaseHandler.changeMainSourceNotificationConfigurationDB(sourceID,notify1)); +#endif + ASSERT_EQ(E_OK,pDatabaseHandler.changeMainSourceNotificationConfigurationDB(sourceID,notify2)); +} + +int main(int argc, char **argv) +{ + try + { + TCLAP::CmdLine* cmd(CAmCommandLineSingleton::instanciateOnce("The team of the AudioManager wishes you a nice day!",' ',DAEMONVERSION,true)); + cmd->add(enableNoDLTDebug); + } + catch (TCLAP::ArgException &e) // catch any exceptions + { std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; } + CAmCommandLineSingleton::instance()->preparse(argc,argv); + CAmDltWrapper::instance(enableNoDLTDebug.getValue())->registerApp("databse", "databasetest"); + logInfo("Database Test started "); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + + diff --git a/AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.h b/AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.h new file mode 100644 index 0000000..e3cc0ef --- /dev/null +++ b/AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.h @@ -0,0 +1,92 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#ifndef MAPHANDLERTEST_H_ +#define MAPHANDLERTEST_H_ + +#define UNIT_TEST 1 + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "CAmSocketHandler.h" +#include "CAmDatabaseHandlerMap.h" +#include "CAmControlReceiver.h" +#include "CAmControlSender.h" +#include "CAmDatabaseObserver.h" +#include "CAmRoutingSender.h" +#include "CAmRouter.h" +#include "CAmControlSender.h" +#include "../IAmControlBackdoor.h" +#include "../IAmCommandBackdoor.h" +#include "../CAmCommonFunctions.h" +#include "../MockIAmControlSend.h" +#include "../MockIAmCommandSend.h" +#include "MockDatabaseObserver.h" + +namespace am +{ + +class CAmMapBasicTest : public ::testing::Test +{ +public: + CAmMapBasicTest(); + ~CAmMapBasicTest(); + std::vector<std::string> plistRoutingPluginDirs; + std::vector<std::string> plistCommandPluginDirs; + CAmRoutingSender pRoutingSender; + CAmCommandSender pCommandSender; + IAmRoutingBackdoor pRoutingInterfaceBackdoor; + IAmCommandBackdoor pCommandInterfaceBackdoor; + CAmSocketHandler pSocketHandler; + CAmDatabaseHandlerMap pDatabaseHandler; + CAmControlSender pControlSender; + CAmRouter pRouter; + CAmControlReceiver pControlReceiver; + CAmCommonFunctions pCF; + void SetUp(); + void TearDown(); + void createMainConnectionSetup(am_mainConnectionID_t & mainConnectionID, am_MainConnection_s & mainConnection); +}; + +class CAmMapHandlerTest: public CAmMapBasicTest +{ +public: + CAmMapHandlerTest(); + ~CAmMapHandlerTest(); + MockIAmCommandSend pMockInterface; + CAmDatabaseObserver pObserver; +}; + +class CAmMapHandlerObserverCallbacksTest : public CAmMapBasicTest +{ +public: + CAmMapHandlerObserverCallbacksTest(); + ~CAmMapHandlerObserverCallbacksTest(); + CAmDatabaseObserver mMockObserver; +}; + + +} + +#endif /* MAPHANDLERTEST_H_ */ diff --git a/AudioManagerCore/test/AmMapHandlerTest/CAmTestDatabaseObserver.cpp b/AudioManagerCore/test/AmMapHandlerTest/CAmTestDatabaseObserver.cpp new file mode 100644 index 0000000..a035cee --- /dev/null +++ b/AudioManagerCore/test/AmMapHandlerTest/CAmTestDatabaseObserver.cpp @@ -0,0 +1,98 @@ +/** + * 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 CAmTestDatabaseObserver.cpp + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmDatabaseObserver.h" +#include "MockDatabaseObserver.h" + +namespace am { + +CAmDatabaseObserver::CAmDatabaseObserver(CAmCommandSender *iCommandSender, CAmRoutingSender *iRoutingSender, CAmSocketHandler *iSocketHandler) : +mCommandSender(iCommandSender), // +mRoutingSender(iRoutingSender), // +mTelnetServer(NULL), // +mSerializer(iSocketHandler) // +{} + +CAmDatabaseObserver::~CAmDatabaseObserver() {} + + +void CAmDatabaseObserver::numberOfSinkClassesChanged() +{ MockDatabaseObserver::getMockObserverObject()->numberOfSinkClassesChanged(); } +void CAmDatabaseObserver::numberOfSourceClassesChanged() +{ MockDatabaseObserver::getMockObserverObject()->numberOfSourceClassesChanged(); } +void CAmDatabaseObserver::newSink(const am_Sink_s& sink) +{ MockDatabaseObserver::getMockObserverObject()->newSink(sink); } +void CAmDatabaseObserver::newSource(const am_Source_s& source) +{ MockDatabaseObserver::getMockObserverObject()->newSource(source); } +void CAmDatabaseObserver::newDomain(const am_Domain_s& domain) +{ MockDatabaseObserver::getMockObserverObject()->newDomain(domain); } +void CAmDatabaseObserver::newGateway(const am_Gateway_s& gateway) +{ MockDatabaseObserver::getMockObserverObject()->newGateway(gateway); } +void CAmDatabaseObserver::newConverter(const am_Converter_s& coverter) +{ MockDatabaseObserver::getMockObserverObject()->newConverter(coverter); } +void CAmDatabaseObserver::newCrossfader(const am_Crossfader_s& crossfader) +{ MockDatabaseObserver::getMockObserverObject()->newCrossfader(crossfader); } +void CAmDatabaseObserver::newMainConnection(const am_MainConnectionType_s& mainConnection) +{ MockDatabaseObserver::getMockObserverObject()->newMainConnection(mainConnection); } +void CAmDatabaseObserver::removedMainConnection(const am_mainConnectionID_t mainConnection) +{ MockDatabaseObserver::getMockObserverObject()->removedMainConnection(mainConnection); } +void CAmDatabaseObserver::removedSink(const am_sinkID_t sinkID, const bool visible) +{ MockDatabaseObserver::getMockObserverObject()->removedSink(sinkID, visible); } +void CAmDatabaseObserver::removedSource(const am_sourceID_t sourceID, const bool visible) +{ MockDatabaseObserver::getMockObserverObject()->removedSource(sourceID, visible); } +void CAmDatabaseObserver::removeDomain(const am_domainID_t domainID) +{ MockDatabaseObserver::getMockObserverObject()->removeDomain(domainID); } +void CAmDatabaseObserver::removeGateway(const am_gatewayID_t gatewayID) +{ MockDatabaseObserver::getMockObserverObject()->removeGateway(gatewayID); } +void CAmDatabaseObserver::removeConverter(const am_converterID_t converterID) +{ MockDatabaseObserver::getMockObserverObject()->removeConverter(converterID); } +void CAmDatabaseObserver::removeCrossfader(const am_crossfaderID_t crossfaderID) +{ MockDatabaseObserver::getMockObserverObject()->removeCrossfader(crossfaderID); } +void CAmDatabaseObserver::mainConnectionStateChanged(const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState) +{ MockDatabaseObserver::getMockObserverObject()->mainConnectionStateChanged(connectionID, connectionState); } +void CAmDatabaseObserver::mainSinkSoundPropertyChanged(const am_sinkID_t sinkID, const am_MainSoundProperty_s& SoundProperty) +{ MockDatabaseObserver::getMockObserverObject()->mainSinkSoundPropertyChanged(sinkID, SoundProperty); } +void CAmDatabaseObserver::mainSourceSoundPropertyChanged(const am_sourceID_t sourceID, const am_MainSoundProperty_s& SoundProperty) +{ MockDatabaseObserver::getMockObserverObject()->mainSourceSoundPropertyChanged(sourceID, SoundProperty); } +void CAmDatabaseObserver::sinkAvailabilityChanged(const am_sinkID_t sinkID, const am_Availability_s& availability) +{ MockDatabaseObserver::getMockObserverObject()->sinkAvailabilityChanged(sinkID, availability); } +void CAmDatabaseObserver::sourceAvailabilityChanged(const am_sourceID_t sourceID, const am_Availability_s& availability) +{ MockDatabaseObserver::getMockObserverObject()->sourceAvailabilityChanged(sourceID, availability); } +void CAmDatabaseObserver::volumeChanged(const am_sinkID_t sinkID, const am_mainVolume_t volume) +{ MockDatabaseObserver::getMockObserverObject()->volumeChanged(sinkID, volume); } +void CAmDatabaseObserver::sinkMuteStateChanged(const am_sinkID_t sinkID, const am_MuteState_e muteState) +{ MockDatabaseObserver::getMockObserverObject()->sinkMuteStateChanged(sinkID, muteState); } +void CAmDatabaseObserver::systemPropertyChanged(const am_SystemProperty_s& SystemProperty) +{ MockDatabaseObserver::getMockObserverObject()->systemPropertyChanged(SystemProperty); } +void CAmDatabaseObserver::timingInformationChanged(const am_mainConnectionID_t mainConnection, const am_timeSync_t time) +{ MockDatabaseObserver::getMockObserverObject()->timingInformationChanged(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) +{ MockDatabaseObserver::getMockObserverObject()->sinkUpdated(sinkID,sinkClassID,listMainSoundProperties, visible); } +void CAmDatabaseObserver::sourceUpdated(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible) +{ MockDatabaseObserver::getMockObserverObject()->sourceUpdated(sourceID,sourceClassID,listMainSoundProperties, visible); } +void CAmDatabaseObserver::sinkMainNotificationConfigurationChanged(const am_sinkID_t sinkID, const am_NotificationConfiguration_s mainNotificationConfiguration) +{ MockDatabaseObserver::getMockObserverObject()->sinkMainNotificationConfigurationChanged(sinkID,mainNotificationConfiguration); } +void CAmDatabaseObserver::sourceMainNotificationConfigurationChanged(const am_sourceID_t sourceID, const am_NotificationConfiguration_s mainNotificationConfiguration) +{ MockDatabaseObserver::getMockObserverObject()->sourceMainNotificationConfigurationChanged(sourceID,mainNotificationConfiguration); } +} + diff --git a/AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt b/AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt new file mode 100644 index 0000000..6588710 --- /dev/null +++ b/AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt @@ -0,0 +1,49 @@ +# 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 +# +# For further information see http://www.genivi.org/. +# + +cmake_minimum_required(VERSION 3.0) + +project(AmMapHandlerTest LANGUAGES CXX VERSION ${DAEMONVERSION}) + +INCLUDE_DIRECTORIES( + ${AUDIOMANAGER_UTILITIES_INCLUDE} + ${GMOCK_INCLUDE_DIRS} + ${GTEST_INCLUDE_DIRS} +) + +file(GLOB DATABASE_SRCS_CXX + "../CAmCommonFunctions.cpp" + "CAmTestDatabaseObserver.cpp" + "*.cpp" + ) + +ADD_EXECUTABLE( AmMapHandlerTest ${DATABASE_SRCS_CXX}) + +TARGET_LINK_LIBRARIES( AmMapHandlerTest + ${GTEST_LIBRARIES} + ${GMOCK_LIBRARIES} + AudioManagerCore +) + +ADD_DEPENDENCIES(AmMapHandlerTest AudioManagerCore) + +INSTALL(TARGETS AmMapHandlerTest + DESTINATION ${TEST_EXECUTABLE_INSTALL_PATH} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + COMPONENT tests +) + diff --git a/AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt~ b/AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt~ new file mode 100644 index 0000000..05d2a05 --- /dev/null +++ b/AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt~ @@ -0,0 +1,54 @@ +# 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 +# +# For further information see http://www.genivi.org/. +# + +cmake_minimum_required(VERSION 3.0) + +project(AmMapHandlerTest LANGUAGES CXX VERSION ${DAEMONVERSION}) + +INCLUDE_DIRECTORIES( + ${AUDIOMANAGER_UTILITIES_INCLUDE} + ${GMOCK_INCLUDE_DIRS} +) + +if(WITH_DLT) + INCLUDE_DIRECTORIES( + ${INCLUDE_DIRECTORIES} + ${DLT_INCLUDE_DIRS}) +endif(WITH_DLT) + +file(GLOB DATABASE_SRCS_CXX + "../CAmCommonFunctions.cpp" + "CAmTestDatabaseObserver.cpp" + "*.cpp" + ) + +ADD_EXECUTABLE( AmMapHandlerTest ${DATABASE_SRCS_CXX}) + +TARGET_LINK_LIBRARIES( AmMapHandlerTest + ${GTEST_LIBRARIES} + ${GMOCK_LIBRARIES} + AudioManagerCore +) + +ADD_DEPENDENCIES(AmMapHandlerTest AudioManagerCore) + +INSTALL(TARGETS AmMapHandlerTest + DESTINATION ${TEST_EXECUTABLE_INSTALL_PATH} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + COMPONENT tests +) + diff --git a/AudioManagerCore/test/AmMapHandlerTest/MockDatabaseObserver.h b/AudioManagerCore/test/AmMapHandlerTest/MockDatabaseObserver.h new file mode 100644 index 0000000..da1b3b4 --- /dev/null +++ b/AudioManagerCore/test/AmMapHandlerTest/MockDatabaseObserver.h @@ -0,0 +1,120 @@ +/** + * 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 MockDatabaseObserver.h + * For further information see http://www.genivi.org/. + * + */ + + +#ifndef MOCKDATABASEOBSERVER_H_ +#define MOCKDATABASEOBSERVER_H_ + +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "CAmDatabaseObserver.h" + +class CAmCommandSender; +class CAmRoutingSender; +class CAmSocketHandler; +class CAmTelnetServer; + +namespace am { +using namespace testing; + +class IAmDatabaseObserver +{ +public: + IAmDatabaseObserver() {}; + virtual ~IAmDatabaseObserver() {}; + + virtual void numberOfSinkClassesChanged() = 0; + virtual void numberOfSourceClassesChanged() = 0; + virtual void newSink(const am_Sink_s& sink) = 0; + virtual void newSource(const am_Source_s& source) = 0; + virtual void newDomain(const am_Domain_s& domain) = 0; + virtual void newGateway(const am_Gateway_s& gateway) = 0; + virtual void newConverter(const am_Converter_s& coverter) = 0; + virtual void newCrossfader(const am_Crossfader_s& crossfader) = 0; + virtual void newMainConnection(const am_MainConnectionType_s& mainConnection) = 0; + virtual void removedMainConnection(const am_mainConnectionID_t mainConnection) = 0; + virtual void removedSink(const am_sinkID_t sinkID, const bool visible) = 0; + virtual void removedSource(const am_sourceID_t sourceID, const bool visible) = 0; + virtual void removeDomain(const am_domainID_t domainID) = 0; + virtual void removeGateway(const am_gatewayID_t gatewayID) = 0; + virtual void removeConverter(const am_converterID_t converterID) = 0; + virtual void removeCrossfader(const am_crossfaderID_t crossfaderID) = 0; + virtual void mainConnectionStateChanged(const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState) = 0; + virtual void mainSinkSoundPropertyChanged(const am_sinkID_t sinkID, const am_MainSoundProperty_s& SoundProperty) = 0; + virtual void mainSourceSoundPropertyChanged(const am_sourceID_t sourceID, const am_MainSoundProperty_s& SoundProperty) = 0; + virtual void sinkAvailabilityChanged(const am_sinkID_t sinkID, const am_Availability_s& availability) = 0; + virtual void sourceAvailabilityChanged(const am_sourceID_t sourceID, const am_Availability_s& availability) = 0; + virtual void volumeChanged(const am_sinkID_t sinkID, const am_mainVolume_t volume) = 0; + virtual void sinkMuteStateChanged(const am_sinkID_t sinkID, const am_MuteState_e muteState) = 0; + virtual void systemPropertyChanged(const am_SystemProperty_s& SystemProperty) = 0; + virtual void timingInformationChanged(const am_mainConnectionID_t mainConnection, const am_timeSync_t time) = 0; + virtual void sinkUpdated(const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible) = 0; + virtual void sourceUpdated(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible) = 0; + virtual void sinkMainNotificationConfigurationChanged(const am_sinkID_t sinkID, const am_NotificationConfiguration_s mainNotificationConfiguration) = 0; + virtual void sourceMainNotificationConfigurationChanged(const am_sourceID_t sourceID, const am_NotificationConfiguration_s mainNotificationConfiguration) = 0; + +}; + +class MockDatabaseObserver : public IAmDatabaseObserver{ + public: + MOCK_METHOD0(numberOfSinkClassesChanged, void()); + MOCK_METHOD0(numberOfSourceClassesChanged, void()); + MOCK_METHOD1(newSink, void(const am_Sink_s& sink)); + MOCK_METHOD1(newSource, void(const am_Source_s& source)); + MOCK_METHOD1(newDomain, void(const am_Domain_s& domain)); + MOCK_METHOD1(newGateway, void(const am_Gateway_s& gateway)); + MOCK_METHOD1(newConverter, void(const am_Converter_s& converter)); + MOCK_METHOD1(newCrossfader, void(const am_Crossfader_s& crossfader)); + MOCK_METHOD1(newMainConnection, void(const am_MainConnectionType_s & mainConnection)); + MOCK_METHOD1(removedMainConnection, void(const am_mainConnectionID_t mainConnection)); + MOCK_METHOD2(removedSink, void(const am_sinkID_t sinkID, const bool visible)); + MOCK_METHOD2(removedSource, void(const am_sourceID_t sourceID, const bool visible)); + MOCK_METHOD1(removeDomain, void(const am_domainID_t domainID)); + MOCK_METHOD1(removeGateway, void(const am_gatewayID_t gatewayID)); + MOCK_METHOD1(removeConverter, void(const am_converterID_t converterID)); + MOCK_METHOD1(removeCrossfader, void(const am_crossfaderID_t crossfaderID)); + MOCK_METHOD2(mainConnectionStateChanged, void(const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState)); + MOCK_METHOD2(mainSinkSoundPropertyChanged, void(const am_sinkID_t sinkID, const am_MainSoundProperty_s& SoundProperty)); + MOCK_METHOD2(mainSourceSoundPropertyChanged, void(const am_sourceID_t sourceID, const am_MainSoundProperty_s& SoundProperty)); + MOCK_METHOD2(sinkAvailabilityChanged, void(const am_sinkID_t sinkID, const am_Availability_s& availability)); + MOCK_METHOD2(sourceAvailabilityChanged, void(const am_sourceID_t sourceID, const am_Availability_s& availability)); + MOCK_METHOD2(volumeChanged, void(const am_sinkID_t sinkID, const am_mainVolume_t volume)); + MOCK_METHOD2(sinkMuteStateChanged, void(const am_sinkID_t sinkID, const am_MuteState_e muteState)); + MOCK_METHOD1(systemPropertyChanged, void(const am_SystemProperty_s& SystemProperty)); + MOCK_METHOD2(timingInformationChanged, void(const am_mainConnectionID_t mainConnection, const am_timeSync_t time)); + MOCK_METHOD4(sinkUpdated, void(const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible)); + MOCK_METHOD4(sourceUpdated, void(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible)); + MOCK_METHOD2(sinkMainNotificationConfigurationChanged, void(const am_sinkID_t sinkID, const am_NotificationConfiguration_s mainNotificationConfiguration)); + MOCK_METHOD2(sourceMainNotificationConfigurationChanged, void(const am_sourceID_t sourceID, const am_NotificationConfiguration_s mainNotificationConfiguration)); + + static MockDatabaseObserver *getMockObserverObject() + { + static MockDatabaseObserver glMockObserverObject; + return &glMockObserverObject; + } +}; + + + +} // namespace am +#endif /* MOCKDATABASEOBSERVER_H_ */ diff --git a/AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.cpp b/AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.cpp new file mode 100644 index 0000000..f95a24a --- /dev/null +++ b/AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.cpp @@ -0,0 +1,3183 @@ +/** + * 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, 2014 + * + * For further information see http://www.genivi.org/. + * + */ + +#include <ctime> +#include <chrono> +#include "CAmRouterMapTest.h" +#include <string.h> +#include "CAmDltWrapper.h" +#include "CAmCommandLineSingleton.h" + +TCLAP::SwitchArg enableNoDLTDebug ("V","logDlt","print DLT logs to stdout or dlt-daemon default off",false); + + +using namespace am; +using namespace testing; + +CAmRouterMapTest::CAmRouterMapTest() : + plistRoutingPluginDirs(), // + plistCommandPluginDirs(), // + pSocketHandler(), // + pControlSender(), // + pDatabaseHandler(), + pRouter(&pDatabaseHandler, &pControlSender), // + pRoutingSender(plistRoutingPluginDirs), // + pCommandSender(plistCommandPluginDirs), // + pMockInterface(), // + pMockControlInterface(), // + pRoutingInterfaceBackdoor(), // + pCommandInterfaceBackdoor(), // + pControlInterfaceBackdoor(), // + pControlReceiver(&pDatabaseHandler, &pRoutingSender, &pCommandSender,&pSocketHandler, &pRouter), // + pObserver(&pCommandSender, &pRoutingSender, &pSocketHandler) +{ + pDatabaseHandler.registerObserver(&pObserver); + pCommandInterfaceBackdoor.injectInterface(&pCommandSender, &pMockInterface); + pControlInterfaceBackdoor.replaceController(&pControlSender, &pMockControlInterface); +} + +CAmRouterMapTest::~CAmRouterMapTest() +{ + +} + +void CAmRouterMapTest::SetUp() +{ + logInfo("Routing Test started "); +} + +void CAmRouterMapTest::TearDown() +{ +} + +ACTION(returnConnectionFormat){ + arg4=arg3; +} + +void CAmRouterMapTest::enterDomainDB(const std::string & domainName, am_domainID_t & domainID) +{ + am_Domain_s domain1; + domain1.domainID = 0; + domain1.name = domainName; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID)); +} + +void CAmRouterMapTest::enterSourceDB(const std::string & sourceName, const am_domainID_t domainID, const std::vector<am_CustomConnectionFormat_t> & connectionFormats, am_sourceID_t & sourceID) +{ + am_Source_s source; + source.domainID = domainID; + source.name = sourceName; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats = connectionFormats; + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); +} + +void CAmRouterMapTest::enterSinkDB(const std::string & sinkName, const am_domainID_t domainID, const std::vector<am_CustomConnectionFormat_t> & connectionFormats, am_sinkID_t & sinkID) +{ + am_Sink_s sink; + sink.domainID = domainID; + sink.name = sinkName; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats = connectionFormats; + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); +} + +void CAmRouterMapTest::enterGatewayDB(const std::string & gwName, + const am_domainID_t domainSourceID, + const am_domainID_t domainSinkID, + const std::vector<am_CustomConnectionFormat_t> & sourceConnectionFormats, + const std::vector<am_CustomConnectionFormat_t> & sinkConnectionFormats, + const std::vector<bool> & matrix, + const am_sourceID_t & sourceID, + const am_sinkID_t & sinkID, + am_gatewayID_t & gatewayID) +{ + am_Gateway_s gateway; + gateway.controlDomainID = domainSourceID; + gateway.gatewayID = 0; + gateway.sinkID = sinkID; + gateway.sourceID = sourceID; + gateway.domainSourceID = domainSourceID; + gateway.domainSinkID = domainSinkID; + gateway.listSinkFormats = sinkConnectionFormats; + gateway.listSourceFormats = sourceConnectionFormats; + gateway.convertionMatrix = matrix; + gateway.name = gwName; + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); +} + +void CAmRouterMapTest::enterConverterDB(const std::string & gwName, + const am_domainID_t domainID, + const std::vector<am_CustomConnectionFormat_t> & sourceConnectionFormats, + const std::vector<am_CustomConnectionFormat_t> & sinkConnectionFormats, + const std::vector<bool> & matrix, + const am_sourceID_t & sourceID, + const am_sinkID_t & sinkID, + am_converterID_t & converterID) +{ + am_Converter_s converter; + converter.converterID = 0; + converter.sinkID = sinkID; + converter.sourceID = sourceID; + converter.domainID = domainID; + converter.listSinkFormats = sinkConnectionFormats; + converter.listSourceFormats = sourceConnectionFormats; + converter.convertionMatrix = matrix; + converter.name = gwName; + ASSERT_EQ(E_OK, pDatabaseHandler.enterConverterDB(converter,converterID)); +} + +void CAmRouterMapTest::getRoute(const bool onlyfree, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes) +{ + std::ios_base::fmtflags oldflags = std::cout.flags(); + std::streamsize oldprecision = std::cout.precision(); + auto t_start = std::chrono::high_resolution_clock::now(); + ASSERT_EQ(E_OK, pRouter.getRoute(onlyfree, aSource, aSink, listRoutes)); + auto t_end = std::chrono::high_resolution_clock::now(); + std::cout << std::fixed << std::setprecision(2); + std::cout << "getRoute did find " << listRoutes.size() <<" routes from " << aSource.sourceID << " to " << aSink.sinkID; + std::cout << " in " << std::chrono::duration<double, std::milli>(t_end-t_start).count() << " ms\n"; + std::cout.flags (oldflags); + std::cout.precision (oldprecision); +} + +void CAmRouterMapTest::getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s>& returnList) +{ + std::ios_base::fmtflags oldflags = std::cout.flags(); + std::streamsize oldprecision = std::cout.precision(); + auto t_start = std::chrono::high_resolution_clock::now(); + ASSERT_EQ(E_OK, pRouter.getRoute(onlyfree, sourceID, sinkID, returnList)); + auto t_end = std::chrono::high_resolution_clock::now(); + std::cout << std::fixed << std::setprecision(2); + std::cout << "getRoute by id did find " << returnList.size() <<" routes from " << sourceID << " to " << sinkID; + std::cout << " in " << std::chrono::duration<double, std::milli>(t_end-t_start).count() << " ms\n"; + std::cout.flags (oldflags); + std::cout.precision (oldprecision); +} + +void CAmRouterMapTest::getAllPaths(CAmRoutingNode & aSource, + CAmRoutingNode & aSink, + std::vector<am_Route_s> & resultPath, + std::vector<std::vector<CAmRoutingNode*>> & resultNodesPath, + const bool includeCycles) +{ + std::ios_base::fmtflags oldflags = std::cout.flags(); + std::streamsize oldprecision = std::cout.precision(); + auto t_start = std::chrono::high_resolution_clock::now(); + ASSERT_EQ(E_OK, pRouter.getAllPaths(aSource, aSink, resultPath, resultNodesPath, includeCycles)); + auto t_end = std::chrono::high_resolution_clock::now(); + std::cout << std::fixed << std::setprecision(2); + std::cout << "getAllPaths did find " << resultPath.size() + << " routes from " << aSource.getData().data.source->sourceID + << " to " << aSink.getData().data.sink->sinkID; + std::cout << " in " << std::chrono::duration<double, std::milli>(t_end-t_start).count() << " ms\n"; + std::cout.flags (oldflags); + std::cout.precision (oldprecision); +} + +TEST_F(CAmRouterMapTest,checkInsertedDomain) +{ + std::vector<am_domainID_t> domains; + ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 22)); + domains.push_back(22); + ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 22)); + domains.push_back(22); + ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 22)); + ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 50)); + domains.push_back(30); + ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 30)); + ASSERT_FALSE(CAmRouter::shouldGoInDomain(domains, 22)); + domains.push_back(30); + ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 30)); + ASSERT_FALSE(CAmRouter::shouldGoInDomain(domains, 22)); + ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 60)); +} + +//test that checks just sinks and source in a domain but connectionformats do not match +TEST_F(CAmRouterMapTest,simpleRoute2withDomainNoMatchFormats) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1; + am_domainID_t domainID1; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + + am_Source_s source; + am_sourceID_t sourceID; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + + am_Sink_s sink; + am_sinkID_t sinkID; + + sink.domainID = domainID1; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + + hopp1.sinkID = sinkID; + hopp1.sourceID = sourceID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + am::am_Source_s sourceDb; + am::am_Sink_s sinkDb; + pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb); + pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb); + listRoutes.clear(); + getRoute(true, sourceDb, sinkDb, listRoutes); + ASSERT_EQ(static_cast<uint>(0), listRoutes.size()); +} + +//test that checks just sinks and source in a domain +TEST_F(CAmRouterMapTest,simpleRoute2withDomain) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1; + am_domainID_t domainID1; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + + am_Source_s source; + am_sourceID_t sourceID; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + + am_Sink_s sink; + am_sinkID_t sinkID; + + sink.domainID = domainID1; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + + hopp1.sinkID = sinkID; + hopp1.sourceID = sourceID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + am::am_Source_s sourceDb; + am::am_Sink_s sinkDb; + pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb); + pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb); + listRoutes.clear(); + getRoute(true, sourceDb, sinkDb, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + +//test that checks just 2 domains, one sink one source with only one connection format each +TEST_F(CAmRouterMapTest,simpleRoute2DomainsOnlyFree) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2; + am_domainID_t domainID1, domainID2; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + + am_Source_s source, gwSource; + am_sourceID_t sourceID, gwSourceID; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + + am_Sink_s sink, gwSink; + am_sinkID_t sinkID, gwSinkID; + + sink.domainID = domainID2; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + + am_Gateway_s gateway; + am_gatewayID_t gatewayID; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + + hopp1.sinkID = gwSinkID; + hopp1.sourceID = sourceID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sinkID = sinkID; + hopp2.sourceID = gwSourceID; + hopp2.domainID = domainID2; + hopp2.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + am::am_Source_s sourceDb; + am::am_Sink_s sinkDb; + pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb); + pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb); + + getRoute(true,sourceID,sinkID,listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + + +//test that checks just 2 domains, one sink one source with only one connection format each +TEST_F(CAmRouterMapTest,simpleRoute2DomainsOnlyFreeNotFree) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2; + am_domainID_t domainID1, domainID2; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + + am_Source_s source, gwSource; + am_sourceID_t sourceID, gwSourceID; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + + am_Sink_s sink, gwSink; + am_sinkID_t sinkID, gwSinkID; + + sink.domainID = domainID2; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + + am_Gateway_s gateway; + am_gatewayID_t gatewayID; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + + hopp1.sinkID = gwSinkID; + hopp1.sourceID = sourceID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sinkID = sinkID; + hopp2.sourceID = gwSourceID; + hopp2.domainID = domainID2; + hopp2.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + am_Connection_s connection,connection1; + am_connectionID_t id1,id2; + connection.sourceID=sourceID; + connection.sinkID=gwSinkID; + connection.connectionFormat=CF_GENIVI_ANALOG; + connection.connectionID=0; + connection1.sourceID=gwSourceID; + connection1.sinkID=sinkID; + connection1.connectionFormat=CF_GENIVI_ANALOG; + connection1.connectionID=0; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterConnectionDB(connection,id1)); + ASSERT_EQ(E_OK,pDatabaseHandler.enterConnectionDB(connection1,id2)); + + am::am_Source_s sourceDb; + am::am_Sink_s sinkDb; + pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb); + pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb); + listRoutes.clear(); + getRoute(true, sourceDb, sinkDb, listRoutes); + ASSERT_EQ(static_cast<uint>(0), listRoutes.size()); + + listRoutes.clear(); + getRoute(false, sourceDb, sinkDb, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + +//test that checks just 2 domains, with gateway for each direction (possible circular route) +TEST_F(CAmRouterMapTest,simpleRoute2DomainsCircularGWOnlyFree) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2; + am_domainID_t domainID1, domainID2; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + + am_Source_s source, gwSource, gwSource2; + am_sourceID_t sourceID, gwSourceID, gwSourceID2; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource2.domainID = domainID1; + gwSource2.name = "gwsource2"; + gwSource2.sourceState = SS_ON; + gwSource2.sourceID = 0; + gwSource2.sourceClassID = 5; + gwSource2.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource2,gwSourceID2)); + + am_Sink_s sink, gwSink, gwSink2; + am_sinkID_t sinkID, gwSinkID, gwSinkID2; + + sink.domainID = domainID2; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSink2.domainID = domainID2; + gwSink2.name = "gwSink2"; + gwSink2.sinkID = 0; + gwSink2.sinkClassID = 5; + gwSink2.muteState = MS_MUTED; + gwSink2.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink2,gwSinkID2)); + + am_Gateway_s gateway, gateway2; + am_gatewayID_t gatewayID, gatewayID2; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + gateway2.controlDomainID = domainID1; + gateway2.gatewayID = 0; + gateway2.sinkID = gwSinkID2; + gateway2.sourceID = gwSourceID2; + gateway2.domainSourceID = domainID1; + gateway2.domainSinkID = domainID2; + gateway2.listSinkFormats = gwSink2.listConnectionFormats; + gateway2.listSourceFormats = gwSource2.listConnectionFormats; + gateway2.convertionMatrix.push_back(true); + gateway2.name = "gateway2"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway2,gatewayID2)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + + hopp1.sinkID = gwSinkID; + hopp1.sourceID = sourceID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sinkID = sinkID; + hopp2.sourceID = gwSourceID; + hopp2.domainID = domainID2; + hopp2.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + am::am_Source_s sourceDb; + am::am_Sink_s sinkDb; + pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb); + pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb); + listRoutes.clear(); + getRoute(true, sourceDb, sinkDb, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + +//test that checks 3 domains, one sink one source, longer lists of connectionformats. +TEST_F(CAmRouterMapTest,simpleRoute3DomainsListConnectionFormats_2) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2, domain3; + am_domainID_t domainID1, domainID2, domainID3; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + domain3.domainID = 0; + domain3.name = "domain3"; + domain3.busname = "domain3bus"; + domain3.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain3,domainID3)); + + am_Source_s source, gwSource, gwSource1; + am_sourceID_t sourceID, gwSourceID, gwSourceID1; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_STEREO); + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_MONO); + gwSource.listConnectionFormats.push_back(CF_GENIVI_STEREO); + gwSource.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource1.domainID = domainID3; + gwSource1.name = "gwsource2"; + gwSource1.sourceState = SS_ON; + gwSource1.sourceID = 0; + gwSource1.sourceClassID = 5; + gwSource1.listConnectionFormats.push_back(CF_GENIVI_STEREO); + gwSource1.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource1,gwSourceID1)); + + am_Sink_s sink, gwSink, gwSink1; + am_sinkID_t sinkID, gwSinkID, gwSinkID1; + + sink.domainID = domainID3; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_STEREO); + gwSink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink1.domainID = domainID2; + gwSink1.name = "gwSink1"; + gwSink1.sinkID = 0; + gwSink1.sinkClassID = 5; + gwSink1.muteState = MS_MUTED; + gwSink1.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + gwSink1.listConnectionFormats.push_back(CF_GENIVI_STEREO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink1,gwSinkID1)); + + am_Gateway_s gateway, gateway1; + am_gatewayID_t gatewayID, gatewayID1; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(true); + gateway.convertionMatrix.push_back(true); + gateway.convertionMatrix.push_back(false); + gateway.name = "gateway"; + + gateway1.controlDomainID = domainID2; + gateway1.gatewayID = 0; + gateway1.sinkID = gwSinkID1; + gateway1.sourceID = gwSourceID1; + gateway1.domainSourceID = domainID3; + gateway1.domainSinkID = domainID2; + gateway1.listSinkFormats = gwSink1.listConnectionFormats; + gateway1.listSourceFormats = gwSource1.listConnectionFormats; + gateway1.convertionMatrix.push_back(false); + gateway1.convertionMatrix.push_back(false); + gateway1.convertionMatrix.push_back(false); + gateway1.convertionMatrix.push_back(true); + gateway1.name = "gateway1"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + am_RoutingElement_s hopp3; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[1]; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = gwSinkID1; + hopp2.domainID = domainID2; + hopp2.connectionFormat = gwSink1.listConnectionFormats[1]; + + hopp3.sourceID = gwSourceID1; + hopp3.sinkID = sinkID; + hopp3.domainID = domainID3; + hopp3.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + listRoutingElements.push_back(hopp3); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + am::am_Source_s sourceDb; + am::am_Sink_s sinkDb; + pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb); + pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb); + getRoute(false, sourceDb, sinkDb, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + +//test that checks 3 domains, one sink one source, longer lists of connectionformats. +TEST_F(CAmRouterMapTest,simpleRoute3DomainsListConnectionFormats_1) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2, domain3; + am_domainID_t domainID1, domainID2, domainID3; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + domain3.domainID = 0; + domain3.name = "domain3"; + domain3.busname = "domain3bus"; + domain3.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain3,domainID3)); + + am_Source_s source, gwSource, gwSource1; + am_sourceID_t sourceID, gwSourceID, gwSourceID1; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_STEREO); + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_STEREO); + gwSource.listConnectionFormats.push_back(CF_GENIVI_MONO); + gwSource.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource1.domainID = domainID3; + gwSource1.name = "gwsource2"; + gwSource1.sourceState = SS_ON; + gwSource1.sourceID = 0; + gwSource1.sourceClassID = 5; + gwSource1.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource1,gwSourceID1)); + + am_Sink_s sink, gwSink, gwSink1; + am_sinkID_t sinkID, gwSinkID, gwSinkID1; + + sink.domainID = domainID3; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_STEREO); + gwSink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink1.domainID = domainID2; + gwSink1.name = "gwSink1"; + gwSink1.sinkID = 0; + gwSink1.sinkClassID = 5; + gwSink1.muteState = MS_MUTED; + gwSink1.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink1,gwSinkID1)); + + am_Gateway_s gateway, gateway1; + am_gatewayID_t gatewayID, gatewayID1; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(true); + gateway.convertionMatrix.push_back(false); + gateway.name = "gateway"; + + gateway1.controlDomainID = domainID2; + gateway1.gatewayID = 0; + gateway1.sinkID = gwSinkID1; + gateway1.sourceID = gwSourceID1; + gateway1.domainSourceID = domainID3; + gateway1.domainSinkID = domainID2; + gateway1.listSinkFormats = gwSink1.listConnectionFormats; + gateway1.listSourceFormats = gwSource1.listConnectionFormats; + gateway1.convertionMatrix.push_back(true); + gateway1.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + am_RoutingElement_s hopp3; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = gwSinkID1; + hopp2.domainID = domainID2; + hopp2.connectionFormat = gwSink1.listConnectionFormats[0]; + + hopp3.sourceID = gwSourceID1; + hopp3.sinkID = sinkID; + hopp3.domainID = domainID3; + hopp3.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + listRoutingElements.push_back(hopp3); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + am::am_Source_s sourceDb; + am::am_Sink_s sinkDb; + pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb); + pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb); + getRoute(false, sourceDb, sinkDb, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + + +//test that checks 3 domains, one sink one source, longer lists of connectionformats. +TEST_F(CAmRouterMapTest,simpleRoute3DomainsListConnectionFormats) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2, domain3; + am_domainID_t domainID1, domainID2, domainID3; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + domain3.domainID = 0; + domain3.name = "domain3"; + domain3.busname = "domain3bus"; + domain3.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain3,domainID3)); + + am_Source_s source, gwSource, gwSource1; + am_sourceID_t sourceID, gwSourceID, gwSourceID1; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_STEREO); + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource1.domainID = domainID3; + gwSource1.name = "gwsource2"; + gwSource1.sourceState = SS_ON; + gwSource1.sourceID = 0; + gwSource1.sourceClassID = 5; + gwSource1.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource1,gwSourceID1)); + + am_Sink_s sink, gwSink, gwSink1; + am_sinkID_t sinkID, gwSinkID, gwSinkID1; + + sink.domainID = domainID3; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_STEREO); + gwSink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink1.domainID = domainID2; + gwSink1.name = "gwSink1"; + gwSink1.sinkID = 0; + gwSink1.sinkClassID = 5; + gwSink1.muteState = MS_MUTED; + gwSink1.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink1,gwSinkID1)); + + am_Gateway_s gateway, gateway1; + am_gatewayID_t gatewayID, gatewayID1; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + gateway1.controlDomainID = domainID2; + gateway1.gatewayID = 0; + gateway1.sinkID = gwSinkID1; + gateway1.sourceID = gwSourceID1; + gateway1.domainSourceID = domainID3; + gateway1.domainSinkID = domainID2; + gateway1.listSinkFormats = gwSink1.listConnectionFormats; + gateway1.listSourceFormats = gwSource1.listConnectionFormats; + gateway1.convertionMatrix.push_back(true); + gateway1.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + am_RoutingElement_s hopp3; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[1]; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = gwSinkID1; + hopp2.domainID = domainID2; + hopp2.connectionFormat = gwSink1.listConnectionFormats[0]; + + hopp3.sourceID = gwSourceID1; + hopp3.sinkID = sinkID; + hopp3.domainID = domainID3; + hopp3.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + listRoutingElements.push_back(hopp3); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + am::am_Source_s sourceDb; + am::am_Sink_s sinkDb; + pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb); + pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb); + getRoute(false, sourceDb, sinkDb, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + + +//test that checks 4 domains, one sink and one source but there are 2 routes because there are 2 gateways +TEST_F(CAmRouterMapTest,simpleRoute4Domains2Routes) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2, domain3, domain4; + am_domainID_t domainID1, domainID2, domainID3, domainID4; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + domain3.domainID = 0; + domain3.name = "domain3"; + domain3.busname = "domain3bus"; + domain3.state = DS_CONTROLLED; + domain4.domainID = 0; + domain4.name = "domain4"; + domain4.busname = "domain4bus"; + domain4.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain3,domainID3)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain4,domainID4)); + + am_Source_s source, gwSource, gwSource1, gwSource2, gwSource3; + am_sourceID_t sourceID, gwSourceID, gwSourceID1, gwSourceID2, gwSourceID3; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource1.domainID = domainID3; + gwSource1.name = "gwsource2"; + gwSource1.sourceState = SS_ON; + gwSource1.sourceID = 0; + gwSource1.sourceClassID = 5; + gwSource1.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource2.domainID = domainID4; + gwSource2.name = "gwsource3"; + gwSource2.sourceState = SS_OFF; + gwSource2.sourceID = 0; + gwSource2.sourceClassID = 5; + gwSource2.listConnectionFormats.push_back(CF_GENIVI_STEREO); + + gwSource3.domainID = domainID3; + gwSource3.name = "gwsource4"; + gwSource3.sourceState = SS_OFF; + gwSource3.sourceID = 0; + gwSource3.sourceClassID = 5; + gwSource3.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource1,gwSourceID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource2,gwSourceID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource3,gwSourceID3)); + + am_Sink_s sink, gwSink, gwSink1, gwSink2, gwSink3; + am_sinkID_t sinkID, gwSinkID, gwSinkID1, gwSinkID2, gwSinkID3; + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink1.domainID = domainID2; + gwSink1.name = "gwSink1"; + gwSink1.sinkID = 0; + gwSink1.sinkClassID = 5; + gwSink1.muteState = MS_MUTED; + gwSink1.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSink2.domainID = domainID3; + gwSink2.name = "gwSink2"; + gwSink2.sinkID = 0; + gwSink2.sinkClassID = 5; + gwSink2.muteState = MS_MUTED; + gwSink2.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink3.domainID = domainID2; + gwSink3.name = "gwSink3"; + gwSink3.sinkID = 0; + gwSink3.sinkClassID = 5; + gwSink3.muteState = MS_MUTED; + gwSink3.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + sink.domainID = domainID4; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_STEREO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink1,gwSinkID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink2,gwSinkID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink3,gwSinkID3)); + + am_Gateway_s gateway, gateway1, gateway2, gateway3; + am_gatewayID_t gatewayID, gatewayID1, gatewayID2, gatewayID3; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + gateway1.controlDomainID = domainID2; + gateway1.gatewayID = 0; + gateway1.sinkID = gwSinkID1; + gateway1.sourceID = gwSourceID1; + gateway1.domainSourceID = domainID3; + gateway1.domainSinkID = domainID2; + gateway1.listSinkFormats = gwSink1.listConnectionFormats; + gateway1.listSourceFormats = gwSource1.listConnectionFormats; + gateway1.convertionMatrix.push_back(true); + gateway1.name = "gateway1"; + + gateway2.controlDomainID = domainID3; + gateway2.gatewayID = 0; + gateway2.sinkID = gwSinkID2; + gateway2.sourceID = gwSourceID2; + gateway2.domainSourceID = domainID4; + gateway2.domainSinkID = domainID3; + gateway2.listSinkFormats = gwSink2.listConnectionFormats; + gateway2.listSourceFormats = gwSource2.listConnectionFormats; + gateway2.convertionMatrix.push_back(true); + gateway2.name = "gateway2"; + + gateway3.controlDomainID = domainID2; + gateway3.gatewayID = 0; + gateway3.sinkID = gwSinkID3; + gateway3.sourceID = gwSourceID3; + gateway3.domainSourceID = domainID3; + gateway3.domainSinkID = domainID2; + gateway3.listSinkFormats = gwSink3.listConnectionFormats; + gateway3.listSourceFormats = gwSource3.listConnectionFormats; + gateway3.convertionMatrix.push_back(true); + gateway3.name = "gateway3"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway2,gatewayID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway3,gatewayID3)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements, listRoutingElements1; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + am_RoutingElement_s hopp3; + am_RoutingElement_s hopp4; + am_RoutingElement_s hopp2alt; + am_RoutingElement_s hopp3alt; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = gwSinkID1; + hopp2.domainID = domainID2; + hopp2.connectionFormat = gwSink1.listConnectionFormats[0]; + + hopp3.sourceID = gwSourceID1; + hopp3.sinkID = gwSinkID2; + hopp3.domainID = domainID3; + hopp3.connectionFormat = gwSink2.listConnectionFormats[0]; + + hopp4.sourceID = gwSourceID2; + hopp4.sinkID = sinkID; + hopp4.domainID = domainID4; + hopp4.connectionFormat = sink.listConnectionFormats[0]; + + hopp2alt.sourceID = gwSourceID; + hopp2alt.sinkID = gwSinkID3; + hopp2alt.domainID = domainID2; + hopp2alt.connectionFormat = gwSink3.listConnectionFormats[0]; + + hopp3alt.sourceID = gwSourceID3; + hopp3alt.sinkID = gwSinkID2; + hopp3alt.domainID = domainID3; + hopp3alt.connectionFormat = gwSink2.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + listRoutingElements.push_back(hopp3); + listRoutingElements.push_back(hopp4); + listRoutingElements1.push_back(hopp1); + listRoutingElements1.push_back(hopp2alt); + listRoutingElements1.push_back(hopp3alt); + listRoutingElements1.push_back(hopp4); + + am_Route_s compareRoute, compareRoute1; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + compareRoute1.route = listRoutingElements1; + compareRoute1.sinkID = sinkID; + compareRoute1.sourceID = sourceID; + + am::am_Source_s sourceDb; + am::am_Sink_s sinkDb; + pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb); + pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb); + getRoute(false, sourceDb, sinkDb, listRoutes); + ASSERT_EQ(static_cast<uint>(2), listRoutes.size()); + + bool containsRoute1 = std::find_if(listRoutes.begin(), listRoutes.end(), [&](const am_Route_s & ref) { + return pCF.compareRoute(compareRoute, ref); + })!=listRoutes.end(); + bool containsRoute2 = std::find_if(listRoutes.begin(), listRoutes.end(), [&](const am_Route_s & ref) { + return pCF.compareRoute(compareRoute1, ref); + })!=listRoutes.end(); + + ASSERT_TRUE(containsRoute1); + ASSERT_TRUE(containsRoute2); +} + +//test that checks 3 domains, one sink one source but the connectionformat of third domains do not fit. +TEST_F(CAmRouterMapTest,simpleRoute3DomainsNoConnection) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2, domain3; + am_domainID_t domainID1, domainID2, domainID3; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + domain3.domainID = 0; + domain3.name = "domain3"; + domain3.busname = "domain3bus"; + domain3.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain3,domainID3)); + + am_Source_s source, gwSource, gwSource1; + am_sourceID_t sourceID, gwSourceID, gwSourceID1; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource1.domainID = domainID3; + gwSource1.name = "gwsource2"; + gwSource1.sourceState = SS_ON; + gwSource1.sourceID = 0; + gwSource1.sourceClassID = 5; + gwSource1.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource1,gwSourceID1)); + + am_Sink_s sink, gwSink, gwSink1; + am_sinkID_t sinkID, gwSinkID, gwSinkID1; + + sink.domainID = domainID3; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_STEREO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink1.domainID = domainID2; + gwSink1.name = "gwSink1"; + gwSink1.sinkID = 0; + gwSink1.sinkClassID = 5; + gwSink1.muteState = MS_MUTED; + gwSink1.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink1,gwSinkID1)); + + am_Gateway_s gateway, gateway1; + am_gatewayID_t gatewayID, gatewayID1; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + gateway1.controlDomainID = domainID2; + gateway1.gatewayID = 0; + gateway1.sinkID = gwSinkID1; + gateway1.sourceID = gwSourceID1; + gateway1.domainSourceID = domainID3; + gateway1.domainSinkID = domainID2; + gateway1.listSinkFormats = gwSink1.listConnectionFormats; + gateway1.listSourceFormats = gwSource1.listConnectionFormats; + gateway1.convertionMatrix.push_back(true); + gateway1.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + am_RoutingElement_s hopp3; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = gwSinkID1; + hopp2.domainID = domainID2; + hopp2.connectionFormat = gwSink1.listConnectionFormats[0]; + + hopp3.sourceID = gwSourceID1; + hopp3.sinkID = sinkID; + hopp3.domainID = domainID3; + hopp3.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + listRoutingElements.push_back(hopp3); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + am::am_Source_s sourceDb; + am::am_Sink_s sinkDb; + pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb); + pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb); + listRoutes.clear(); + getRoute(false, sourceDb, sinkDb, listRoutes); + ASSERT_EQ(static_cast<uint>(0), listRoutes.size()); +} +//test that checks just 2 domains, one sink one source with only one connection format each +TEST_F(CAmRouterMapTest,simpleRoute2Domains) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2; + am_domainID_t domainID1, domainID2; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + + am_Source_s source, gwSource; + am_sourceID_t sourceID, gwSourceID; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + + am_Sink_s sink, gwSink; + am_sinkID_t sinkID, gwSinkID; + + sink.domainID = domainID2; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + + am_Gateway_s gateway; + am_gatewayID_t gatewayID; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + + hopp1.sinkID = gwSinkID; + hopp1.sourceID = sourceID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sinkID = sinkID; + hopp2.sourceID = gwSourceID; + hopp2.domainID = domainID2; + hopp2.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + am::am_Source_s sourceDb; + am::am_Sink_s sinkDb; + pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb); + pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb); + getRoute(false, sourceDb, sinkDb, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + +//test that checks just 2 domains, one sink one source but the connectionformat of source +TEST_F(CAmRouterMapTest,simpleRoute2DomainsNoMatchConnectionFormats) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2; + am_domainID_t domainID1, domainID2; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + + am_Source_s source, gwSource; + am_sourceID_t sourceID, gwSourceID; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_STEREO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + + am_Sink_s sink, gwSink; + am_sinkID_t sinkID, gwSinkID; + + sink.domainID = domainID2; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + + am_Gateway_s gateway; + am_gatewayID_t gatewayID; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + + std::vector<am_Route_s> listRoutes; + + am::am_Source_s sourceDb; + am::am_Sink_s sinkDb; + pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb); + pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb); + getRoute(false, sourceDb, sinkDb, listRoutes); + ASSERT_EQ(static_cast<uint>(0), listRoutes.size()); + } + +//test that checks 3 domains, one sink one source. +TEST_F(CAmRouterMapTest,simpleRoute3Domains) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2, domain3; + am_domainID_t domainID1, domainID2, domainID3; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + domain3.domainID = 0; + domain3.name = "domain3"; + domain3.busname = "domain3bus"; + domain3.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain3,domainID3)); + + am_Source_s source, gwSource, gwSource1; + am_sourceID_t sourceID, gwSourceID, gwSourceID1; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource1.domainID = domainID3; + gwSource1.name = "gwsource2"; + gwSource1.sourceState = SS_ON; + gwSource1.sourceID = 0; + gwSource1.sourceClassID = 5; + gwSource1.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource1,gwSourceID1)); + + am_Sink_s sink, gwSink, gwSink1; + am_sinkID_t sinkID, gwSinkID, gwSinkID1; + + sink.domainID = domainID3; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink1.domainID = domainID2; + gwSink1.name = "gwSink1"; + gwSink1.sinkID = 0; + gwSink1.sinkClassID = 5; + gwSink1.muteState = MS_MUTED; + gwSink1.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink1,gwSinkID1)); + + am_Gateway_s gateway, gateway1; + am_gatewayID_t gatewayID, gatewayID1; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + gateway1.controlDomainID = domainID2; + gateway1.gatewayID = 0; + gateway1.sinkID = gwSinkID1; + gateway1.sourceID = gwSourceID1; + gateway1.domainSourceID = domainID3; + gateway1.domainSinkID = domainID2; + gateway1.listSinkFormats = gwSink1.listConnectionFormats; + gateway1.listSourceFormats = gwSource1.listConnectionFormats; + gateway1.convertionMatrix.push_back(true); + gateway1.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + am_RoutingElement_s hopp3; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = gwSinkID1; + hopp2.domainID = domainID2; + hopp2.connectionFormat = gwSink1.listConnectionFormats[0]; + + hopp3.sourceID = gwSourceID1; + hopp3.sinkID = sinkID; + hopp3.domainID = domainID3; + hopp3.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + listRoutingElements.push_back(hopp3); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + am::am_Source_s sourceDb; + am::am_Sink_s sinkDb; + pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb); + pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb); + listRoutes.clear(); + getRoute(false, sourceDb, sinkDb, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + +//test that checks 4 domains, one sink and one source. +TEST_F(CAmRouterMapTest,simpleRoute4Domains) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2, domain3, domain4; + am_domainID_t domainID1, domainID2, domainID3, domainID4; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + domain3.domainID = 0; + domain3.name = "domain3"; + domain3.busname = "domain3bus"; + domain3.state = DS_CONTROLLED; + domain4.domainID = 0; + domain4.name = "domain4"; + domain4.busname = "domain4bus"; + domain4.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain3,domainID3)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain4,domainID4)); + + am_Source_s source, gwSource, gwSource1, gwSource2; + am_sourceID_t sourceID, gwSourceID, gwSourceID1, gwSourceID2; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource1.domainID = domainID3; + gwSource1.name = "gwsource2"; + gwSource1.sourceState = SS_ON; + gwSource1.sourceID = 0; + gwSource1.sourceClassID = 5; + gwSource1.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource2.domainID = domainID4; + gwSource2.name = "gwsource3"; + gwSource2.sourceState = SS_OFF; + gwSource2.sourceID = 0; + gwSource2.sourceClassID = 5; + gwSource2.listConnectionFormats.push_back(CF_GENIVI_STEREO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource1,gwSourceID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource2,gwSourceID2)); + + am_Sink_s sink, gwSink, gwSink1, gwSink2; + am_sinkID_t sinkID, gwSinkID, gwSinkID1, gwSinkID2; + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink1.domainID = domainID2; + gwSink1.name = "gwSink1"; + gwSink1.sinkID = 0; + gwSink1.sinkClassID = 5; + gwSink1.muteState = MS_MUTED; + gwSink1.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSink2.domainID = domainID3; + gwSink2.name = "gwSink2"; + gwSink2.sinkID = 0; + gwSink2.sinkClassID = 5; + gwSink2.muteState = MS_MUTED; + gwSink2.listConnectionFormats.push_back(CF_GENIVI_MONO); + + sink.domainID = domainID4; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_STEREO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink1,gwSinkID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink2,gwSinkID2)); + + am_Gateway_s gateway, gateway1, gateway2; + am_gatewayID_t gatewayID, gatewayID1, gatewayID2; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + gateway1.controlDomainID = domainID2; + gateway1.gatewayID = 0; + gateway1.sinkID = gwSinkID1; + gateway1.sourceID = gwSourceID1; + gateway1.domainSourceID = domainID3; + gateway1.domainSinkID = domainID2; + gateway1.listSinkFormats = gwSink1.listConnectionFormats; + gateway1.listSourceFormats = gwSource1.listConnectionFormats; + gateway1.convertionMatrix.push_back(true); + gateway1.name = "gateway1"; + + gateway2.controlDomainID = domainID3; + gateway2.gatewayID = 0; + gateway2.sinkID = gwSinkID2; + gateway2.sourceID = gwSourceID2; + gateway2.domainSourceID = domainID4; + gateway2.domainSinkID = domainID3; + gateway2.listSinkFormats = gwSink2.listConnectionFormats; + gateway2.listSourceFormats = gwSource2.listConnectionFormats; + gateway2.convertionMatrix.push_back(true); + gateway2.name = "gateway2"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway2,gatewayID2)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + am_RoutingElement_s hopp3; + am_RoutingElement_s hopp4; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = gwSinkID1; + hopp2.domainID = domainID2; + hopp2.connectionFormat = gwSink1.listConnectionFormats[0]; + + hopp3.sourceID = gwSourceID1; + hopp3.sinkID = gwSinkID2; + hopp3.domainID = domainID3; + hopp3.connectionFormat = gwSink2.listConnectionFormats[0]; + + hopp4.sourceID = gwSourceID2; + hopp4.sinkID = sinkID; + hopp4.domainID = domainID4; + hopp4.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + listRoutingElements.push_back(hopp3); + listRoutingElements.push_back(hopp4); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + am::am_Source_s sourceDb; + am::am_Sink_s sinkDb; + pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb); + pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb); + listRoutes.clear(); + getRoute(false, sourceDb, sinkDb, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + +TEST_F(CAmRouterMapTest,getAllowedFormatsFromConvMatrix) +{ + std::vector<bool> convertionMatrix; + convertionMatrix.push_back(1); + convertionMatrix.push_back(0); + convertionMatrix.push_back(0); + convertionMatrix.push_back(1); + convertionMatrix.push_back(1); + convertionMatrix.push_back(0); + + std::vector<am_CustomConnectionFormat_t> listSourceFormats; + listSourceFormats.push_back(CF_GENIVI_ANALOG); + listSourceFormats.push_back(CF_GENIVI_STEREO); + + std::vector<am_CustomConnectionFormat_t> listSinkFormats; + listSinkFormats.push_back(CF_GENIVI_MONO); + listSinkFormats.push_back(CF_GENIVI_AUTO); + listSinkFormats.push_back(CF_GENIVI_STEREO); + + std::vector<am_CustomConnectionFormat_t> sourceFormats; + std::vector<am_CustomConnectionFormat_t> sinkFormats; + + ASSERT_TRUE(CAmRouter::getAllowedFormatsFromConvMatrix(convertionMatrix, listSourceFormats, listSinkFormats, sourceFormats, sinkFormats)); + + ASSERT_TRUE(sourceFormats.size()==3); + ASSERT_TRUE(sinkFormats.size()==3); + ASSERT_TRUE(sourceFormats.at(0)==CF_GENIVI_ANALOG); + ASSERT_TRUE(sourceFormats.at(1)==CF_GENIVI_STEREO); + ASSERT_TRUE(sourceFormats.at(2)==CF_GENIVI_ANALOG); + ASSERT_TRUE(sinkFormats.at(0)==CF_GENIVI_MONO); + ASSERT_TRUE(sinkFormats.at(1)==CF_GENIVI_AUTO); + ASSERT_TRUE(sinkFormats.at(2)==CF_GENIVI_STEREO); + + sinkFormats.clear(); + sourceFormats.clear(); + convertionMatrix.clear(); + listSinkFormats.clear(); + listSourceFormats.clear(); + + convertionMatrix.push_back(1); + listSinkFormats.push_back(CF_GENIVI_STEREO); + listSourceFormats.push_back(CF_GENIVI_STEREO); + + ASSERT_TRUE(CAmRouter::getAllowedFormatsFromConvMatrix(convertionMatrix, listSourceFormats, listSinkFormats, sourceFormats, sinkFormats)); + + sinkFormats.clear(); + sourceFormats.clear(); + convertionMatrix.clear(); + listSinkFormats.clear(); + listSourceFormats.clear(); + + convertionMatrix.push_back(1); + convertionMatrix.push_back(0); + listSourceFormats.push_back(CF_GENIVI_STEREO); + listSinkFormats.push_back(CF_GENIVI_STEREO); + + ASSERT_FALSE(CAmRouter::getAllowedFormatsFromConvMatrix(convertionMatrix, listSourceFormats, listSinkFormats, sourceFormats, sinkFormats)); + + sinkFormats.clear(); + sourceFormats.clear(); + convertionMatrix.clear(); + listSinkFormats.clear(); + listSourceFormats.clear(); + + convertionMatrix.push_back(1); + listSinkFormats.push_back(CF_GENIVI_STEREO); + + ASSERT_FALSE(CAmRouter::getAllowedFormatsFromConvMatrix(convertionMatrix, listSourceFormats, listSinkFormats, sourceFormats, sinkFormats)); +} + +TEST_F(CAmRouterMapTest,route1Domain1Source1Sink) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + am_domainID_t domainID1; + enterDomainDB("domain1", domainID1); + + am_sourceID_t sourceID; + std::vector<am_CustomConnectionFormat_t> cf1; + cf1.push_back(CF_GENIVI_STEREO); + cf1.push_back(CF_GENIVI_ANALOG); + enterSourceDB("source1", domainID1, cf1, sourceID); + + am_sinkID_t sinkID; + std::vector<am_CustomConnectionFormat_t> cf2; + cf2.push_back(CF_GENIVI_ANALOG); + cf2.push_back(CF_GENIVI_MONO); + enterSinkDB("sink1", domainID1, cf2, sinkID); + + am::am_Source_s source; + am::am_Sink_s sink; + + pDatabaseHandler.getSinkInfoDB(sinkID, sink); + pDatabaseHandler.getSourceInfoDB(sourceID, source); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + + hopp1.sourceID = sourceID; + hopp1.sinkID = sinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = cf2[0]; + + listRoutingElements.push_back(hopp1); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + getRoute(false, source, sink, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + +TEST_F(CAmRouterMapTest,route1Domain1Source1Converter1Sink) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + am_domainID_t domainID1; + enterDomainDB("domain1", domainID1); + + am_sourceID_t sourceID; + std::vector<am_CustomConnectionFormat_t> cf1; + cf1.push_back(CF_GENIVI_STEREO); + cf1.push_back(CF_GENIVI_AUTO); + enterSourceDB("source1", domainID1, cf1, sourceID); + + am_sinkID_t sinkID1, sinkID2; + std::vector<am_CustomConnectionFormat_t> cf2; + cf2.push_back(CF_GENIVI_MONO); + cf2.push_back(CF_GENIVI_ANALOG); + enterSinkDB("sink1", domainID1, cf2, sinkID1); + enterSinkDB("sink2", domainID1, cf2, sinkID2); + + am_sourceID_t gwSourceID; + std::vector<am_CustomConnectionFormat_t> cf3; + cf3.push_back(CF_GENIVI_MONO); + cf3.push_back(CF_GENIVI_ANALOG); + enterSourceDB("gwSource1", domainID1, cf3, gwSourceID); + + am_sinkID_t gwSinkID; + std::vector<am_CustomConnectionFormat_t> cf4; + cf4.push_back(CF_GENIVI_STEREO); + cf4.push_back(CF_GENIVI_ANALOG); + enterSinkDB("gwSink1", domainID1, cf4, gwSinkID); + + am_converterID_t converterID; + std::vector<bool> matrix; + matrix.resize(4, false); + matrix[0]=(true); + matrix[1]=(true); + enterConverterDB("converter", domainID1, cf3, cf4, matrix, gwSourceID, gwSinkID, converterID); + + am::am_Source_s source; + am::am_Sink_s sink; + + pDatabaseHandler.getSinkInfoDB(sinkID1, sink); + pDatabaseHandler.getSourceInfoDB(sourceID, source); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = CF_GENIVI_STEREO; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = sinkID1; + hopp2.domainID = domainID1; + hopp2.connectionFormat = CF_GENIVI_MONO; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID1; + compareRoute.sourceID = sourceID; + + getRoute(false, source, sink, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + +TEST_F(CAmRouterMapTest,route1Domain1Source3Converters1Sink) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + am_domainID_t domainID1; + enterDomainDB("domain1", domainID1); + + std::vector<am_CustomConnectionFormat_t> cf1; + cf1.push_back(CF_GENIVI_STEREO); + std::vector<am_CustomConnectionFormat_t> cf2; + cf2.push_back(CF_GENIVI_MONO); + std::vector<am_CustomConnectionFormat_t> cf3; + cf3.push_back(CF_GENIVI_AUTO); + + am_sourceID_t sourceID; + enterSourceDB("source1", domainID1, cf1, sourceID); + + am_sinkID_t sinkID; + enterSinkDB("sink1", domainID1, cf3, sinkID); + + am_sourceID_t gwSourceID; + enterSourceDB("gwSource1", domainID1, cf2, gwSourceID); + am_sinkID_t gwSinkID; + enterSinkDB("gwSink1", domainID1, cf1, gwSinkID); + am_converterID_t converterID; + std::vector<bool> matrix; + matrix.push_back(true); + enterConverterDB("converter1", domainID1, cf2, cf1, matrix, gwSourceID, gwSinkID, converterID); + + am_sourceID_t gwSourceID1; + enterSourceDB("gwSource2", domainID1, cf2, gwSourceID1); + am_sinkID_t gwSinkID1; + enterSinkDB("gwSink2", domainID1, cf1, gwSinkID1); + am_converterID_t converterID1; + enterConverterDB("converter2", domainID1, cf2, cf1, matrix, gwSourceID1, gwSinkID1, converterID1); + + am_sourceID_t gwSourceID2; + enterSourceDB("gwSource3", domainID1, cf3, gwSourceID2); + am_sinkID_t gwSinkID2; + enterSinkDB("gwSink3", domainID1, cf2, gwSinkID2); + am_converterID_t converterID2; + enterConverterDB("converter3", domainID1, cf3, cf2, matrix, gwSourceID2, gwSinkID2, converterID2); + + am::am_Source_s source; + am::am_Sink_s sink; + pDatabaseHandler.getSinkInfoDB(sinkID, sink); + pDatabaseHandler.getSourceInfoDB(sourceID, source); + + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements1; + std::vector<am_RoutingElement_s> listRoutingElements2; + am_RoutingElement_s hopp11; + am_RoutingElement_s hopp12; + am_RoutingElement_s hopp13; + am_RoutingElement_s hopp21; + am_RoutingElement_s hopp22; + + hopp11.sourceID = sourceID; + hopp11.sinkID = gwSinkID; + hopp11.domainID = domainID1; + hopp11.connectionFormat = CF_GENIVI_STEREO; + + hopp12.sourceID = gwSourceID; + hopp12.sinkID = gwSinkID2; + hopp12.domainID = domainID1; + hopp12.connectionFormat = CF_GENIVI_MONO; + + hopp21.sourceID = sourceID; + hopp21.sinkID = gwSinkID1; + hopp21.domainID = domainID1; + hopp21.connectionFormat = CF_GENIVI_STEREO; + + hopp22.sourceID = gwSourceID1; + hopp22.sinkID = gwSinkID2; + hopp22.domainID = domainID1; + hopp22.connectionFormat = CF_GENIVI_MONO; + + hopp13.sourceID = gwSourceID2; + hopp13.sinkID = sinkID; + hopp13.domainID = domainID1; + hopp13.connectionFormat = CF_GENIVI_AUTO; + + listRoutingElements1.push_back(hopp11); + listRoutingElements1.push_back(hopp12); + listRoutingElements1.push_back(hopp13); + + listRoutingElements2.push_back(hopp21); + listRoutingElements2.push_back(hopp22); + listRoutingElements2.push_back(hopp13); + + am_Route_s compareRoute1; + compareRoute1.route = listRoutingElements1; + compareRoute1.sinkID = sinkID; + compareRoute1.sourceID = sourceID; + + getRoute(false, source, sink, listRoutes); + ASSERT_EQ(static_cast<uint>(2), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute1,listRoutes[0])||pCF.compareRoute(compareRoute1,listRoutes[1])); + + am_Route_s compareRoute2; + compareRoute2.route = listRoutingElements2; + compareRoute2.sinkID = sinkID; + compareRoute2.sourceID = sourceID; + ASSERT_TRUE(pCF.compareRoute(compareRoute2,listRoutes[1])||pCF.compareRoute(compareRoute2,listRoutes[0])); +} + +TEST_F(CAmRouterMapTest,route2Domains1Source1Sink) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + am_domainID_t domainID1, domainID2; + enterDomainDB("domain1", domainID1); + enterDomainDB("domain2", domainID2); + + am_sourceID_t sourceID; + std::vector<am_CustomConnectionFormat_t> cf1; + cf1.push_back(CF_GENIVI_STEREO); + enterSourceDB("source1", domainID1, cf1, sourceID); + + am_sinkID_t sinkID; + std::vector<am_CustomConnectionFormat_t> cf2; + cf2.push_back(CF_GENIVI_ANALOG); + enterSinkDB("sink1", domainID2, cf2, sinkID); + + am_sourceID_t gwSourceID; + std::vector<am_CustomConnectionFormat_t> cf3; + cf3.push_back(CF_GENIVI_ANALOG); + enterSourceDB("gwSource1", domainID2, cf3, gwSourceID); + + am_sinkID_t gwSinkID; + std::vector<am_CustomConnectionFormat_t> cf4; + cf4.push_back(CF_GENIVI_STEREO); + enterSinkDB("gwSink1", domainID1, cf4, gwSinkID); + + am_gatewayID_t gatewayID; + std::vector<bool> matrix; + matrix.push_back(true); + enterGatewayDB("gateway", domainID2, domainID1, cf3, cf4, matrix, gwSourceID, gwSinkID, gatewayID); + + am::am_Source_s source; + am::am_Sink_s sink; + + pDatabaseHandler.getSinkInfoDB(sinkID, sink); + pDatabaseHandler.getSourceInfoDB(sourceID, source); + std::vector<am_Route_s> listRoutes; + + getRoute(false, source, sink, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + + am_Route_s compareRoute1; + compareRoute1.sinkID = sinkID; + compareRoute1.sourceID = sourceID; + compareRoute1.route.push_back({sourceID, gwSinkID, domainID1, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gwSourceID, sinkID, domainID2, CF_GENIVI_ANALOG}); + ASSERT_TRUE(pCF.compareRoute(compareRoute1,listRoutes[0])); +} + +TEST_F(CAmRouterMapTest,route3Domains1Source1Sink) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + am_domainID_t domainID1, domainID2, domainID3; + enterDomainDB("domain1", domainID1); + enterDomainDB("domain2", domainID2); + enterDomainDB("domain3", domainID3); + + std::vector<am_CustomConnectionFormat_t> cfStereo; + cfStereo.push_back(CF_GENIVI_STEREO); + std::vector<am_CustomConnectionFormat_t> cfAnalog; + cfAnalog.push_back(CF_GENIVI_ANALOG); + std::vector<am_CustomConnectionFormat_t> cfMono; + cfMono.push_back(CF_GENIVI_MONO); + + am_sourceID_t sourceID; + enterSourceDB("source1", domainID1, cfStereo, sourceID); + + am_sinkID_t gwSinkID1; + enterSinkDB("gwSink1", domainID1, cfStereo, gwSinkID1); + + am_sourceID_t gwSourceID1; + enterSourceDB("gwSource1", domainID2, cfMono, gwSourceID1); + + std::vector<bool> matrix; + matrix.push_back(true); + + am_gatewayID_t gatewayID; + enterGatewayDB("gateway", domainID2, domainID1, cfMono, cfStereo, matrix, gwSourceID1, gwSinkID1, gatewayID); + + am_sourceID_t gwSourceID2; + enterSourceDB("gwSource2", domainID3, cfStereo, gwSourceID2); + + am_sinkID_t gwSinkID2; + enterSinkDB("gwSink2", domainID2, cfMono, gwSinkID2); + + am_sinkID_t sinkID; + enterSinkDB("sink1", domainID3, cfStereo, sinkID); + + am_gatewayID_t gatewayID1; + enterGatewayDB("gateway", domainID3, domainID2, cfStereo, cfMono, matrix, gwSourceID2, gwSinkID2, gatewayID1); + + am::am_Source_s source; + am::am_Sink_s sink; + + pDatabaseHandler.getSinkInfoDB(sinkID, sink); + pDatabaseHandler.getSourceInfoDB(sourceID, source); + + std::vector<am_Route_s> listRoutes; + + getRoute(false, source, sink, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + + am_Route_s compareRoute1; + compareRoute1.sinkID = sinkID; + compareRoute1.sourceID = sourceID; + compareRoute1.route.push_back({sourceID, gwSinkID1, domainID1, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gwSourceID1, gwSinkID2, domainID2, CF_GENIVI_MONO}); + compareRoute1.route.push_back({gwSourceID2, sinkID, domainID3, CF_GENIVI_STEREO}); + ASSERT_TRUE(pCF.compareRoute(compareRoute1,listRoutes[0])); +} + +TEST_F(CAmRouterMapTest,routeSource1Sink2PathThroughConv1Gate1) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + std::vector<bool> matrix; + matrix.push_back(true); + am_domainID_t domainID1, domainID2; + enterDomainDB("domain1", domainID1); + enterDomainDB("domain2", domainID2); + + std::vector<am_CustomConnectionFormat_t> cfStereo; + cfStereo.push_back(CF_GENIVI_STEREO); + std::vector<am_CustomConnectionFormat_t> cfAnalog; + cfAnalog.push_back(CF_GENIVI_ANALOG); + std::vector<am_CustomConnectionFormat_t> cfMono; + cfMono.push_back(CF_GENIVI_MONO); + std::vector<am_CustomConnectionFormat_t> cfAuto; + cfAuto.push_back(CF_GENIVI_AUTO); + + am_sourceID_t sourceID; + enterSourceDB("source1", domainID1, cfStereo, sourceID); + + am_sinkID_t gwSinkID1; + enterSinkDB("gwSink1", domainID1, cfMono, gwSinkID1); + + am_sinkID_t coSinkID21; + enterSinkDB("coSink21", domainID1, cfStereo, coSinkID21); + + am_sourceID_t coSourceID21; + enterSourceDB("coSource21", domainID1, cfMono, coSourceID21); + + am_converterID_t converterID1; + enterConverterDB("converter1", domainID1, cfMono, cfStereo, matrix, coSourceID21, coSinkID21, converterID1); + + am_sourceID_t gwSourceID1; + enterSourceDB("gwSource21", domainID2, cfAuto, gwSourceID1); + + am_gatewayID_t gatewayID; + enterGatewayDB("gateway1", domainID2, domainID1, cfAuto, cfMono, matrix, gwSourceID1, gwSinkID1, gatewayID); + + am_sinkID_t sinkID1; + enterSinkDB("sink1", domainID2, cfAuto, sinkID1); + + am_sinkID_t sinkID2; + enterSinkDB("sink2", domainID1, cfAuto, sinkID2); + + am::am_Source_s source; + am::am_Sink_s sink1; + pDatabaseHandler.getSinkInfoDB(sinkID1, sink1); + am::am_Sink_s sink2; + pDatabaseHandler.getSinkInfoDB(sinkID2, sink2); + pDatabaseHandler.getSourceInfoDB(sourceID, source); + + std::vector<am_Route_s> listRoutes; + + getRoute(false, source, sink1, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + + am_Route_s compareRoute1; + compareRoute1.sinkID = sinkID1; + compareRoute1.sourceID = sourceID; + compareRoute1.route.push_back({sourceID, coSinkID21, domainID1, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({coSourceID21, gwSinkID1, domainID1, CF_GENIVI_MONO}); + compareRoute1.route.push_back({gwSourceID1, sinkID1, domainID2, CF_GENIVI_AUTO}); + ASSERT_TRUE(pCF.compareRoute(compareRoute1,listRoutes[0])); + + listRoutes.clear(); + getRoute(false, source, sink2, listRoutes); + ASSERT_EQ(static_cast<uint>(0), listRoutes.size()); +} + +TEST_F(CAmRouterMapTest, routeSource1Sink1PathThroughDomain2) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + std::vector<bool> matrix; + matrix.push_back(true); + am_domainID_t domainID1, domainID2; + enterDomainDB("domain1", domainID1); + enterDomainDB("domain2", domainID2); + + std::vector<am_CustomConnectionFormat_t> cfStereo; + cfStereo.push_back(CF_GENIVI_STEREO); + std::vector<am_CustomConnectionFormat_t> cfAnalog; + cfAnalog.push_back(CF_GENIVI_ANALOG); + std::vector<am_CustomConnectionFormat_t> cfMono; + cfMono.push_back(CF_GENIVI_MONO); + std::vector<am_CustomConnectionFormat_t> cfAuto; + cfAuto.push_back(CF_GENIVI_AUTO); + + am_sourceID_t sourceID; + enterSourceDB("source1", domainID1, cfStereo, sourceID); + + am_sinkID_t gwSinkID11; + enterSinkDB("gwSink11", domainID1, cfStereo, gwSinkID11); + am_sourceID_t gwSourceID11; + enterSourceDB("gwSource11", domainID2, cfAnalog, gwSourceID11); + am_converterID_t gatewayID1; + enterGatewayDB("gateway1", domainID2, domainID1, cfAnalog, cfStereo, matrix, gwSourceID11, gwSinkID11, gatewayID1); + + am_sinkID_t gwSinkID21; + enterSinkDB("gwSink21", domainID2, cfAnalog, gwSinkID21); + am_sourceID_t gwSourceID12; + enterSourceDB("gwSource12", domainID1, cfAuto, gwSourceID12); + am_gatewayID_t gatewayID2; + enterGatewayDB("gateway2", domainID1, domainID2, cfAuto, cfAnalog, matrix, gwSourceID12, gwSinkID21, gatewayID2); + + am_sinkID_t sink1ID; + enterSinkDB("sink1", domainID1, cfAuto, sink1ID); + am_sinkID_t sink2ID; + enterSinkDB("sink2", domainID2, cfAnalog, sink2ID); + + std::vector<am_Route_s> listRoutes; + + am::am_Source_s source; + am::am_Sink_s sink1; + pDatabaseHandler.getSinkInfoDB(sink1ID, sink1); + pDatabaseHandler.getSourceInfoDB(sourceID, source); + + getRoute(false, source, sink1, listRoutes); + ASSERT_EQ(static_cast<uint>(0), listRoutes.size()); + + am::am_Sink_s sink2; + pDatabaseHandler.getSinkInfoDB(sink2ID, sink2); + + getRoute(false, source, sink2, listRoutes); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + + am_Route_s compareRoute1; + compareRoute1.sinkID = sink2ID; + compareRoute1.sourceID = sourceID; + compareRoute1.route.push_back({sourceID, gwSinkID11, domainID1, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gwSourceID11, sink2ID, domainID2, CF_GENIVI_ANALOG}); + ASSERT_TRUE(pCF.compareRoute(compareRoute1,listRoutes[0])); +} + +TEST_F(CAmRouterMapTest, routeSource1Sink1PathThroughGate1Conv2Gate2) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + std::vector<bool> matrix; + matrix.push_back(true); + am_domainID_t domainID1, domainID2; + enterDomainDB("domain1", domainID1); + enterDomainDB("domain2", domainID2); + + std::vector<am_CustomConnectionFormat_t> cfStereo; + cfStereo.push_back(CF_GENIVI_STEREO); + std::vector<am_CustomConnectionFormat_t> cfAnalog; + cfAnalog.push_back(CF_GENIVI_ANALOG); + std::vector<am_CustomConnectionFormat_t> cfMono; + cfMono.push_back(CF_GENIVI_MONO); + std::vector<am_CustomConnectionFormat_t> cfAuto; + cfAuto.push_back(CF_GENIVI_AUTO); + + am_sourceID_t sourceID; + enterSourceDB("source1", domainID1, cfStereo, sourceID); + + am_sinkID_t gwSinkID11; + enterSinkDB("gwSink11", domainID1, cfStereo, gwSinkID11); + + am_sourceID_t gwSourceID21; + enterSourceDB("gwSource21", domainID2, cfAnalog, gwSourceID21); + + am_converterID_t gatewayID1; + enterGatewayDB("gateway1", domainID2, domainID1, cfAnalog, cfStereo, matrix, gwSourceID21, gwSinkID11, gatewayID1); + + am_sinkID_t gwSinkID21; + enterSinkDB("gwSink21", domainID2, cfStereo, gwSinkID21); + + am_sourceID_t gwSourceID12; + enterSourceDB("gwSource12", domainID1, cfAuto, gwSourceID12); + + am_sinkID_t coSinkID21; + enterSinkDB("coSink21", domainID2, cfAnalog, coSinkID21); + + am_sourceID_t coSourceID21; + enterSourceDB("coSource21", domainID2, cfStereo, coSourceID21); + + am_converterID_t converterID2; + enterConverterDB("converter2", domainID2, cfStereo, cfAnalog, matrix, coSourceID21, coSinkID21, converterID2); + + am_gatewayID_t gatewayID2; + enterGatewayDB("gateway2", domainID1, domainID2, cfAuto, cfStereo, matrix, gwSourceID12, gwSinkID21, gatewayID2); + + am_sinkID_t sink1ID; + enterSinkDB("sink1", domainID1, cfAuto, sink1ID); + am_sinkID_t sink2ID; + enterSinkDB("sink2", domainID2, cfStereo, sink2ID); + + am::am_Source_s source; + am::am_Sink_s sink; + + pDatabaseHandler.getSinkInfoDB(sink1ID, sink); + pDatabaseHandler.getSourceInfoDB(sourceID, source); + + std::vector<am_Route_s> listRoutes; + + getRoute(false, source, sink, listRoutes); + ASSERT_EQ(static_cast<uint>(0), listRoutes.size()); + + am::am_Sink_s sink1; + pDatabaseHandler.getSinkInfoDB(sink2ID, sink1); + getRoute(false, source, sink1, listRoutes); + + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + am_Route_s compareRoute1; + compareRoute1.sinkID = sink2ID; + compareRoute1.sourceID = sourceID; + compareRoute1.route.push_back({sourceID, gwSinkID11, domainID1, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gwSourceID21, coSinkID21, domainID2, CF_GENIVI_ANALOG}); + compareRoute1.route.push_back({coSourceID21, sink2ID, domainID2, CF_GENIVI_STEREO}); + ASSERT_TRUE(pCF.compareRoute(compareRoute1,listRoutes[0])); +} + +TEST_F(CAmRouterMapTest, routeSource1Sink1PathThroughConv1Gate1Conv2Gate2) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + std::vector<bool> matrix; + matrix.push_back(true); + am_domainID_t domainID1, domainID2; + enterDomainDB("domain1", domainID1); + enterDomainDB("domain2", domainID2); + + std::vector<am_CustomConnectionFormat_t> cfStereo; + cfStereo.push_back(CF_GENIVI_STEREO); + std::vector<am_CustomConnectionFormat_t> cfAnalog; + cfAnalog.push_back(CF_GENIVI_ANALOG); + std::vector<am_CustomConnectionFormat_t> cfMono; + cfMono.push_back(CF_GENIVI_MONO); + std::vector<am_CustomConnectionFormat_t> cfAuto; + cfAuto.push_back(CF_GENIVI_AUTO); + std::vector<am_CustomConnectionFormat_t> cfFuture1; + cfFuture1.push_back(5); + std::vector<am_CustomConnectionFormat_t> cfFuture2; + cfFuture2.push_back(6); + + am_sourceID_t sourceID; + enterSourceDB("source1", domainID1, cfStereo, sourceID); + + am_sinkID_t coSinkID11; + enterSinkDB("coSink11", domainID1, cfStereo, coSinkID11); + am_sourceID_t coSourceID11; + enterSourceDB("coSource11", domainID1, cfFuture1, coSourceID11); + am_converterID_t converterID11; + enterConverterDB("converter11", domainID1, cfFuture1, cfStereo, matrix, coSourceID11, coSinkID11, converterID11); + + am_sinkID_t coSinkID12; + enterSinkDB("coSink12", domainID1, cfStereo, coSinkID12); + am_sourceID_t coSourceID12; + enterSourceDB("coSource12", domainID1, cfFuture2, coSourceID12); + am_converterID_t converterID12; + enterConverterDB("converter12", domainID1, cfFuture2, cfStereo, matrix, coSourceID12, coSinkID12, converterID12); + + am_sinkID_t coSinkID13; + enterSinkDB("coSink13", domainID1, cfFuture2, coSinkID13); + am_sourceID_t coSourceID13; + enterSourceDB("coSource13", domainID1, cfFuture1, coSourceID13); + am_converterID_t converterID13; + enterConverterDB("converter13", domainID1, cfFuture1, cfFuture2, matrix, coSourceID13, coSinkID13, converterID13); + + am_sinkID_t gwSinkID11; + enterSinkDB("gwSink11", domainID1, cfFuture1, gwSinkID11); + am_sourceID_t gwSourceID21; + enterSourceDB("gwSource21", domainID2, cfAnalog, gwSourceID21); + am_converterID_t gatewayID1; + enterGatewayDB("gateway1", domainID2, domainID1, cfAnalog, cfFuture1, matrix, gwSourceID21, gwSinkID11, gatewayID1); + + am_sinkID_t gwSinkID21; + enterSinkDB("gwSink21", domainID2, cfStereo, gwSinkID21); + + am_sourceID_t gwSourceID12; + enterSourceDB("gwSource12", domainID1, cfAuto, gwSourceID12); + + am_sinkID_t coSinkID21; + enterSinkDB("coSink21", domainID2, cfAnalog, coSinkID21); + + am_sourceID_t coSourceID21; + enterSourceDB("coSource21", domainID2, cfStereo, coSourceID21); + + am_converterID_t converterID2; + enterConverterDB("converter2", domainID2, cfStereo, cfAnalog, matrix, coSourceID21, coSinkID21, converterID2); + + + am_gatewayID_t gatewayID2; + enterGatewayDB("gateway2", domainID1, domainID2, cfAuto, cfStereo, matrix, gwSourceID12, gwSinkID21, gatewayID2); + + am_sinkID_t sinkID; + enterSinkDB("sink1", domainID1, cfAuto, sinkID); + + am::am_Source_s source; + am::am_Sink_s sink; + pDatabaseHandler.getSinkInfoDB(sinkID, sink); + pDatabaseHandler.getSourceInfoDB(sourceID, source); + + std::vector<am_Route_s> listRoutes; + + getRoute(false, source, sink, listRoutes); + ASSERT_EQ(static_cast<uint>(0), listRoutes.size()); + + am::am_Sink_s sink2; + pDatabaseHandler.getSinkInfoDB(coSinkID21, sink2); + pRouter.getRoute(false, source, sink2, listRoutes); + ASSERT_EQ(static_cast<uint>(2), listRoutes.size()); + + am_Route_s compareRoute1; + compareRoute1.sinkID = coSinkID21; + compareRoute1.sourceID = sourceID; + compareRoute1.route.push_back({sourceID, coSinkID11, domainID1, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({coSourceID11, gwSinkID11, domainID1, 5}); + compareRoute1.route.push_back({gwSourceID21, coSinkID21, domainID2, CF_GENIVI_ANALOG}); + + am_Route_s compareRoute2; + compareRoute2.sinkID = coSinkID21; + compareRoute2.sourceID = sourceID; + compareRoute2.route.push_back({sourceID, coSinkID12, domainID1, CF_GENIVI_STEREO}); + compareRoute2.route.push_back({coSourceID12, coSinkID13, domainID1, 6}); + compareRoute2.route.push_back({coSourceID13, gwSinkID11, domainID1, 5}); + compareRoute2.route.push_back({gwSourceID21, coSinkID21, domainID2, CF_GENIVI_ANALOG}); + + ASSERT_TRUE(pCF.compareRoute(compareRoute1,listRoutes[1])||pCF.compareRoute(compareRoute1,listRoutes[0])); + ASSERT_TRUE(pCF.compareRoute(compareRoute2,listRoutes[0])||pCF.compareRoute(compareRoute2,listRoutes[1])); +} + +TEST_F(CAmRouterMapTest,route3Domains1Source1SinkGwCycles) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + am_domainID_t domain1ID, domain2ID, domain3ID; + enterDomainDB("domain1", domain1ID); + enterDomainDB("domain2", domain2ID); + enterDomainDB("domain3", domain3ID); + + //just make so many cycles as possible + std::vector<am_CustomConnectionFormat_t> cfStereo; + cfStereo.push_back(CF_GENIVI_STEREO); + std::vector<am_CustomConnectionFormat_t> cfAnalog = cfStereo; + std::vector<am_CustomConnectionFormat_t> cfMono = cfStereo; + std::vector<am_CustomConnectionFormat_t> cfAuto; + cfAuto.push_back(CF_GENIVI_AUTO); + + am_sourceID_t source1ID; + enterSourceDB("source1", domain1ID, cfStereo, source1ID); + am_sinkID_t gw1SinkID; + enterSinkDB("gw1Sink", domain1ID, cfStereo, gw1SinkID); + am_sinkID_t gw2SinkID; + enterSinkDB("gw2Sink", domain1ID, cfStereo, gw2SinkID); + am_sourceID_t gw3SourceID; + enterSourceDB("gw3Source", domain1ID, cfAnalog, gw3SourceID); + am_sourceID_t gw4SourceID; + enterSourceDB("gw4Source", domain1ID, cfAnalog, gw4SourceID); + am_sinkID_t gw5SinkID; + enterSinkDB("gw5Sink", domain1ID, cfAnalog, gw5SinkID); + + am_sourceID_t gw1SourceID; + enterSourceDB("gw1Source", domain2ID, cfMono, gw1SourceID); + am_sourceID_t gw2SourceID; + enterSourceDB("gw2Source", domain2ID, cfMono, gw2SourceID); + am_sinkID_t gw3SinkID; + enterSinkDB("gw3Sink", domain2ID, cfMono, gw3SinkID); + am_sinkID_t gw4SinkID; + enterSinkDB("gw4Sink", domain2ID, cfMono, gw4SinkID); + + am_sourceID_t gw5SourceID; + enterSourceDB("gw5Source", domain3ID, cfStereo, gw5SourceID); + am_sinkID_t sink1ID; + enterSinkDB("sink1", domain3ID, cfStereo, sink1ID); + + std::vector<bool> matrixT; + matrixT.push_back(true); + std::vector<bool> matrixF; + matrixF.push_back(false); + + am_gatewayID_t gateway1ID; + enterGatewayDB("gateway1", domain2ID, domain1ID, cfMono, cfStereo, matrixT, gw1SourceID, gw1SinkID, gateway1ID); + am_gatewayID_t gateway2ID; + enterGatewayDB("gateway2", domain2ID, domain1ID, cfMono, cfStereo, matrixT, gw2SourceID, gw2SinkID, gateway2ID); + am_gatewayID_t gateway3ID; + enterGatewayDB("gateway3", domain1ID, domain2ID, cfAnalog, cfMono, matrixT, gw3SourceID, gw3SinkID, gateway3ID); + am_gatewayID_t gateway4ID; + enterGatewayDB("gateway4", domain1ID, domain2ID, cfAnalog, cfMono, matrixT, gw4SourceID, gw4SinkID, gateway4ID); + am_gatewayID_t gateway5ID; + enterGatewayDB("gateway5", domain3ID, domain1ID, cfStereo, cfAnalog, matrixT, gw5SourceID, gw5SinkID, gateway5ID); + + pRouter.load(false); + + CAmRoutingNode* sourceNode = pRouter.sourceNodeWithID(source1ID); + CAmRoutingNode* sinkNode = pRouter.sinkNodeWithID(sink1ID); + + ASSERT_TRUE(sourceNode); + ASSERT_TRUE(sinkNode); + + std::vector<am_Route_s> listRoutes; + std::vector<std::vector<CAmRoutingNode*>> resultNodesPath; + + am_Route_s compareRoute1; + compareRoute1.sinkID = sink1ID; + compareRoute1.sourceID = source1ID; + +#define DO_ASSERT() \ + {\ + bool didMatch = false; \ + for(auto it = listRoutes.begin(); it!=listRoutes.end(); it++) \ + didMatch|=pCF.compareRoute(compareRoute1,*it); \ + ASSERT_TRUE(didMatch); \ + } + +#ifdef ROUTING_BUILD_CONNECTIONS + getAllPaths(*sourceNode, *sinkNode, listRoutes, resultNodesPath, true); + ASSERT_EQ(static_cast<uint>(9), listRoutes.size()); + + compareRoute1.route.clear(); + compareRoute1.route.push_back({source1ID, gw2SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw2SourceID, gw4SinkID, domain2ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw4SourceID, gw5SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO}); + DO_ASSERT() + + compareRoute1.route.clear(); + compareRoute1.route.push_back({source1ID, gw1SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw1SourceID, gw3SinkID, domain2ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw3SourceID, gw5SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO}); + DO_ASSERT() + + compareRoute1.route.clear(); + compareRoute1.route.push_back({source1ID, gw2SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw2SourceID, gw3SinkID, domain2ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw3SourceID, gw5SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO}); + DO_ASSERT() + + compareRoute1.route.clear(); + compareRoute1.route.push_back({source1ID, gw1SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw1SourceID, gw4SinkID, domain2ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw4SourceID, gw5SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO}); + DO_ASSERT() + + compareRoute1.route.clear(); + compareRoute1.route.push_back({source1ID, gw2SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw2SourceID, gw4SinkID, domain2ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw4SourceID, gw1SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw1SourceID, gw3SinkID, domain2ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw3SourceID, gw5SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO}); + DO_ASSERT() + + compareRoute1.route.clear(); + compareRoute1.route.push_back({source1ID, gw2SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw2SourceID, gw3SinkID, domain2ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw3SourceID, gw1SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw1SourceID, gw4SinkID, domain2ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw4SourceID, gw5SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO}); + DO_ASSERT() + + compareRoute1.route.clear(); + compareRoute1.route.push_back({source1ID, gw1SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw1SourceID, gw3SinkID, domain2ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw3SourceID, gw2SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw2SourceID, gw4SinkID, domain2ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw4SourceID, gw5SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO}); + DO_ASSERT() + + compareRoute1.route.clear(); + compareRoute1.route.push_back({source1ID, gw1SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw1SourceID, gw4SinkID, domain2ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw4SourceID, gw2SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw2SourceID, gw3SinkID, domain2ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw3SourceID, gw5SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO}); + DO_ASSERT() + + compareRoute1.route.clear(); + compareRoute1.route.push_back({source1ID, gw5SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO}); + DO_ASSERT() +#else + compareRoute1.route.clear(); + compareRoute1.route.push_back({source1ID, gw5SinkID, domain1ID, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO}); +#endif + + listRoutes.clear(); + resultNodesPath.clear(); + getAllPaths(*sourceNode, *sinkNode, listRoutes, resultNodesPath, false); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + DO_ASSERT() +} + +TEST_F(CAmRouterMapTest,route3Domains1Source3Gateways3Convertres1Sink) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + am_domainID_t domainID1, domainID2, domainID3; + enterDomainDB("domain1", domainID1); + enterDomainDB("domain2", domainID2); + enterDomainDB("domain3", domainID3); + + std::vector<am_CustomConnectionFormat_t> cfStereo; + cfStereo.push_back(CF_GENIVI_STEREO); + std::vector<am_CustomConnectionFormat_t> cfAnalog; + cfAnalog.push_back(CF_GENIVI_ANALOG); + std::vector<am_CustomConnectionFormat_t> cfMono; + cfMono.push_back(CF_GENIVI_MONO); + std::vector<am_CustomConnectionFormat_t> cfAuto; + cfAuto.push_back(CF_GENIVI_AUTO); + + am_sourceID_t sourceID; + enterSourceDB("source1", domainID1, cfStereo, sourceID); + am_sinkID_t gwSinkID1; + enterSinkDB("gwSink1", domainID1, cfStereo, gwSinkID1); + am_sinkID_t gwSinkID21; + enterSinkDB("gwSink21", domainID1, cfStereo, gwSinkID21); + + am_sourceID_t gwSourceID1; + enterSourceDB("gwSource1", domainID2, cfMono, gwSourceID1); + am_sinkID_t gwSinkID22; + enterSinkDB("gwSink22", domainID2, cfMono, gwSinkID22); + + am_sourceID_t gwSourceID21; + enterSourceDB("gwSource21", domainID3, cfAuto, gwSourceID21); + + am_sourceID_t gwSourceID22; + enterSourceDB("gwSource22", domainID3, cfAuto, gwSourceID22); + am_sourceID_t gwSourceID5; + enterSourceDB("gwSource5", domainID3, cfStereo, gwSourceID5); + am_sinkID_t gwSinkID5; + enterSinkDB("gwSink5", domainID3, cfAnalog, gwSinkID5); + am_sourceID_t gwSourceID3; + enterSourceDB("gwSource3", domainID3, cfAnalog, gwSourceID3); + am_sinkID_t gwSinkID3; + enterSinkDB("gwSink3", domainID3, cfAuto, gwSinkID3); + am_sourceID_t gwSourceID4; + enterSourceDB("gwSource4", domainID3, cfStereo, gwSourceID4); + am_sinkID_t gwSinkID4; + enterSinkDB("gwSink4", domainID3, cfAnalog, gwSinkID4); + am_sinkID_t sinkID; + enterSinkDB("sink1", domainID3, cfStereo, sinkID); + + std::vector<bool> matrix; + matrix.push_back(true); + am_gatewayID_t gatewayID; + enterGatewayDB("gateway1", domainID2, domainID1, cfMono, cfStereo, matrix, gwSourceID1, gwSinkID1, gatewayID); + am_gatewayID_t gatewayID22; + enterGatewayDB("gateway22", domainID3, domainID2, cfAuto, cfMono, matrix, gwSourceID22, gwSinkID22, gatewayID22); + am_gatewayID_t gatewayID21; + enterGatewayDB("gateway21", domainID3, domainID1, cfAuto, cfStereo, matrix, gwSourceID21, gwSinkID21, gatewayID21); + am_converterID_t converterID1; + enterConverterDB("converter1", domainID3, cfAnalog, cfAuto, matrix, gwSourceID3, gwSinkID3, converterID1); + am_converterID_t converterID2; + enterConverterDB("converter2", domainID3, cfStereo, cfAnalog, matrix, gwSourceID4, gwSinkID4, converterID2); + am_converterID_t converterID3; + enterConverterDB("converter3", domainID3, cfStereo, cfAnalog, matrix, gwSourceID5, gwSinkID5, converterID3); + + am::am_Source_s source; + am::am_Sink_s sink; + + pDatabaseHandler.getSinkInfoDB(sinkID, sink); + pDatabaseHandler.getSourceInfoDB(sourceID, source); + + std::vector<am_Route_s> listRoutes; + + getRoute(false, source, sink, listRoutes); + ASSERT_EQ(static_cast<uint>(4), listRoutes.size()); + + am_Route_s compareRoute1; + compareRoute1.sinkID = sinkID; + compareRoute1.sourceID = sourceID; + compareRoute1.route.push_back({sourceID, gwSinkID1, domainID1, CF_GENIVI_STEREO}); + compareRoute1.route.push_back({gwSourceID1, gwSinkID22, domainID2, CF_GENIVI_MONO}); + compareRoute1.route.push_back({gwSourceID22, gwSinkID3, domainID3, CF_GENIVI_AUTO}); + compareRoute1.route.push_back({gwSourceID3, gwSinkID4, domainID3, CF_GENIVI_ANALOG}); + compareRoute1.route.push_back({gwSourceID4, sinkID, domainID3, CF_GENIVI_STEREO}); + + am_Route_s compareRoute2; + compareRoute2.sinkID = sinkID; + compareRoute2.sourceID = sourceID; + compareRoute2.route.push_back({sourceID, gwSinkID1, domainID1, CF_GENIVI_STEREO}); + compareRoute2.route.push_back({gwSourceID1, gwSinkID22, domainID2, CF_GENIVI_MONO}); + compareRoute2.route.push_back({gwSourceID22, gwSinkID3, domainID3, CF_GENIVI_AUTO}); + compareRoute2.route.push_back({gwSourceID3, gwSinkID5, domainID3, CF_GENIVI_ANALOG}); + compareRoute2.route.push_back({gwSourceID5, sinkID, domainID3, CF_GENIVI_STEREO}); + + am_Route_s compareRoute3; + compareRoute3.sinkID = sinkID; + compareRoute3.sourceID = sourceID; + compareRoute3.route.push_back({sourceID, gwSinkID21, domainID1, CF_GENIVI_STEREO}); + compareRoute3.route.push_back({gwSourceID21, gwSinkID3, domainID3, CF_GENIVI_AUTO}); + compareRoute3.route.push_back({gwSourceID3, gwSinkID4, domainID3, CF_GENIVI_ANALOG}); + compareRoute3.route.push_back({gwSourceID4, sinkID, domainID3, CF_GENIVI_STEREO}); + + am_Route_s compareRoute4; + compareRoute4.sinkID = sinkID; + compareRoute4.sourceID = sourceID; + compareRoute4.route.push_back({sourceID, gwSinkID21, domainID1, CF_GENIVI_STEREO}); + compareRoute4.route.push_back({gwSourceID21, gwSinkID3, domainID3, CF_GENIVI_AUTO}); + compareRoute4.route.push_back({gwSourceID3, gwSinkID5, domainID3, CF_GENIVI_ANALOG}); + compareRoute4.route.push_back({gwSourceID5, sinkID, domainID3, CF_GENIVI_STEREO}); + + ASSERT_TRUE(pCF.compareRoute(compareRoute1,listRoutes[0])|| + pCF.compareRoute(compareRoute1,listRoutes[1])|| + pCF.compareRoute(compareRoute1,listRoutes[2])|| + pCF.compareRoute(compareRoute1,listRoutes[3])); + + ASSERT_TRUE(pCF.compareRoute(compareRoute2,listRoutes[0])|| + pCF.compareRoute(compareRoute2,listRoutes[1])|| + pCF.compareRoute(compareRoute2,listRoutes[2])|| + pCF.compareRoute(compareRoute2,listRoutes[3])); + + ASSERT_TRUE(pCF.compareRoute(compareRoute3,listRoutes[0])|| + pCF.compareRoute(compareRoute3,listRoutes[1])|| + pCF.compareRoute(compareRoute3,listRoutes[2])|| + pCF.compareRoute(compareRoute3,listRoutes[3])); + + ASSERT_TRUE(pCF.compareRoute(compareRoute4,listRoutes[0])|| + pCF.compareRoute(compareRoute4,listRoutes[1])|| + pCF.compareRoute(compareRoute4,listRoutes[2])|| + pCF.compareRoute(compareRoute4,listRoutes[3])); +} + +int main(int argc, char **argv) +{ + try + { + TCLAP::CmdLine* cmd(CAmCommandLineSingleton::instanciateOnce("The team of the AudioManager wishes you a nice day!",' ',DAEMONVERSION,true)); + cmd->add(enableNoDLTDebug); + } + catch (TCLAP::ArgException &e) // catch any exceptions + { std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; } + CAmCommandLineSingleton::instance()->preparse(argc,argv); + CAmDltWrapper::instance(enableNoDLTDebug.getValue())->registerApp("routing", "CAmRouterMapTest"); + logInfo("Routing Test started "); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.h b/AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.h new file mode 100644 index 0000000..65ff97b --- /dev/null +++ b/AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.h @@ -0,0 +1,108 @@ +/** + * 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, 2014 + * + * For further information see http://www.genivi.org/. + * + */ + +#ifndef MAPTEST_H_ +#define MAPTEST_H_ + +#define UNIT_TEST 1 + +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include <algorithm> +#include <string> +#include <vector> +#include <set> +#include "CAmDatabaseHandlerMap.h" +#include "CAmControlReceiver.h" +#include "CAmControlSender.h" +#include "CAmDatabaseObserver.h" +#include "CAmRoutingSender.h" +#include "CAmRouter.h" +#include "CAmSocketHandler.h" +#include "../IAmControlBackdoor.h" +#include "../IAmCommandBackdoor.h" +#include "../CAmCommonFunctions.h" +#include "../MockIAmControlSend.h" +#include "../MockIAmCommandSend.h" + + +namespace am +{ + +class CAmRouterMapTest: public ::testing::Test +{ +public: + CAmRouterMapTest(); + ~CAmRouterMapTest(); + std::vector<std::string> plistRoutingPluginDirs; + std::vector<std::string> plistCommandPluginDirs; + CAmSocketHandler pSocketHandler; + CAmControlSender pControlSender; + CAmDatabaseHandlerMap pDatabaseHandler; + CAmRouter pRouter; + CAmRoutingSender pRoutingSender; + CAmCommandSender pCommandSender; + MockIAmCommandSend pMockInterface; + MockIAmControlSend pMockControlInterface; + IAmRoutingBackdoor pRoutingInterfaceBackdoor; + IAmCommandBackdoor pCommandInterfaceBackdoor; + IAmControlBackdoor pControlInterfaceBackdoor; + CAmControlReceiver pControlReceiver; + CAmDatabaseObserver pObserver; + CAmCommonFunctions pCF; + void SetUp(); + void TearDown(); + + void createMainConnectionSetup(); + + void enterDomainDB(const std::string & domainName, am_domainID_t & domainID); + void enterSourceDB(const std::string & sourceName, const am_domainID_t domainID, const std::vector<am_CustomConnectionFormat_t> & connectionFormats, am_sourceID_t & sourceID); + void enterSinkDB(const std::string & sinkName, const am_domainID_t domainID, const std::vector<am_CustomConnectionFormat_t> & connectionFormats, am_sinkID_t & sinkID); + void enterGatewayDB(const std::string & gwName, + const am_domainID_t domainSourceID, + const am_domainID_t domainSinkID, + const std::vector<am_CustomConnectionFormat_t> & sourceConnectionFormats, + const std::vector<am_CustomConnectionFormat_t> & sinkConnectionFormats, + const std::vector<bool> & matrix, + const am_sourceID_t & sourceID, + const am_sinkID_t & sinkID, + am_gatewayID_t & gatewayID); + void enterConverterDB(const std::string & gwName, + const am_domainID_t domainID, + const std::vector<am_CustomConnectionFormat_t> & sourceConnectionFormats, + const std::vector<am_CustomConnectionFormat_t> & sinkConnectionFormats, + const std::vector<bool> & matrix, + const am_sourceID_t & sourceID, + const am_sinkID_t & sinkID, + am_converterID_t & converterID); + void getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s>& returnList); + void getRoute(const bool onlyfree, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes); + void getAllPaths(CAmRoutingNode & aSource, + CAmRoutingNode & aSink, + std::vector<am_Route_s> & resultPath, + std::vector<std::vector<CAmRoutingNode*>> & resultNodesPath, + const bool includeCycles); +}; + +} + +#endif /* MAPTEST_H_ */ diff --git a/AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt b/AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt new file mode 100644 index 0000000..17689d9 --- /dev/null +++ b/AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt @@ -0,0 +1,47 @@ +# 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 +# +# For further information see http://www.genivi.org/. +# + +cmake_minimum_required(VERSION 3.0) + +project (AmRouterMapTest LANGUAGES CXX VERSION ${DAEMONVERSION}) + +INCLUDE_DIRECTORIES( + ${AUDIOMANAGER_CORE_INCLUDE} + ${GMOCK_INCLUDE_DIRS} + ${GTEST_INCLUDE_DIRS}) + +file(GLOB ROUTINGMAP_SRCS_CXX + "../CAmCommonFunctions.cpp" + "*.cpp" + ) + +ADD_EXECUTABLE( AmRouterMapTest ${ROUTINGMAP_SRCS_CXX}) + +TARGET_LINK_LIBRARIES(AmRouterMapTest + ${GTEST_LIBRARIES} + ${GMOCK_LIBRARIES} + AudioManagerCore +) + +ADD_DEPENDENCIES(AmRouterMapTest AudioManagerCore) + +INSTALL(TARGETS AmRouterMapTest + DESTINATION ${TEST_EXECUTABLE_INSTALL_PATH} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + COMPONENT tests +) + diff --git a/AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt~ b/AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt~ new file mode 100644 index 0000000..ec79082 --- /dev/null +++ b/AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt~ @@ -0,0 +1,47 @@ +# 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 +# +# For further information see http://www.genivi.org/. +# + +cmake_minimum_required(VERSION 3.0) + +project (AmRouterMapTest LANGUAGES CXX VERSION ${DAEMONVERSION}) + +INCLUDE_DIRECTORIES( + ${AUDIOMANAGER_CORE_INCLUDE} + ${GMOCK_INCLUDE_DIR} + ${GTEST_INCLUDE_DIRS}) + +file(GLOB ROUTINGMAP_SRCS_CXX + "../CAmCommonFunctions.cpp" + "*.cpp" + ) + +ADD_EXECUTABLE( AmRouterMapTest ${ROUTINGMAP_SRCS_CXX}) + +TARGET_LINK_LIBRARIES(AmRouterMapTest + ${GTEST_LIBRARIES} + ${GMOCK_LIBRARIES} + AudioManagerCore +) + +ADD_DEPENDENCIES(AmRouterMapTest AudioManagerCore) + +INSTALL(TARGETS AmRouterMapTest + DESTINATION ${TEST_EXECUTABLE_INSTALL_PATH} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + COMPONENT tests +) + diff --git a/AudioManagerCore/test/AmRouterTest/CAmRouterTest.cpp b/AudioManagerCore/test/AmRouterTest/CAmRouterTest.cpp new file mode 100644 index 0000000..a64979e --- /dev/null +++ b/AudioManagerCore/test/AmRouterTest/CAmRouterTest.cpp @@ -0,0 +1,1967 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmRouterTest.h" +#include <string.h> +#include "CAmDltWrapper.h" +#include "CAmCommandLineSingleton.h" + +using namespace am; +using namespace testing; + +TCLAP::SwitchArg enableNoDLTDebug ("V","logDlt","print DLT logs to stdout or dlt-daemon default off",false); + +CAmRouterTest::CAmRouterTest() : + plistRoutingPluginDirs(), // + plistCommandPluginDirs(), // + pSocketHandler(), // + pControlSender(), // + pDatabaseHandler(), + pRouter(&pDatabaseHandler, &pControlSender), // + pRoutingSender(plistRoutingPluginDirs), // + pCommandSender(plistCommandPluginDirs), // + pMockInterface(), // + pMockControlInterface(), // + pRoutingInterfaceBackdoor(), // + pCommandInterfaceBackdoor(), // + pControlInterfaceBackdoor(), // + pControlReceiver(&pDatabaseHandler, &pRoutingSender, &pCommandSender,&pSocketHandler, &pRouter), // + pObserver(&pCommandSender, &pRoutingSender, &pSocketHandler) +{ + pDatabaseHandler.registerObserver(&pObserver); + pCommandInterfaceBackdoor.injectInterface(&pCommandSender, &pMockInterface); + pControlInterfaceBackdoor.replaceController(&pControlSender, &pMockControlInterface); +} + +CAmRouterTest::~CAmRouterTest() +{ + +} + +void CAmRouterTest::SetUp() +{ + logInfo("Routing Test started "); +} + +void CAmRouterTest::TearDown() +{ +} + +ACTION(returnConnectionFormat){ +arg4=arg3; +} + +//test that checks just sinks and source in a domain but connectionformats do not match +TEST_F(CAmRouterTest,simpleRoute2withDomainNoMatchFormats) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1; + am_domainID_t domainID1; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + + am_Source_s source; + am_sourceID_t sourceID; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + source.sourceID=sourceID; + + am_Sink_s sink; + am_sinkID_t sinkID; + + sink.domainID = domainID1; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + sink.sinkID=sinkID; + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + + hopp1.sinkID = sinkID; + hopp1.sourceID = sourceID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + ASSERT_EQ(E_OK, pRouter.getRoute(true,sourceID,sinkID,listRoutes)); + ASSERT_EQ(static_cast<uint>(0), listRoutes.size()); + +} + +//test that checks just sinks and source in a domain +TEST_F(CAmRouterTest,simpleRoute2withDomain) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1; + am_domainID_t domainID1; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + + am_Source_s source; + am_sourceID_t sourceID; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + + am_Sink_s sink; + am_sinkID_t sinkID; + + sink.domainID = domainID1; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + + hopp1.sinkID = sinkID; + hopp1.sourceID = sourceID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + ASSERT_EQ(E_OK, pRouter.getRoute(true,sourceID,sinkID,listRoutes)); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); + +} + +//test that checks just 2 domains, one sink one source with only one connection format each +TEST_F(CAmRouterTest,simpleRoute2DomainsOnlyFree) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2; + am_domainID_t domainID1, domainID2; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + + am_Source_s source, gwSource; + am_sourceID_t sourceID, gwSourceID; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + + am_Sink_s sink, gwSink; + am_sinkID_t sinkID, gwSinkID; + + sink.domainID = domainID2; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + + am_Gateway_s gateway; + am_gatewayID_t gatewayID; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + + hopp1.sinkID = gwSinkID; + hopp1.sourceID = sourceID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sinkID = sinkID; + hopp2.sourceID = gwSourceID; + hopp2.domainID = domainID2; + hopp2.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + std::vector<am_Connection_s> listConnections; + pDatabaseHandler.getListConnections(listConnections); + ASSERT_EQ(0, listConnections.size()); + ASSERT_EQ(E_OK, pRouter.getRoute(true,sourceID,sinkID,listRoutes)); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); + +} + +//test that checks just 2 domains, one sink one source with only one connection format each +TEST_F(CAmRouterTest,simpleRoute2DomainsOnlyFreeNotFree) +{ + + + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2; + am_domainID_t domainID1, domainID2; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + + am_Source_s source, gwSource; + am_sourceID_t sourceID, gwSourceID; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + + am_Sink_s sink, gwSink; + am_sinkID_t sinkID, gwSinkID; + + sink.domainID = domainID2; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + + am_Gateway_s gateway; + am_gatewayID_t gatewayID; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + + hopp1.sinkID = gwSinkID; + hopp1.sourceID = sourceID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sinkID = sinkID; + hopp2.sourceID = gwSourceID; + hopp2.domainID = domainID2; + hopp2.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + am_Connection_s connection,connection1; + am_connectionID_t id1,id2; + connection.sourceID=sourceID; + connection.sinkID=gwSinkID; + connection.connectionFormat=CF_GENIVI_ANALOG; + connection.connectionID=0; + connection1.sourceID=gwSourceID; + connection1.sinkID=sinkID; + connection1.connectionFormat=CF_GENIVI_ANALOG; + connection1.connectionID=0; + + ASSERT_EQ(E_OK,pDatabaseHandler.enterConnectionDB(connection,id1)); + ASSERT_EQ(E_OK,pDatabaseHandler.enterConnectionDB(connection1,id2)); + + ASSERT_EQ(E_OK, pRouter.getRoute(true,sourceID,sinkID,listRoutes)); + ASSERT_EQ(static_cast<uint>(0), listRoutes.size()); + + ASSERT_EQ(E_OK, pRouter.getRoute(false,sourceID,sinkID,listRoutes)); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + +//test that checks just 2 domains, with gateway for each direction (possible circular route) +TEST_F(CAmRouterTest,simpleRoute2DomainsCircularGWOnlyFree) +{ + + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2; + am_domainID_t domainID1, domainID2; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + + am_Source_s source, gwSource, gwSource2; + am_sourceID_t sourceID, gwSourceID, gwSourceID2; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource2.domainID = domainID1; + gwSource2.name = "gwsource2"; + gwSource2.sourceState = SS_ON; + gwSource2.sourceID = 0; + gwSource2.sourceClassID = 5; + gwSource2.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource2,gwSourceID2)); + + am_Sink_s sink, gwSink, gwSink2; + am_sinkID_t sinkID, gwSinkID, gwSinkID2; + + sink.domainID = domainID2; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSink2.domainID = domainID2; + gwSink2.name = "gwSink2"; + gwSink2.sinkID = 0; + gwSink2.sinkClassID = 5; + gwSink2.muteState = MS_MUTED; + gwSink2.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink2,gwSinkID2)); + + am_Gateway_s gateway, gateway2; + am_gatewayID_t gatewayID, gatewayID2; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + gateway2.controlDomainID = domainID1; + gateway2.gatewayID = 0; + gateway2.sinkID = gwSinkID2; + gateway2.sourceID = gwSourceID2; + gateway2.domainSourceID = domainID1; + gateway2.domainSinkID = domainID2; + gateway2.listSinkFormats = gwSink2.listConnectionFormats; + gateway2.listSourceFormats = gwSource2.listConnectionFormats; + gateway2.convertionMatrix.push_back(true); + gateway2.name = "gateway2"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway2,gatewayID2)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + + hopp1.sinkID = gwSinkID; + hopp1.sourceID = sourceID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sinkID = sinkID; + hopp2.sourceID = gwSourceID; + hopp2.domainID = domainID2; + hopp2.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + ASSERT_EQ(E_OK, pRouter.getRoute(true,sourceID,sinkID,listRoutes)); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + +//test that checks 3 domains, one sink one source, longer lists of connectionformats. +TEST_F(CAmRouterTest,simpleRoute3DomainsListConnectionFormats_2) +{ + + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2, domain3; + am_domainID_t domainID1, domainID2, domainID3; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + domain3.domainID = 0; + domain3.name = "domain3"; + domain3.busname = "domain3bus"; + domain3.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain3,domainID3)); + + am_Source_s source, gwSource, gwSource1; + am_sourceID_t sourceID, gwSourceID, gwSourceID1; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_STEREO); + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_MONO); + gwSource.listConnectionFormats.push_back(CF_GENIVI_STEREO); + gwSource.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource1.domainID = domainID3; + gwSource1.name = "gwsource2"; + gwSource1.sourceState = SS_ON; + gwSource1.sourceID = 0; + gwSource1.sourceClassID = 5; + gwSource1.listConnectionFormats.push_back(CF_GENIVI_STEREO); + gwSource1.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource1,gwSourceID1)); + + am_Sink_s sink, gwSink, gwSink1; + am_sinkID_t sinkID, gwSinkID, gwSinkID1; + + sink.domainID = domainID3; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_STEREO); + gwSink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink1.domainID = domainID2; + gwSink1.name = "gwSink1"; + gwSink1.sinkID = 0; + gwSink1.sinkClassID = 5; + gwSink1.muteState = MS_MUTED; + gwSink1.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + gwSink1.listConnectionFormats.push_back(CF_GENIVI_STEREO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink1,gwSinkID1)); + + am_Gateway_s gateway, gateway1; + am_gatewayID_t gatewayID, gatewayID1; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(true); + gateway.convertionMatrix.push_back(true); + gateway.convertionMatrix.push_back(false); + gateway.name = "gateway"; + + gateway1.controlDomainID = domainID2; + gateway1.gatewayID = 0; + gateway1.sinkID = gwSinkID1; + gateway1.sourceID = gwSourceID1; + gateway1.domainSourceID = domainID3; + gateway1.domainSinkID = domainID2; + gateway1.listSinkFormats = gwSink1.listConnectionFormats; + gateway1.listSourceFormats = gwSource1.listConnectionFormats; + gateway1.convertionMatrix.push_back(false); + gateway1.convertionMatrix.push_back(false); + gateway1.convertionMatrix.push_back(false); + gateway1.convertionMatrix.push_back(true); + gateway1.name = "gateway1"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + am_RoutingElement_s hopp3; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[1]; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = gwSinkID1; + hopp2.domainID = domainID2; + hopp2.connectionFormat = gwSink1.listConnectionFormats[1]; + + hopp3.sourceID = gwSourceID1; + hopp3.sinkID = sinkID; + hopp3.domainID = domainID3; + hopp3.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + listRoutingElements.push_back(hopp3); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + ASSERT_EQ(E_OK, pRouter.getRoute(false,sourceID,sinkID,listRoutes)); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + +//test that checks 3 domains, one sink one source, longer lists of connectionformats. +TEST_F(CAmRouterTest,simpleRoute3DomainsListConnectionFormats_1) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2, domain3; + am_domainID_t domainID1, domainID2, domainID3; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + domain3.domainID = 0; + domain3.name = "domain3"; + domain3.busname = "domain3bus"; + domain3.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain3,domainID3)); + + am_Source_s source, gwSource, gwSource1; + am_sourceID_t sourceID, gwSourceID, gwSourceID1; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_STEREO); + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_STEREO); + gwSource.listConnectionFormats.push_back(CF_GENIVI_MONO); + gwSource.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource1.domainID = domainID3; + gwSource1.name = "gwsource2"; + gwSource1.sourceState = SS_ON; + gwSource1.sourceID = 0; + gwSource1.sourceClassID = 5; + gwSource1.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource1,gwSourceID1)); + + am_Sink_s sink, gwSink, gwSink1; + am_sinkID_t sinkID, gwSinkID, gwSinkID1; + + sink.domainID = domainID3; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_STEREO); + gwSink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink1.domainID = domainID2; + gwSink1.name = "gwSink1"; + gwSink1.sinkID = 0; + gwSink1.sinkClassID = 5; + gwSink1.muteState = MS_MUTED; + gwSink1.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink1,gwSinkID1)); + + am_Gateway_s gateway, gateway1; + am_gatewayID_t gatewayID, gatewayID1; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(true); + gateway.convertionMatrix.push_back(false); + gateway.name = "gateway"; + + gateway1.controlDomainID = domainID2; + gateway1.gatewayID = 0; + gateway1.sinkID = gwSinkID1; + gateway1.sourceID = gwSourceID1; + gateway1.domainSourceID = domainID3; + gateway1.domainSinkID = domainID2; + gateway1.listSinkFormats = gwSink1.listConnectionFormats; + gateway1.listSourceFormats = gwSource1.listConnectionFormats; + gateway1.convertionMatrix.push_back(true); + gateway1.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + am_RoutingElement_s hopp3; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = gwSinkID1; + hopp2.domainID = domainID2; + hopp2.connectionFormat = gwSink1.listConnectionFormats[0]; + + hopp3.sourceID = gwSourceID1; + hopp3.sinkID = sinkID; + hopp3.domainID = domainID3; + hopp3.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + listRoutingElements.push_back(hopp3); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + ASSERT_EQ(E_OK, pRouter.getRoute(false,sourceID,sinkID,listRoutes)); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + + +//test that checks 3 domains, one sink one source, longer lists of connectionformats. +TEST_F(CAmRouterTest,simpleRoute3DomainsListConnectionFormats) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2, domain3; + am_domainID_t domainID1, domainID2, domainID3; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + domain3.domainID = 0; + domain3.name = "domain3"; + domain3.busname = "domain3bus"; + domain3.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain3,domainID3)); + + am_Source_s source, gwSource, gwSource1; + am_sourceID_t sourceID, gwSourceID, gwSourceID1; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_STEREO); + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource1.domainID = domainID3; + gwSource1.name = "gwsource2"; + gwSource1.sourceState = SS_ON; + gwSource1.sourceID = 0; + gwSource1.sourceClassID = 5; + gwSource1.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource1,gwSourceID1)); + + am_Sink_s sink, gwSink, gwSink1; + am_sinkID_t sinkID, gwSinkID, gwSinkID1; + + sink.domainID = domainID3; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_STEREO); + gwSink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink1.domainID = domainID2; + gwSink1.name = "gwSink1"; + gwSink1.sinkID = 0; + gwSink1.sinkClassID = 5; + gwSink1.muteState = MS_MUTED; + gwSink1.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink1,gwSinkID1)); + + am_Gateway_s gateway, gateway1; + am_gatewayID_t gatewayID, gatewayID1; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(false); + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + gateway1.controlDomainID = domainID2; + gateway1.gatewayID = 0; + gateway1.sinkID = gwSinkID1; + gateway1.sourceID = gwSourceID1; + gateway1.domainSourceID = domainID3; + gateway1.domainSinkID = domainID2; + gateway1.listSinkFormats = gwSink1.listConnectionFormats; + gateway1.listSourceFormats = gwSource1.listConnectionFormats; + gateway1.convertionMatrix.push_back(true); + gateway1.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + am_RoutingElement_s hopp3; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[1]; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = gwSinkID1; + hopp2.domainID = domainID2; + hopp2.connectionFormat = gwSink1.listConnectionFormats[0]; + + hopp3.sourceID = gwSourceID1; + hopp3.sinkID = sinkID; + hopp3.domainID = domainID3; + hopp3.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + listRoutingElements.push_back(hopp3); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + ASSERT_EQ(E_OK, pRouter.getRoute(false,sourceID,sinkID,listRoutes)); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + + +//test that checks 4 domains, one sink and one source but there are 2 routes because there are 2 gateways +TEST_F(CAmRouterTest,simpleRoute4Domains2Routes) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2, domain3, domain4; + am_domainID_t domainID1, domainID2, domainID3, domainID4; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + domain3.domainID = 0; + domain3.name = "domain3"; + domain3.busname = "domain3bus"; + domain3.state = DS_CONTROLLED; + domain4.domainID = 0; + domain4.name = "domain4"; + domain4.busname = "domain4bus"; + domain4.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain3,domainID3)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain4,domainID4)); + + am_Source_s source, gwSource, gwSource1, gwSource2, gwSource3; + am_sourceID_t sourceID, gwSourceID, gwSourceID1, gwSourceID2, gwSourceID3; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource1.domainID = domainID3; + gwSource1.name = "gwsource2"; + gwSource1.sourceState = SS_ON; + gwSource1.sourceID = 0; + gwSource1.sourceClassID = 5; + gwSource1.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource2.domainID = domainID4; + gwSource2.name = "gwsource3"; + gwSource2.sourceState = SS_OFF; + gwSource2.sourceID = 0; + gwSource2.sourceClassID = 5; + gwSource2.listConnectionFormats.push_back(CF_GENIVI_STEREO); + + gwSource3.domainID = domainID3; + gwSource3.name = "gwsource4"; + gwSource3.sourceState = SS_OFF; + gwSource3.sourceID = 0; + gwSource3.sourceClassID = 5; + gwSource3.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource1,gwSourceID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource2,gwSourceID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource3,gwSourceID3)); + + am_Sink_s sink, gwSink, gwSink1, gwSink2, gwSink3; + am_sinkID_t sinkID, gwSinkID, gwSinkID1, gwSinkID2, gwSinkID3; + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink1.domainID = domainID2; + gwSink1.name = "gwSink1"; + gwSink1.sinkID = 0; + gwSink1.sinkClassID = 5; + gwSink1.muteState = MS_MUTED; + gwSink1.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSink2.domainID = domainID3; + gwSink2.name = "gwSink2"; + gwSink2.sinkID = 0; + gwSink2.sinkClassID = 5; + gwSink2.muteState = MS_MUTED; + gwSink2.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink3.domainID = domainID2; + gwSink3.name = "gwSink3"; + gwSink3.sinkID = 0; + gwSink3.sinkClassID = 5; + gwSink3.muteState = MS_MUTED; + gwSink3.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + sink.domainID = domainID4; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_STEREO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink1,gwSinkID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink2,gwSinkID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink3,gwSinkID3)); + + am_Gateway_s gateway, gateway1, gateway2, gateway3; + am_gatewayID_t gatewayID, gatewayID1, gatewayID2, gatewayID3; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + gateway1.controlDomainID = domainID2; + gateway1.gatewayID = 0; + gateway1.sinkID = gwSinkID1; + gateway1.sourceID = gwSourceID1; + gateway1.domainSourceID = domainID3; + gateway1.domainSinkID = domainID2; + gateway1.listSinkFormats = gwSink1.listConnectionFormats; + gateway1.listSourceFormats = gwSource1.listConnectionFormats; + gateway1.convertionMatrix.push_back(true); + gateway1.name = "gateway1"; + + gateway2.controlDomainID = domainID3; + gateway2.gatewayID = 0; + gateway2.sinkID = gwSinkID2; + gateway2.sourceID = gwSourceID2; + gateway2.domainSourceID = domainID4; + gateway2.domainSinkID = domainID3; + gateway2.listSinkFormats = gwSink2.listConnectionFormats; + gateway2.listSourceFormats = gwSource2.listConnectionFormats; + gateway2.convertionMatrix.push_back(true); + gateway2.name = "gateway2"; + + gateway3.controlDomainID = domainID2; + gateway3.gatewayID = 0; + gateway3.sinkID = gwSinkID3; + gateway3.sourceID = gwSourceID3; + gateway3.domainSourceID = domainID3; + gateway3.domainSinkID = domainID2; + gateway3.listSinkFormats = gwSink3.listConnectionFormats; + gateway3.listSourceFormats = gwSource3.listConnectionFormats; + gateway3.convertionMatrix.push_back(true); + gateway3.name = "gateway3"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway2,gatewayID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway3,gatewayID3)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements, listRoutingElements1; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + am_RoutingElement_s hopp3; + am_RoutingElement_s hopp4; + am_RoutingElement_s hopp2alt; + am_RoutingElement_s hopp3alt; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = gwSinkID1; + hopp2.domainID = domainID2; + hopp2.connectionFormat = gwSink1.listConnectionFormats[0]; + + hopp3.sourceID = gwSourceID1; + hopp3.sinkID = gwSinkID2; + hopp3.domainID = domainID3; + hopp3.connectionFormat = gwSink2.listConnectionFormats[0]; + + hopp4.sourceID = gwSourceID2; + hopp4.sinkID = sinkID; + hopp4.domainID = domainID4; + hopp4.connectionFormat = sink.listConnectionFormats[0]; + + hopp2alt.sourceID = gwSourceID; + hopp2alt.sinkID = gwSinkID3; + hopp2alt.domainID = domainID2; + hopp2alt.connectionFormat = gwSink3.listConnectionFormats[0]; + + hopp3alt.sourceID = gwSourceID3; + hopp3alt.sinkID = gwSinkID2; + hopp3alt.domainID = domainID3; + hopp3alt.connectionFormat = gwSink2.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + listRoutingElements.push_back(hopp3); + listRoutingElements.push_back(hopp4); + listRoutingElements1.push_back(hopp1); + listRoutingElements1.push_back(hopp2alt); + listRoutingElements1.push_back(hopp3alt); + listRoutingElements1.push_back(hopp4); + + am_Route_s compareRoute, compareRoute1; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + compareRoute1.route = listRoutingElements1; + compareRoute1.sinkID = sinkID; + compareRoute1.sourceID = sourceID; + + ASSERT_EQ(E_OK, pRouter.getRoute(false,sourceID,sinkID,listRoutes)); + ASSERT_EQ(static_cast<uint>(2), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0]) || pCF.compareRoute(compareRoute,listRoutes[1]) ); + ASSERT_TRUE(pCF.compareRoute(compareRoute1,listRoutes[1]) || pCF.compareRoute(compareRoute1,listRoutes[0]) ); +} + +//test that checks 3 domains, one sink one source but the connectionformat of third domains do not fit. +TEST_F(CAmRouterTest,simpleRoute3DomainsNoConnection) +{ + + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2, domain3; + am_domainID_t domainID1, domainID2, domainID3; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + domain3.domainID = 0; + domain3.name = "domain3"; + domain3.busname = "domain3bus"; + domain3.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain3,domainID3)); + + am_Source_s source, gwSource, gwSource1; + am_sourceID_t sourceID, gwSourceID, gwSourceID1; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource1.domainID = domainID3; + gwSource1.name = "gwsource2"; + gwSource1.sourceState = SS_ON; + gwSource1.sourceID = 0; + gwSource1.sourceClassID = 5; + gwSource1.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource1,gwSourceID1)); + + am_Sink_s sink, gwSink, gwSink1; + am_sinkID_t sinkID, gwSinkID, gwSinkID1; + + sink.domainID = domainID3; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_STEREO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink1.domainID = domainID2; + gwSink1.name = "gwSink1"; + gwSink1.sinkID = 0; + gwSink1.sinkClassID = 5; + gwSink1.muteState = MS_MUTED; + gwSink1.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink1,gwSinkID1)); + + am_Gateway_s gateway, gateway1; + am_gatewayID_t gatewayID, gatewayID1; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + gateway1.controlDomainID = domainID2; + gateway1.gatewayID = 0; + gateway1.sinkID = gwSinkID1; + gateway1.sourceID = gwSourceID1; + gateway1.domainSourceID = domainID3; + gateway1.domainSinkID = domainID2; + gateway1.listSinkFormats = gwSink1.listConnectionFormats; + gateway1.listSourceFormats = gwSource1.listConnectionFormats; + gateway1.convertionMatrix.push_back(true); + gateway1.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + am_RoutingElement_s hopp3; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = gwSinkID1; + hopp2.domainID = domainID2; + hopp2.connectionFormat = gwSink1.listConnectionFormats[0]; + + hopp3.sourceID = gwSourceID1; + hopp3.sinkID = sinkID; + hopp3.domainID = domainID3; + hopp3.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + listRoutingElements.push_back(hopp3); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + ASSERT_EQ(E_OK, pRouter.getRoute(false,sourceID,sinkID,listRoutes)); + ASSERT_EQ(static_cast<uint>(0), listRoutes.size()); +} +//test that checks just 2 domains, one sink one source with only one connection format each +TEST_F(CAmRouterTest,simpleRoute2Domains) +{ + + + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2; + am_domainID_t domainID1, domainID2; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + + am_Source_s source, gwSource; + am_sourceID_t sourceID, gwSourceID; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + + am_Sink_s sink, gwSink; + am_sinkID_t sinkID, gwSinkID; + + sink.domainID = domainID2; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + + am_Gateway_s gateway; + am_gatewayID_t gatewayID; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + + hopp1.sinkID = gwSinkID; + hopp1.sourceID = sourceID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sinkID = sinkID; + hopp2.sourceID = gwSourceID; + hopp2.domainID = domainID2; + hopp2.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + ASSERT_EQ(E_OK, pRouter.getRoute(false,sourceID,sinkID,listRoutes)); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); + +} + +//test that checks just 2 domains, one sink one source but the connectionformat of source +TEST_F(CAmRouterTest,simpleRoute2DomainsNoMatchConnectionFormats) +{ + + + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2; + am_domainID_t domainID1, domainID2; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + + am_Source_s source, gwSource; + am_sourceID_t sourceID, gwSourceID; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_STEREO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + + am_Sink_s sink, gwSink; + am_sinkID_t sinkID, gwSinkID; + + sink.domainID = domainID2; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + + am_Gateway_s gateway; + am_gatewayID_t gatewayID; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + + hopp1.sinkID = gwSinkID; + hopp1.sourceID = sourceID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sinkID = sinkID; + hopp2.sourceID = gwSourceID; + hopp2.domainID = domainID2; + hopp2.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + ASSERT_EQ(E_OK, pRouter.getRoute(false,sourceID,sinkID,listRoutes)); + ASSERT_EQ(static_cast<uint>(0), listRoutes.size()); +} + +//test that checks 3 domains, one sink one source. +TEST_F(CAmRouterTest,simpleRoute3Domains) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2, domain3; + am_domainID_t domainID1, domainID2, domainID3; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + domain3.domainID = 0; + domain3.name = "domain3"; + domain3.busname = "domain3bus"; + domain3.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain3,domainID3)); + + am_Source_s source, gwSource, gwSource1; + am_sourceID_t sourceID, gwSourceID, gwSourceID1; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource1.domainID = domainID3; + gwSource1.name = "gwsource2"; + gwSource1.sourceState = SS_ON; + gwSource1.sourceID = 0; + gwSource1.sourceClassID = 5; + gwSource1.listConnectionFormats.push_back(CF_GENIVI_MONO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource1,gwSourceID1)); + + am_Sink_s sink, gwSink, gwSink1; + am_sinkID_t sinkID, gwSinkID, gwSinkID1; + + sink.domainID = domainID3; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink1.domainID = domainID2; + gwSink1.name = "gwSink1"; + gwSink1.sinkID = 0; + gwSink1.sinkClassID = 5; + gwSink1.muteState = MS_MUTED; + gwSink1.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink1,gwSinkID1)); + + am_Gateway_s gateway, gateway1; + am_gatewayID_t gatewayID, gatewayID1; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + gateway1.controlDomainID = domainID2; + gateway1.gatewayID = 0; + gateway1.sinkID = gwSinkID1; + gateway1.sourceID = gwSourceID1; + gateway1.domainSourceID = domainID3; + gateway1.domainSinkID = domainID2; + gateway1.listSinkFormats = gwSink1.listConnectionFormats; + gateway1.listSourceFormats = gwSource1.listConnectionFormats; + gateway1.convertionMatrix.push_back(true); + gateway1.name = "gateway"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + am_RoutingElement_s hopp3; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = gwSinkID1; + hopp2.domainID = domainID2; + hopp2.connectionFormat = gwSink1.listConnectionFormats[0]; + + hopp3.sourceID = gwSourceID1; + hopp3.sinkID = sinkID; + hopp3.domainID = domainID3; + hopp3.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + listRoutingElements.push_back(hopp3); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + ASSERT_EQ(E_OK, pRouter.getRoute(false,sourceID,sinkID,listRoutes)); + ASSERT_EQ(static_cast<uint>(1), listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + +//test that checks 4 domains, one sink and one source. +TEST_F(CAmRouterTest,simpleRoute4Domains) +{ + EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK))); + + //initialize 2 domains + am_Domain_s domain1, domain2, domain3, domain4; + am_domainID_t domainID1, domainID2, domainID3, domainID4; + + domain1.domainID = 0; + domain1.name = "domain1"; + domain1.busname = "domain1bus"; + domain1.state = DS_CONTROLLED; + domain2.domainID = 0; + domain2.name = "domain2"; + domain2.busname = "domain2bus"; + domain2.state = DS_CONTROLLED; + domain3.domainID = 0; + domain3.name = "domain3"; + domain3.busname = "domain3bus"; + domain3.state = DS_CONTROLLED; + domain4.domainID = 0; + domain4.name = "domain4"; + domain4.busname = "domain4bus"; + domain4.state = DS_CONTROLLED; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain1,domainID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain2,domainID2)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain3,domainID3)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain4,domainID4)); + + am_Source_s source, gwSource, gwSource1, gwSource2; + am_sourceID_t sourceID, gwSourceID, gwSourceID1, gwSourceID2; + + source.domainID = domainID1; + source.name = "source1"; + source.sourceState = SS_ON; + source.sourceID = 0; + source.sourceClassID = 5; + source.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource.domainID = domainID2; + gwSource.name = "gwsource1"; + gwSource.sourceState = SS_ON; + gwSource.sourceID = 0; + gwSource.sourceClassID = 5; + gwSource.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSource1.domainID = domainID3; + gwSource1.name = "gwsource2"; + gwSource1.sourceState = SS_ON; + gwSource1.sourceID = 0; + gwSource1.sourceClassID = 5; + gwSource1.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSource2.domainID = domainID4; + gwSource2.name = "gwsource3"; + gwSource2.sourceState = SS_OFF; + gwSource2.sourceID = 0; + gwSource2.sourceClassID = 5; + gwSource2.listConnectionFormats.push_back(CF_GENIVI_STEREO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource,gwSourceID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource1,gwSourceID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(gwSource2,gwSourceID2)); + + am_Sink_s sink, gwSink, gwSink1, gwSink2; + am_sinkID_t sinkID, gwSinkID, gwSinkID1, gwSinkID2; + + gwSink.domainID = domainID1; + gwSink.name = "gwSink"; + gwSink.sinkID = 0; + gwSink.sinkClassID = 5; + gwSink.muteState = MS_MUTED; + gwSink.listConnectionFormats.push_back(CF_GENIVI_MONO); + + gwSink1.domainID = domainID2; + gwSink1.name = "gwSink1"; + gwSink1.sinkID = 0; + gwSink1.sinkClassID = 5; + gwSink1.muteState = MS_MUTED; + gwSink1.listConnectionFormats.push_back(CF_GENIVI_ANALOG); + + gwSink2.domainID = domainID3; + gwSink2.name = "gwSink2"; + gwSink2.sinkID = 0; + gwSink2.sinkClassID = 5; + gwSink2.muteState = MS_MUTED; + gwSink2.listConnectionFormats.push_back(CF_GENIVI_MONO); + + sink.domainID = domainID4; + sink.name = "sink1"; + sink.sinkID = 0; + sink.sinkClassID = 5; + sink.muteState = MS_MUTED; + sink.listConnectionFormats.push_back(CF_GENIVI_STEREO); + + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink,gwSinkID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink1,gwSinkID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(gwSink2,gwSinkID2)); + + am_Gateway_s gateway, gateway1, gateway2; + am_gatewayID_t gatewayID, gatewayID1, gatewayID2; + + gateway.controlDomainID = domainID1; + gateway.gatewayID = 0; + gateway.sinkID = gwSinkID; + gateway.sourceID = gwSourceID; + gateway.domainSourceID = domainID2; + gateway.domainSinkID = domainID1; + gateway.listSinkFormats = gwSink.listConnectionFormats; + gateway.listSourceFormats = gwSource.listConnectionFormats; + gateway.convertionMatrix.push_back(true); + gateway.name = "gateway"; + + gateway1.controlDomainID = domainID2; + gateway1.gatewayID = 0; + gateway1.sinkID = gwSinkID1; + gateway1.sourceID = gwSourceID1; + gateway1.domainSourceID = domainID3; + gateway1.domainSinkID = domainID2; + gateway1.listSinkFormats = gwSink1.listConnectionFormats; + gateway1.listSourceFormats = gwSource1.listConnectionFormats; + gateway1.convertionMatrix.push_back(true); + gateway1.name = "gateway1"; + + gateway2.controlDomainID = domainID3; + gateway2.gatewayID = 0; + gateway2.sinkID = gwSinkID2; + gateway2.sourceID = gwSourceID2; + gateway2.domainSourceID = domainID4; + gateway2.domainSinkID = domainID3; + gateway2.listSinkFormats = gwSink2.listConnectionFormats; + gateway2.listSourceFormats = gwSource2.listConnectionFormats; + gateway2.convertionMatrix.push_back(true); + gateway2.name = "gateway2"; + + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway,gatewayID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway1,gatewayID1)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterGatewayDB(gateway2,gatewayID2)); + + std::vector<am_Route_s> listRoutes; + std::vector<am_RoutingElement_s> listRoutingElements; + am_RoutingElement_s hopp1; + am_RoutingElement_s hopp2; + am_RoutingElement_s hopp3; + am_RoutingElement_s hopp4; + + hopp1.sourceID = sourceID; + hopp1.sinkID = gwSinkID; + hopp1.domainID = domainID1; + hopp1.connectionFormat = source.listConnectionFormats[0]; + + hopp2.sourceID = gwSourceID; + hopp2.sinkID = gwSinkID1; + hopp2.domainID = domainID2; + hopp2.connectionFormat = gwSink1.listConnectionFormats[0]; + + hopp3.sourceID = gwSourceID1; + hopp3.sinkID = gwSinkID2; + hopp3.domainID = domainID3; + hopp3.connectionFormat = gwSink2.listConnectionFormats[0]; + + hopp4.sourceID = gwSourceID2; + hopp4.sinkID = sinkID; + hopp4.domainID = domainID4; + hopp4.connectionFormat = sink.listConnectionFormats[0]; + + listRoutingElements.push_back(hopp1); + listRoutingElements.push_back(hopp2); + listRoutingElements.push_back(hopp3); + listRoutingElements.push_back(hopp4); + + am_Route_s compareRoute; + compareRoute.route = listRoutingElements; + compareRoute.sinkID = sinkID; + compareRoute.sourceID = sourceID; + + ASSERT_EQ(E_OK, pRouter.getRoute(false,sourceID,sinkID,listRoutes)); + size_t size(1); + ASSERT_EQ(size, listRoutes.size()); + ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0])); +} + +int main(int argc, char **argv) +{ + try + { + TCLAP::CmdLine* cmd(CAmCommandLineSingleton::instanciateOnce("The team of the AudioManager wishes you a nice day!",' ',DAEMONVERSION,true)); + cmd->add(enableNoDLTDebug); + } + catch (TCLAP::ArgException &e) // catch any exceptions + { std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; } + CAmCommandLineSingleton::instance()->preparse(argc,argv); + CAmDltWrapper::instance(enableNoDLTDebug.getValue())->registerApp("routing", "CAmRouterTest"); + logInfo("Routing Test started "); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/AudioManagerCore/test/AmRouterTest/CAmRouterTest.h b/AudioManagerCore/test/AmRouterTest/CAmRouterTest.h new file mode 100644 index 0000000..4a4e35b --- /dev/null +++ b/AudioManagerCore/test/AmRouterTest/CAmRouterTest.h @@ -0,0 +1,81 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#ifndef DATABASETEST_H_ +#define DATABASETEST_H_ + +#define UNIT_TEST 1 + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include <algorithm> +#include <string> +#include <vector> +#include <set> +#include "CAmDatabaseHandlerMap.h" +#include "CAmControlReceiver.h" +#include "CAmControlSender.h" +#include "CAmDatabaseObserver.h" +#include "CAmRoutingSender.h" +#include "CAmRouter.h" +#include "CAmSocketHandler.h" +#include "../IAmControlBackdoor.h" +#include "../IAmCommandBackdoor.h" +#include "../CAmCommonFunctions.h" +#include "../MockIAmControlSend.h" +#include "../MockIAmCommandSend.h" + + +namespace am +{ + +class CAmRouterTest: public ::testing::Test +{ +public: + CAmRouterTest(); + ~CAmRouterTest(); + std::vector<std::string> plistRoutingPluginDirs; + std::vector<std::string> plistCommandPluginDirs; + CAmSocketHandler pSocketHandler; + CAmControlSender pControlSender; + CAmDatabaseHandlerMap pDatabaseHandler; + CAmRouter pRouter; + CAmRoutingSender pRoutingSender; + CAmCommandSender pCommandSender; + MockIAmCommandSend pMockInterface; + MockIAmControlSend pMockControlInterface; + IAmRoutingBackdoor pRoutingInterfaceBackdoor; + IAmCommandBackdoor pCommandInterfaceBackdoor; + IAmControlBackdoor pControlInterfaceBackdoor; + CAmControlReceiver pControlReceiver; + CAmDatabaseObserver pObserver; + CAmCommonFunctions pCF; + void SetUp(); + void TearDown(); + + void createMainConnectionSetup(); +}; + +} + +#endif /* DATABASETEST_H_ */ diff --git a/AudioManagerCore/test/AmRouterTest/CMakeLists.txt b/AudioManagerCore/test/AmRouterTest/CMakeLists.txt new file mode 100644 index 0000000..db05911 --- /dev/null +++ b/AudioManagerCore/test/AmRouterTest/CMakeLists.txt @@ -0,0 +1,48 @@ +# 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 +# +# For further information see http://www.genivi.org/. +# + +cmake_minimum_required(VERSION 3.0) + +project(AmRouterTest LANGUAGES CXX VERSION ${DAEMONVERSION}) + +INCLUDE_DIRECTORIES( + ${AUDIOMANAGER_CORE_INCLUDE} + ${GMOCK_INCLUDE_DIRS} + ${GTEST_INCLUDE_DIRS}) + + +file(GLOB ROUTING_SRCS_CXX + "../CAmCommonFunctions.cpp" + "*.cpp" + ) + +ADD_EXECUTABLE( AmRouterTest ${ROUTING_SRCS_CXX}) + +TARGET_LINK_LIBRARIES(AmRouterTest + ${GTEST_LIBRARIES} + ${GMOCK_LIBRARIES} + AudioManagerCore +) + +ADD_DEPENDENCIES(AmRouterTest AudioManagerCore) + +INSTALL(TARGETS AmRouterTest + DESTINATION ${TEST_EXECUTABLE_INSTALL_PATH} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + COMPONENT tests +) + diff --git a/AudioManagerCore/test/AmRouterTest/CMakeLists.txt~ b/AudioManagerCore/test/AmRouterTest/CMakeLists.txt~ new file mode 100644 index 0000000..32e1206 --- /dev/null +++ b/AudioManagerCore/test/AmRouterTest/CMakeLists.txt~ @@ -0,0 +1,47 @@ +# 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 +# +# For further information see http://www.genivi.org/. +# + +cmake_minimum_required(VERSION 3.0) + +project(AmRouterTest LANGUAGES CXX VERSION ${DAEMONVERSION}) + +INCLUDE_DIRECTORIES( + ${AUDIOMANAGER_CORE_INCLUDE} + ${GMOCK_INCLUDE_DIR}) + + +file(GLOB ROUTING_SRCS_CXX + "../CAmCommonFunctions.cpp" + "*.cpp" + ) + +ADD_EXECUTABLE( AmRouterTest ${ROUTING_SRCS_CXX}) + +TARGET_LINK_LIBRARIES(AmRouterTest + ${GTEST_LIBRARIES} + ${GMOCK_LIBRARIES} + AudioManagerCore +) + +ADD_DEPENDENCIES(AmRouterTest AudioManagerCore) + +INSTALL(TARGETS AmRouterTest + DESTINATION ${TEST_EXECUTABLE_INSTALL_PATH} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + COMPONENT tests +) + diff --git a/AudioManagerCore/test/AmRoutingInterfaceTest/CAmRoutingInterfaceTest.cpp b/AudioManagerCore/test/AmRoutingInterfaceTest/CAmRoutingInterfaceTest.cpp new file mode 100644 index 0000000..5978b6d --- /dev/null +++ b/AudioManagerCore/test/AmRoutingInterfaceTest/CAmRoutingInterfaceTest.cpp @@ -0,0 +1,383 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmRoutingInterfaceTest.h" +#include "CAmDltWrapper.h" +#include "CAmCommandLineSingleton.h" + +using namespace am; +using namespace testing; + +TCLAP::SwitchArg enableNoDLTDebug ("V","logDlt","print DLT logs to stdout or dlt-daemon default off",false); + +CAmRoutingInterfaceTest::CAmRoutingInterfaceTest() : + plistRoutingPluginDirs(), // + plistCommandPluginDirs(), // + pSocketHandler(), // + pDatabaseHandler(), // + pRoutingSender(plistRoutingPluginDirs), // + pCommandSender(plistCommandPluginDirs), // + pControlSender(), // + pRouter(&pDatabaseHandler, &pControlSender), // + pMockInterface(), // + pRoutingInterfaceBackdoor(), // + pCommandInterfaceBackdoor(), // + pControlReceiver(&pDatabaseHandler, &pRoutingSender, &pCommandSender, &pSocketHandler, &pRouter), // + pObserver(&pCommandSender, &pRoutingSender, &pSocketHandler) +{ + pDatabaseHandler.registerObserver(&pObserver); + pRoutingInterfaceBackdoor.unloadPlugins(&pRoutingSender); + pRoutingInterfaceBackdoor.injectInterface(&pRoutingSender, &pMockInterface, "mock"); + pCommandInterfaceBackdoor.unloadPlugins(&pCommandSender); +} + +CAmRoutingInterfaceTest::~CAmRoutingInterfaceTest() +{ +} + +void CAmRoutingInterfaceTest::SetUp() +{ + logInfo("RoutingSendInterface Test started "); + +} + +void CAmRoutingInterfaceTest::TearDown() +{ +} + +TEST_F(CAmRoutingInterfaceTest,abort) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + am_Domain_s domain; + am_domainID_t domainID; + am_Handle_s handle; + am_connectionID_t connectionID; + std::vector<am_Handle_s> listHandles; + pCF.createSink(sink); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + sink.sinkID = 2; + sink.domainID = DYNAMIC_ID_BOUNDARY; + + //prepare the stage + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + //start a connect, expect a call on the routingInterface + EXPECT_CALL(pMockInterface,asyncConnect(_,_,1,sinkID,CF_GENIVI_ANALOG)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.connect(handle,connectionID,CF_GENIVI_ANALOG,1,2)); + + //check the correctness of the handle + ASSERT_NE(handle.handle, 0); + ASSERT_EQ(handle.handleType, H_CONNECT); + + //the handle must be inside the handlelist + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(listHandles)); + ASSERT_TRUE(listHandles[0].handle==handle.handle); + ASSERT_TRUE(listHandles[0].handleType==handle.handleType); + + //send an abort expect a call on the routing interface + EXPECT_CALL(pMockInterface,asyncAbort(_)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.abortAction(handle)); + + //the reaction on the abort is specific for every function + + //now we try to abort a handle that does not exist + handle.handle = 24; + ASSERT_EQ(E_NON_EXISTENT, pControlReceiver.abortAction(handle)); +} + +TEST_F(CAmRoutingInterfaceTest,abortNonExistent) +{ + EXPECT_CALL(pMockInterface,asyncAbort(_)).Times(0); + am_Handle_s handle; + ASSERT_EQ(E_NON_EXISTENT, pControlReceiver.abortAction(handle)); +} + +TEST_F(CAmRoutingInterfaceTest,alreadyConnected) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + am_Domain_s domain; + am_domainID_t domainID; + pCF.createSink(sink); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + sink.sinkID = 2; + sink.domainID = DYNAMIC_ID_BOUNDARY; + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + EXPECT_CALL(pMockInterface,asyncConnect(_,_,1,sinkID,CF_GENIVI_ANALOG)).WillOnce(Return(E_OK)); + am_Handle_s handle; + am_connectionID_t connectionID; + ASSERT_EQ(E_OK, pControlReceiver.connect(handle,connectionID,CF_GENIVI_ANALOG,1,2)); + ASSERT_EQ(E_OK, pDatabaseHandler.changeConnectionFinal(connectionID)); + //ASSERT_EQ(E_ALREADY_EXISTS, pControlReceiver.connect(handle,connectionID,CF_GENIVI_ANALOG,1,2)); + ASSERT_NE(handle.handle, 0); + ASSERT_EQ(handle.handleType, H_CONNECT); +} + +TEST_F(CAmRoutingInterfaceTest,setSinkSoundPropertyNoChange) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + am_Domain_s domain; + am_domainID_t domainID; + am_Handle_s handle; + am_SoundProperty_s soundProperty; + soundProperty.type = SP_GENIVI_TREBLE; + soundProperty.value = 23; + std::vector<am_Handle_s> listHandles; + pCF.createSink(sink); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + sink.sinkID = 2; + sink.domainID = DYNAMIC_ID_BOUNDARY; + sink.listSoundProperties.push_back(soundProperty); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + EXPECT_CALL(pMockInterface,asyncSetSinkSoundProperty(_,sinkID,_)).Times(1).WillOnce(Return(E_NO_CHANGE)); + ASSERT_EQ(E_NO_CHANGE, pControlReceiver.setSinkSoundProperty(handle,sinkID,soundProperty)); +} + +TEST_F(CAmRoutingInterfaceTest,setSourceState) +{ + am_Source_s source; + am_sourceID_t sourceID; + am_Domain_s domain; + am_domainID_t domainID; + am_Handle_s handle; + handle.handle = 0; + am_SourceState_e state = SS_PAUSED; + pCF.createSource(source); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + source.domainID = DYNAMIC_ID_BOUNDARY; + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + EXPECT_CALL(pMockInterface,asyncSetSourceState(_,sourceID,state)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.setSourceState(handle,sourceID,state)); + ASSERT_NE(handle.handle, 0); + ASSERT_EQ(handle.handleType, H_SETSOURCESTATE); +} + +TEST_F(CAmRoutingInterfaceTest,setSourceSoundProperty) +{ + am_Source_s source; + am_sourceID_t sourceID; + am_Domain_s domain; + am_domainID_t domainID; + am_Handle_s handle; + am_SoundProperty_s soundProperty; + std::vector<am_Handle_s> listHandles; + pCF.createSource(source); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + source.sourceID = 2; + source.domainID = DYNAMIC_ID_BOUNDARY; + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + EXPECT_CALL(pMockInterface,asyncSetSourceSoundProperty(_,sourceID,_)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.setSourceSoundProperty(handle,sourceID,soundProperty)); + ASSERT_NE(handle.handle, 0); + ASSERT_EQ(handle.handleType, H_SETSOURCESOUNDPROPERTY); + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(listHandles)); + ASSERT_TRUE(listHandles[0].handle==handle.handle); + ASSERT_TRUE(listHandles[0].handleType==handle.handleType); +} + +TEST_F(CAmRoutingInterfaceTest,setSinkSoundProperty) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + am_Domain_s domain; + am_domainID_t domainID; + am_Handle_s handle; + am_SoundProperty_s soundProperty; + soundProperty.value=5; + soundProperty.type=SP_GENIVI_MID; + std::vector<am_Handle_s> listHandles; + pCF.createSink(sink); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + sink.sinkID = 2; + sink.domainID = DYNAMIC_ID_BOUNDARY; + sink.listSoundProperties.push_back(soundProperty); + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + EXPECT_CALL(pMockInterface,asyncSetSinkSoundProperty(_,sinkID,_)).WillOnce(Return(E_OK)); + soundProperty.value=10; + ASSERT_EQ(E_OK, pControlReceiver.setSinkSoundProperty(handle,sinkID,soundProperty)); + ASSERT_NE(handle.handle, 0); + ASSERT_EQ(handle.handleType, H_SETSINKSOUNDPROPERTY); + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(listHandles)); + ASSERT_TRUE(listHandles[0].handle==handle.handle); + ASSERT_TRUE(listHandles[0].handleType==handle.handleType); +} + + + +TEST_F(CAmRoutingInterfaceTest,setSourceVolume) +{ + am_Source_s source; + am_sourceID_t sourceID; + am_Domain_s domain; + am_domainID_t domainID; + am_Handle_s handle; + am_volume_t volume = 34; + am_CustomRampType_t rampType = RAMP_GENIVI_DIRECT; + am_time_t rampTime = 300; + std::vector<am_Handle_s> listHandles; + pCF.createSource(source); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + source.sourceID = 2; + source.domainID = DYNAMIC_ID_BOUNDARY; + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceDB(source,sourceID)); + EXPECT_CALL(pMockInterface,asyncSetSourceVolume(_,2,volume,rampType,rampTime)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.setSourceVolume(handle,2,volume,rampType,rampTime)); + ASSERT_NE(handle.handle, 0); + ASSERT_EQ(handle.handleType, H_SETSOURCEVOLUME); + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(listHandles)); + ASSERT_TRUE(listHandles[0].handle==handle.handle); + ASSERT_TRUE(listHandles[0].handleType==handle.handleType); +} + +TEST_F(CAmRoutingInterfaceTest,setSinkVolume) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + am_Domain_s domain; + am_domainID_t domainID; + am_Handle_s handle; + am_volume_t volume = 34; + am_CustomRampType_t rampType = RAMP_GENIVI_DIRECT; + am_time_t rampTime = 300; + std::vector<am_Handle_s> listHandles; + pCF.createSink(sink); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + sink.sinkID = 2; + sink.domainID = DYNAMIC_ID_BOUNDARY; + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + EXPECT_CALL(pMockInterface,asyncSetSinkVolume(_,2,volume,rampType,rampTime)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.setSinkVolume(handle,2,volume,rampType,rampTime)); + ASSERT_NE(handle.handle, 0); + ASSERT_EQ(handle.handleType, H_SETSINKVOLUME); + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(listHandles)); + ASSERT_TRUE(listHandles[0].handle==handle.handle); + ASSERT_TRUE(listHandles[0].handleType==handle.handleType); +} + +TEST_F(CAmRoutingInterfaceTest,connect) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + am_Domain_s domain; + am_domainID_t domainID; + am_Handle_s handle; + am_connectionID_t connectionID; + std::vector<am_Handle_s> listHandles; + pCF.createSink(sink); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + sink.sinkID = 2; + sink.domainID = DYNAMIC_ID_BOUNDARY; + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + EXPECT_CALL(pMockInterface,asyncConnect(_,_,1,sinkID,CF_GENIVI_ANALOG)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.connect(handle,connectionID,CF_GENIVI_ANALOG,1,2)); + ASSERT_NE(handle.handle, 0); + ASSERT_EQ(handle.handleType, H_CONNECT); + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(listHandles)); + ASSERT_TRUE(listHandles[0].handle==handle.handle); + ASSERT_TRUE(listHandles[0].handleType==handle.handleType); +} + +TEST_F(CAmRoutingInterfaceTest,disconnect) +{ + am_Sink_s sink; + am_sinkID_t sinkID; + am_Domain_s domain; + am_domainID_t domainID; + am_Handle_s handle; + am_connectionID_t connectionID; + std::vector<am_Handle_s> listHandles; + pCF.createSink(sink); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + sink.sinkID = 2; + sink.domainID = DYNAMIC_ID_BOUNDARY; + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + EXPECT_CALL(pMockInterface,asyncConnect(_,_,1,sinkID,CF_GENIVI_ANALOG)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.connect(handle,connectionID,CF_GENIVI_ANALOG,1,2)); + ASSERT_EQ(E_OK, pDatabaseHandler.changeConnectionFinal(connectionID)); + EXPECT_CALL(pMockInterface,asyncDisconnect(_,connectionID)).WillOnce(Return(E_OK)); + ASSERT_EQ(E_OK, pControlReceiver.disconnect(handle,connectionID)); + ASSERT_NE(handle.handle, 0); + ASSERT_EQ(handle.handleType, H_DISCONNECT); + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(listHandles)); + ASSERT_TRUE(listHandles[1].handle==handle.handle); + ASSERT_TRUE(listHandles[1].handleType==handle.handleType); +} + + +TEST_F(CAmRoutingInterfaceTest,nothingTodisconnect) +{ + am_Handle_s handle; + am_connectionID_t connectionID = 4; + std::vector<am_Handle_s> listHandles; + ASSERT_EQ(E_NON_EXISTENT, pControlReceiver.disconnect(handle,connectionID)); + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(listHandles)); + ASSERT_TRUE(listHandles.empty()); +} + + +int main(int argc, char **argv) +{ + try + { + TCLAP::CmdLine* cmd(CAmCommandLineSingleton::instanciateOnce("The team of the AudioManager wishes you a nice day!",' ',DAEMONVERSION,true)); + cmd->add(enableNoDLTDebug); + } + catch (TCLAP::ArgException &e) // catch any exceptions + { std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; } + CAmCommandLineSingleton::instance()->preparse(argc,argv); + CAmDltWrapper::instance(enableNoDLTDebug.getValue())->registerApp("routing", "CAmRouterTest"); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/AudioManagerCore/test/AmRoutingInterfaceTest/CAmRoutingInterfaceTest.h b/AudioManagerCore/test/AmRoutingInterfaceTest/CAmRoutingInterfaceTest.h new file mode 100644 index 0000000..75a7511 --- /dev/null +++ b/AudioManagerCore/test/AmRoutingInterfaceTest/CAmRoutingInterfaceTest.h @@ -0,0 +1,71 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#ifndef ROUTINGINTERFACETEST_H_ +#define ROUTINGINTERFACETEST_H_ + +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include <algorithm> +#include <string> +#include <vector> +#include <set> +#include "CAmDatabaseHandlerMap.h" +#include "CAmControlReceiver.h" +#include "CAmControlSender.h" +#include "CAmDatabaseObserver.h" +#include "CAmRouter.h" +#include "../IAmRoutingBackdoor.h" +#include "../IAmCommandBackdoor.h" +#include "../CAmCommonFunctions.h" +#include "../MockIAmRoutingSend.h" +#include "CAmSocketHandler.h" + +namespace am +{ + +class CAmRoutingInterfaceTest: public ::testing::Test +{ +public: + CAmRoutingInterfaceTest(); + ~CAmRoutingInterfaceTest(); + std::vector<std::string> plistRoutingPluginDirs; + std::vector<std::string> plistCommandPluginDirs; + CAmSocketHandler pSocketHandler; + CAmDatabaseHandlerMap pDatabaseHandler; + CAmRoutingSender pRoutingSender; + CAmCommandSender pCommandSender; + CAmControlSender pControlSender; + CAmRouter pRouter; + MockIAmRoutingSend pMockInterface; + IAmRoutingBackdoor pRoutingInterfaceBackdoor; + IAmCommandBackdoor pCommandInterfaceBackdoor; + CAmControlReceiver pControlReceiver; + CAmDatabaseObserver pObserver; + CAmCommonFunctions pCF; + void SetUp(); + void TearDown(); +}; + +} + +#endif /* ROUTINGINTERFACETEST_H_ */ diff --git a/AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt b/AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt new file mode 100644 index 0000000..dc5115d --- /dev/null +++ b/AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt @@ -0,0 +1,49 @@ +# 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 +# +# For further information see http://www.genivi.org/. +# + +cmake_minimum_required(VERSION 3.0) + +project (AmRoutingInterfaceTest LANGUAGES CXX VERSION ${DAEMONVERSION}) + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNIT_TEST=1 -DDLT_CONTEXT=AudioManager") + +INCLUDE_DIRECTORIES( + ${AUDIOMANAGER_CORE_INCLUDE} + ${GMOCK_INCLUDE_DIRS} + ${GTEST_INCLUDE_DIRS}) + +file(GLOB ROUTING_INTERFACE_SRCS_CXX + "../CAmCommonFunctions.cpp" + "*.cpp" +) + +ADD_EXECUTABLE(AmRoutingInterfaceTest ${ROUTING_INTERFACE_SRCS_CXX}) + +TARGET_LINK_LIBRARIES(AmRoutingInterfaceTest + ${GTEST_LIBRARIES} + ${GMOCK_LIBRARIES} + AudioManagerCore +) + +ADD_DEPENDENCIES(AmRoutingInterfaceTest AudioManagerCore) + +INSTALL(TARGETS AmRoutingInterfaceTest + DESTINATION ${TEST_EXECUTABLE_INSTALL_PATH} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + COMPONENT tests +) + diff --git a/AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt~ b/AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt~ new file mode 100644 index 0000000..e8fbb29 --- /dev/null +++ b/AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt~ @@ -0,0 +1,48 @@ +# 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 +# +# For further information see http://www.genivi.org/. +# + +cmake_minimum_required(VERSION 3.0) + +project (AmRoutingInterfaceTest LANGUAGES CXX VERSION ${DAEMONVERSION}) + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNIT_TEST=1 -DDLT_CONTEXT=AudioManager") + +INCLUDE_DIRECTORIES( + ${AUDIOMANAGER_CORE_INCLUDE} + ${GMOCK_INCLUDE_DIR}) + +file(GLOB ROUTING_INTERFACE_SRCS_CXX + "../CAmCommonFunctions.cpp" + "*.cpp" +) + +ADD_EXECUTABLE(AmRoutingInterfaceTest ${ROUTING_INTERFACE_SRCS_CXX}) + +TARGET_LINK_LIBRARIES(AmRoutingInterfaceTest + ${GTEST_LIBRARIES} + ${GMOCK_LIBRARIES} + AudioManagerCore +) + +ADD_DEPENDENCIES(AmRoutingInterfaceTest AudioManagerCore) + +INSTALL(TARGETS AmRoutingInterfaceTest + DESTINATION ${TEST_EXECUTABLE_INSTALL_PATH} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + COMPONENT tests +) + diff --git a/AudioManagerCore/test/AmTelnetServerTest/CAmTelnetServerTest.cpp b/AudioManagerCore/test/AmTelnetServerTest/CAmTelnetServerTest.cpp new file mode 100644 index 0000000..d3f7a11 --- /dev/null +++ b/AudioManagerCore/test/AmTelnetServerTest/CAmTelnetServerTest.cpp @@ -0,0 +1,209 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#include <sys/socket.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <string> + +#include "CAmTelnetServerTest.h" +#include "CAmCommandReceiver.h" +#include "CAmRoutingReceiver.h" +#include "CAmControlReceiver.h" +#include "audiomanagerconfig.h" + + +using namespace testing; +using namespace am; +using namespace std; + + +static std::string controllerPlugin = std::string(CONTROLLER_PLUGIN_DIR); +static unsigned short servPort = 6060; +static int staticSocket = -1; +static CAmSocketHandler* mpSocketHandler = NULL; + +void* startSocketHandler(void* data) +{ + CAmEnvironment* Env = static_cast<CAmEnvironment*>(data); + Env->setSocketHandler(&Env->mSocketHandler); + Env->mSocketHandler.start_listenting(); + Env->setSocketHandler(NULL); + return (NULL); +} + +CAmEnvironment::CAmEnvironment() +: mlistRoutingPluginDirs() +, mlistCommandPluginDirs() +, mSocketHandler() +, mDatabasehandler() +, mRoutingSender(mlistRoutingPluginDirs) +, mCommandSender(mlistRoutingPluginDirs) +, mRouter(&mDatabasehandler,&mControlSender) +, mpCommandReceiver(NULL) +, mpRoutingReceiver(NULL) +, mpControlReceiver(NULL) +, mpTelnetServer(NULL) +, mSocketHandlerThread(0) +{ +} + +CAmEnvironment::~CAmEnvironment() +{ + usleep(500); + if(NULL != mpTelnetServer) + delete(mpTelnetServer); + if(NULL != mpControlReceiver) + delete(mpControlReceiver); + if(NULL != mpRoutingReceiver) + delete(mpRoutingReceiver); + if(NULL != mpCommandReceiver) + delete(mpCommandReceiver); +} + +void CAmEnvironment::SetUp() +{ + pthread_create(&mSocketHandlerThread, NULL, startSocketHandler, this); + sleep(1); +} + +void CAmEnvironment::TearDown() +{ + pthread_cancel(mSocketHandlerThread); +} + +void CAmEnvironment::setSocketHandler(CAmSocketHandler* pSocketHandler) +{ + mpSocketHandler = pSocketHandler; + + if(NULL != pSocketHandler) + { + mpCommandReceiver = new CAmCommandReceiver(&mDatabasehandler,&mControlSender,mpSocketHandler); + mpRoutingReceiver = new CAmRoutingReceiver(&mDatabasehandler,&mRoutingSender,&mControlSender,mpSocketHandler); + mpControlReceiver = new CAmControlReceiver(&mDatabasehandler,&mRoutingSender,&mCommandSender,mpSocketHandler,&mRouter); + + //startup all the Plugins and Interfaces + //mControlSender.startupController(mpControlReceiver); + //mCommandSender.startupInterfaces(mpCommandReceiver); + //mRoutingSender.startupInterfaces(mpRoutingReceiver); + + //when the routingInterface is done, all plugins are loaded: + //mControlSender.setControllerReady(); + + // Starting TelnetServer + mpTelnetServer = new CAmTelnetServer(mpSocketHandler,&mCommandSender,mpCommandReceiver,&mRoutingSender,mpRoutingReceiver,&mControlSender,mpControlReceiver,&mDatabasehandler,&mRouter,servPort,3); + } +} + +void CAmEnvironment::stopSocketHandler() +{ + mpSocketHandler->stop_listening(); +} + +CAmTelnetServerTest::CAmTelnetServerTest() +{ + +} + +CAmTelnetServerTest::~CAmTelnetServerTest() +{ + +} + +void CAmTelnetServerTest::SetUp() +{ + +} + +void CAmTelnetServerTest::TearDown() +{ + +} + +void CAmTelnetServerTest::sendCmd(std::string & command ) +{ + ssize_t sizesent = send(staticSocket, command.c_str(), command.size(), 0); + ASSERT_EQ(static_cast<uint>(sizesent),command.size()); + + char buffer[1000]; + memset(buffer,0,sizeof(buffer)); + int read=recv(staticSocket,buffer,sizeof(buffer),0); + ASSERT_GT(read,1); +} + +TEST_F(CAmTelnetServerTest,connectTelnetServer) +{ + struct sockaddr_in servAddr; + + staticSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + ASSERT_GE(staticSocket,0); + + struct hostent *host = (struct hostent*) gethostbyname("localhost"); + if (host == 0) + { + std::cout << " ERROR: gethostbyname() failed\n" << std::endl; + return; + } + + memset(&servAddr, 0, sizeof(servAddr)); + servAddr.sin_family = AF_INET; + servAddr.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr*) (host->h_addr_list[0]))); + servAddr.sin_port = htons(servPort); + + int return_connect = connect(staticSocket, (struct sockaddr *) &servAddr, sizeof(servAddr)); + ASSERT_GE(return_connect,0); + + char buffer[1000]; + int read=recv(staticSocket,buffer,sizeof(buffer),0); + ASSERT_GT(read,1); +} + +TEST_F(CAmTelnetServerTest,sendCmdTelnetServer) +{ + std::string cmd("help"); + sendCmd(cmd); +} + +TEST_F(CAmTelnetServerTest,sendDumpCmdTelnetServer) +{ + std::string cmd1("info"); + std::string cmd3("dump"); + sendCmd(cmd1); + sendCmd(cmd3); +} + +TEST_F(CAmTelnetServerTest,closeTelnetServerConnection) +{ + std::string cmd("exit"); + mpSocketHandler->stop_listening(); + sendCmd(cmd); + close(staticSocket); + staticSocket = -1; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + ::testing::Environment* const env = ::testing::AddGlobalTestEnvironment(new CAmEnvironment); + (void) env; + return RUN_ALL_TESTS(); +} diff --git a/AudioManagerCore/test/AmTelnetServerTest/CAmTelnetServerTest.h b/AudioManagerCore/test/AmTelnetServerTest/CAmTelnetServerTest.h new file mode 100644 index 0000000..02f98a3 --- /dev/null +++ b/AudioManagerCore/test/AmTelnetServerTest/CAmTelnetServerTest.h @@ -0,0 +1,107 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#ifndef CAMTELNETSERVERTEST_H_ +#define CAMTELNETSERVERTEST_H_ + +#include "gtest/gtest.h" +#include "CAmTelnetServer.h" +#include "CAmRoutingSender.h" +#include "CAmCommandSender.h" +#include "CAmControlSender.h" +#include "CAmRouter.h" +#include "audiomanagerconfig.h" +#include "CAmDatabaseHandlerMap.h" + + + + + +namespace am +{ + +class CAmSocketHandler; +class CAmRoutingSender; +class CAmCommandSender; +class CAmControlSender; +class CAmRouter; +class CAmCommandReceiver; +class CAmRoutingReceiver; +class CAmControlReceiver; +class CAmTelnetServer; + + +class CAmEnvironment : public ::testing::Environment +{ + public: + CAmEnvironment(); + + ~CAmEnvironment(); + // Override this to define how to set up the environment. + void SetUp(); + // Override this to define how to tear down the environment. + void TearDown(); + + void setSocketHandler(CAmSocketHandler* pSocketHandler); + + void stopSocketHandler(); + + std::vector<std::string> mlistRoutingPluginDirs; + std::vector<std::string> mlistCommandPluginDirs; + + CAmSocketHandler mSocketHandler; + CAmDatabaseHandlerMap mDatabasehandler; + CAmRoutingSender mRoutingSender; + CAmCommandSender mCommandSender; + CAmControlSender mControlSender; + CAmRouter mRouter; + + CAmCommandReceiver* mpCommandReceiver; + CAmRoutingReceiver* mpRoutingReceiver; + CAmControlReceiver* mpControlReceiver; + + CAmTelnetServer* mpTelnetServer; + + pthread_t mSocketHandlerThread; +}; + +class CAmTelnetServerTest : public ::testing::Test +{ + public: + CAmTelnetServerTest(); + ~CAmTelnetServerTest(); + + + void SetUp() ; + + void TearDown() ; + void sendCmd(std::string & command ); + //int mSocket; +}; + +} + + + + +#endif /* CAMTELNETSERVERTEST_H_ */ diff --git a/AudioManagerCore/test/AmTelnetServerTest/CMakeLists.txt b/AudioManagerCore/test/AmTelnetServerTest/CMakeLists.txt new file mode 100644 index 0000000..8dcb0a3 --- /dev/null +++ b/AudioManagerCore/test/AmTelnetServerTest/CMakeLists.txt @@ -0,0 +1,48 @@ +# 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 +# +# For further information see http://www.genivi.org/. +# + +cmake_minimum_required(VERSION 3.0) + +PROJECT(AmTelnetServerTest LANGUAGES CXX VERSION ${DAEMONVERSION}) + +INCLUDE_DIRECTORIES( + ${AUDIOMANAGER_CORE_INCLUDE} + ${GMOCK_INCLUDE_DIRS} + ${GTEST_INCLUDE_DIRS}) + +file(GLOB TELNET_SRCS_CXX + "*.cpp" +) + +ADD_EXECUTABLE(AmTelnetServerTest ${TELNET_SRCS_CXX}) + +TARGET_LINK_LIBRARIES(AmTelnetServerTest + ${GTEST_LIBRARIES} + ${GMOCK_LIBRARIES} + AudioManagerCore +) +add_test(AmTelnetServerTest AmTelnetServerTest) + +ADD_DEPENDENCIES(AmTelnetServerTest AudioManagerCore) + +INSTALL(TARGETS AmTelnetServerTest + DESTINATION ${TEST_EXECUTABLE_INSTALL_PATH} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + COMPONENT tests +) + + diff --git a/AudioManagerCore/test/AmTelnetServerTest/CMakeLists.txt~ b/AudioManagerCore/test/AmTelnetServerTest/CMakeLists.txt~ new file mode 100644 index 0000000..51e92b8 --- /dev/null +++ b/AudioManagerCore/test/AmTelnetServerTest/CMakeLists.txt~ @@ -0,0 +1,46 @@ +# 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 +# +# For further information see http://www.genivi.org/. +# + +cmake_minimum_required(VERSION 3.0) + +PROJECT(AmTelnetServerTest LANGUAGES CXX VERSION ${DAEMONVERSION}) + +INCLUDE_DIRECTORIES( + ${AUDIOMANAGER_CORE_INCLUDE} + ${GMOCK_INCLUDE_DIR}) + +file(GLOB TELNET_SRCS_CXX + "*.cpp" +) + +ADD_EXECUTABLE(AmTelnetServerTest ${TELNET_SRCS_CXX}) + +TARGET_LINK_LIBRARIES(AmTelnetServerTest + ${GTEST_LIBRARIES} + ${GMOCK_LIBRARIES} + AudioManagerCore +) + +ADD_DEPENDENCIES(AmTelnetServerTest AudioManagerCore) + +INSTALL(TARGETS AmTelnetServerTest + DESTINATION ${TEST_EXECUTABLE_INSTALL_PATH} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + COMPONENT tests +) + + diff --git a/AudioManagerCore/test/CAmCommonFunctions.cpp b/AudioManagerCore/test/CAmCommonFunctions.cpp new file mode 100644 index 0000000..22331d4 --- /dev/null +++ b/AudioManagerCore/test/CAmCommonFunctions.cpp @@ -0,0 +1,383 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#include "CAmCommonFunctions.h" +#include "IAmCommandBackdoor.h" +#include "IAmRoutingBackdoor.h" +#include "IAmControlBackdoor.h" +#include <cassert> +#include <sstream> + +using namespace am; + +IAmCommandBackdoor::IAmCommandBackdoor() +{ +} +IAmCommandBackdoor::~IAmCommandBackdoor() +{ +} + +bool IAmCommandBackdoor::unloadPlugins(CAmCommandSender *CommandSender) +{ + assert(CommandSender != NULL); + CommandSender->unloadLibraries(); + CommandSender->mListInterfaces.clear(); + if (CommandSender->mListInterfaces.empty()) + return true; + return false; +} + +bool IAmCommandBackdoor::injectInterface(CAmCommandSender *CommandSender, IAmCommandSend *CommandSendInterface) +{ + assert(CommandSender != NULL); + assert(CommandSendInterface != NULL); + CommandSender->mListInterfaces.push_back(CommandSendInterface); + return true; +} + +IAmRoutingBackdoor::IAmRoutingBackdoor() +{ +} +IAmRoutingBackdoor::~IAmRoutingBackdoor() +{ +} + +bool IAmRoutingBackdoor::unloadPlugins(CAmRoutingSender *RoutingSender) +{ + assert(RoutingSender != NULL); + RoutingSender->unloadLibraries(); + RoutingSender->mListInterfaces.clear(); + if (RoutingSender->mListInterfaces.empty()) + return true; + return false; +} + +bool IAmRoutingBackdoor::injectInterface(CAmRoutingSender *RoutingSender, IAmRoutingSend *newInterface, const std::string& busname) +{ + assert(RoutingSender != NULL); + assert(newInterface != NULL); + + CAmRoutingSender::InterfaceNamePairs newInterfacePair; + newInterfacePair.routingInterface = newInterface; + newInterfacePair.busName = busname; + RoutingSender->mListInterfaces.push_back(newInterfacePair); + return true; +} + +IAmControlBackdoor::IAmControlBackdoor() +{ +} + +IAmControlBackdoor::~IAmControlBackdoor() +{ +} + +bool IAmControlBackdoor::replaceController(CAmControlSender *controlSender, IAmControlSend *newController) +{ + controlSender->mController = newController; + return controlSender->mController == newController; +} + +//int GetRandomNumber(int nLow, int nHigh) { +// return (rand() % (nHigh - nLow + 1)) + nLow; +//} + +bool equalSoundProperty(const am_SoundProperty_s a, const am_SoundProperty_s b) +{ + return (a.type == b.type && a.value == b.value); +} + +bool equalMainSoundProperty(const am_MainSoundProperty_s a, const am_MainSoundProperty_s b) +{ + return (a.type == b.type && a.value == b.value); +} + +bool equalNotificationConfiguration(const am_NotificationConfiguration_s a, const am_NotificationConfiguration_s b) +{ + return (a.parameter == b.parameter && a.status == b.status && a.type == b.type); +} + +bool equalRoutingElement(const am_RoutingElement_s a, const am_RoutingElement_s b) +{ + return (a.connectionFormat == b.connectionFormat && a.domainID == b.domainID && a.sinkID == b.sinkID && a.sourceID == b.sourceID); +} + +bool equalClassProperties(const am_ClassProperty_s a, const am_ClassProperty_s b) +{ + return (a.classProperty == b.classProperty && a.value == b.value); +} + +std::string int2string(int i) +{ + std::stringstream out; + out << i; + return out.str(); +} + +bool CAmCommonFunctions::compareSource(std::vector<am_Source_s>::iterator listIterator, const am_Source_s& sourceData) +{ + return (listIterator->available.availability == sourceData.available.availability) && \ + (listIterator->available.availabilityReason == sourceData.available.availabilityReason) && + (listIterator->sourceClassID == sourceData.sourceClassID) && + (listIterator->domainID == sourceData.domainID) && + (listIterator->interruptState == sourceData.interruptState) && + (listIterator->visible == sourceData.visible) && + (listIterator->name.compare(sourceData.name) == 0) && + (listIterator->volume == sourceData.volume) && + std::equal(listIterator->listConnectionFormats.begin(), listIterator->listConnectionFormats.end(), sourceData.listConnectionFormats.begin()) && + std::equal(listIterator->listMainSoundProperties.begin(), listIterator->listMainSoundProperties.end(), sourceData.listMainSoundProperties.begin(), equalMainSoundProperty) && + std::equal(listIterator->listSoundProperties.begin(), listIterator->listSoundProperties.end(), sourceData.listSoundProperties.begin(), equalSoundProperty); +} + +bool CAmCommonFunctions::compareSink(std::vector<am_Sink_s>::iterator listIterator, const am_Sink_s& sinkData) +{ + return (listIterator->available.availability == sinkData.available.availability) && (listIterator->available.availabilityReason == sinkData.available.availabilityReason) && (listIterator->sinkClassID == sinkData.sinkClassID) && (listIterator->domainID == sinkData.domainID) && (listIterator->mainVolume == sinkData.mainVolume) && (listIterator->muteState == sinkData.muteState) && (listIterator->visible == sinkData.visible) && (listIterator->name.compare(sinkData.name) == 0) && (listIterator->volume == sinkData.volume) && std::equal(listIterator->listConnectionFormats.begin(), listIterator->listConnectionFormats.end(), sinkData.listConnectionFormats.begin()) + && std::equal(listIterator->listMainSoundProperties.begin(), listIterator->listMainSoundProperties.end(), sinkData.listMainSoundProperties.begin(), equalMainSoundProperty) && std::equal(listIterator->listSoundProperties.begin(), listIterator->listSoundProperties.end(), sinkData.listSoundProperties.begin(), equalSoundProperty); +} + +bool CAmCommonFunctions::compareGateway(std::vector<am_Gateway_s>::iterator listIterator, const am_Gateway_s& gatewayData) +{ + return (listIterator->name.compare(gatewayData.name) == 0) && (listIterator->sinkID == gatewayData.sinkID) && (listIterator->sourceID == gatewayData.sourceID) && (listIterator->controlDomainID == gatewayData.controlDomainID) && (listIterator->domainSinkID == gatewayData.domainSinkID) && (listIterator->domainSourceID == gatewayData.domainSourceID) && std::equal(listIterator->convertionMatrix.begin(), listIterator->convertionMatrix.end(), gatewayData.convertionMatrix.begin()) && std::equal(listIterator->listSourceFormats.begin(), listIterator->listSourceFormats.end(), gatewayData.listSourceFormats.begin()) && std::equal(listIterator->listSinkFormats.begin(), listIterator->listSinkFormats.end(), gatewayData.listSinkFormats.begin()); +} + +bool CAmCommonFunctions::compareConverter(std::vector<am_Converter_s>::iterator listIterator, const am_Converter_s& gatewayData) +{ + return (listIterator->name.compare(gatewayData.name) == 0) && (listIterator->sinkID == gatewayData.sinkID) && (listIterator->sourceID == gatewayData.sourceID) && (listIterator->domainID == gatewayData.domainID) && std::equal(listIterator->convertionMatrix.begin(), listIterator->convertionMatrix.end(), gatewayData.convertionMatrix.begin()) && std::equal(listIterator->listSourceFormats.begin(), listIterator->listSourceFormats.end(), gatewayData.listSourceFormats.begin()) && std::equal(listIterator->listSinkFormats.begin(), listIterator->listSinkFormats.end(), gatewayData.listSinkFormats.begin()); +} + +bool CAmCommonFunctions::compareGateway1(const am_Gateway_s gateway1, const am_Gateway_s gatewayData) +{ + return (gateway1.name.compare(gatewayData.name) == 0) && (gateway1.sinkID == gatewayData.sinkID) && (gateway1.sourceID == gatewayData.sourceID) && (gateway1.controlDomainID == gatewayData.controlDomainID) && (gateway1.domainSinkID == gatewayData.domainSinkID) && (gateway1.domainSourceID == gatewayData.domainSourceID) && std::equal(gateway1.convertionMatrix.begin(), gateway1.convertionMatrix.end(), gatewayData.convertionMatrix.begin()) && std::equal(gateway1.listSourceFormats.begin(), gateway1.listSourceFormats.end(), gatewayData.listSourceFormats.begin()) && std::equal(gateway1.listSinkFormats.begin(), gateway1.listSinkFormats.end(), gatewayData.listSinkFormats.begin()); +} + +bool CAmCommonFunctions::compareConverter1(const am_Converter_s gateway1, const am_Converter_s gatewayData) +{ + return (gateway1.name.compare(gatewayData.name) == 0) && (gateway1.sinkID == gatewayData.sinkID) && (gateway1.sourceID == gatewayData.sourceID) && (gateway1.domainID == gatewayData.domainID) && std::equal(gateway1.convertionMatrix.begin(), gateway1.convertionMatrix.end(), gatewayData.convertionMatrix.begin()) && std::equal(gateway1.listSourceFormats.begin(), gateway1.listSourceFormats.end(), gatewayData.listSourceFormats.begin()) && std::equal(gateway1.listSinkFormats.begin(), gateway1.listSinkFormats.end(), gatewayData.listSinkFormats.begin()); +} + +bool CAmCommonFunctions::compareSinkMainSink(std::vector<am_SinkType_s>::iterator listIterator, const std::vector<am_Sink_s>& sinkList) +{ + std::vector<am_Sink_s>::const_iterator sinkListIterator = sinkList.begin(); + for (; sinkListIterator < sinkList.end(); ++sinkListIterator) + { + if (listIterator->sinkID == sinkListIterator->sinkID) + { + return (listIterator->name.compare(sinkListIterator->name) == 0) && (listIterator->availability.availability == sinkListIterator->available.availability) && (listIterator->availability.availabilityReason == sinkListIterator->available.availabilityReason) && (listIterator->muteState == sinkListIterator->muteState) && (listIterator->volume == sinkListIterator->mainVolume) && (listIterator->sinkClassID == sinkListIterator->sinkClassID); + } + } + return false; +} + +bool CAmCommonFunctions::compareSinkMainSource(std::vector<am_SourceType_s>::iterator listIterator, const std::vector<am_Source_s>& sourceList) +{ + std::vector<am_Source_s>::const_iterator sinkListIterator = sourceList.begin(); + for (; sinkListIterator < sourceList.end(); ++sinkListIterator) + { + if (listIterator->sourceID == sinkListIterator->sourceID) + { + return (listIterator->name.compare(sinkListIterator->name) == 0) && (listIterator->availability.availability == sinkListIterator->available.availability) && (listIterator->availability.availabilityReason == sinkListIterator->available.availabilityReason) && (listIterator->sourceClassID == sinkListIterator->sourceClassID); + } + } + return false; +} + +bool CAmCommonFunctions::compareRoute(am_Route_s a, am_Route_s b) +{ + bool retVal = true; + std::vector<am_RoutingElement_s>::iterator itA = a.route.begin(), itB = b.route.begin(); + retVal &= a.sourceID == b.sourceID; + retVal &= a.sinkID == b.sinkID; + for (; itA != a.route.end(); ++itA) + { + retVal &= itA->sinkID == itB->sinkID; + retVal &= itA->sourceID == itB->sourceID; + retVal &= itA->connectionFormat == itB->connectionFormat; + retVal &= itA->domainID == itB->domainID; + itB++; + } + return retVal; +} + +std::vector<am_CustomAvailabilityReason_t> CAmCommonFunctions::getStandardConnectionFormatList() +{ + std::vector<am_CustomAvailabilityReason_t> list; + list.push_back(CF_GENIVI_ANALOG); + list.push_back(CF_GENIVI_STEREO); + return list; +} + +std::vector<am_SoundProperty_s> CAmCommonFunctions::getStandardSoundPropertyList() +{ + std::vector<am_SoundProperty_s> soundPropertyList; + am_SoundProperty_s soundProperty; + soundProperty.type = SP_GENIVI_BASS; + soundProperty.value = 23; + soundPropertyList.push_back(soundProperty); + soundProperty.type = SP_GENIVI_MID; + soundProperty.value = 2; + soundPropertyList.push_back(soundProperty); + return soundPropertyList; +} + +std::vector<am_MainSoundProperty_s> CAmCommonFunctions::getStandardMainSoundPropertyList() +{ + std::vector<am_MainSoundProperty_s> mainSoundPropertyList; + am_MainSoundProperty_s mainSoundProperty; + mainSoundProperty.type = MSP_GENIVI_BASS; + mainSoundProperty.value = 23; + mainSoundPropertyList.push_back(mainSoundProperty); + mainSoundProperty.type = MSP_UNKNOWN; + mainSoundProperty.value = 3; + mainSoundPropertyList.push_back(mainSoundProperty); + return mainSoundPropertyList; +} + +void CAmCommonFunctions::createSink(am_Sink_s& sink) const +{ + sink.name = "AnySink"; + sink.domainID = 4; + sink.available.availability = A_AVAILABLE; + sink.available.availabilityReason = AR_GENIVI_NEWMEDIA; + sink.sinkClassID = 1; + sink.listConnectionFormats = getStandardConnectionFormatList(); + sink.listSoundProperties = getStandardSoundPropertyList(); + sink.listMainSoundProperties = getStandardMainSoundPropertyList(); + sink.listNotificationConfigurations = getStandardNotificationConfigurationList(); + sink.listMainNotificationConfigurations = getStandardNotificationConfigurationList(); + sink.mainVolume = 12; + sink.muteState = MS_UNMUTED; + sink.visible = true; + sink.volume = 23; + sink.sinkID = 0; +} + +void CAmCommonFunctions::createSource(am_Source_s& source) const +{ + source.name = "AnySource"; + source.domainID = 4; + source.available.availability = A_AVAILABLE; + source.available.availabilityReason = AR_GENIVI_NEWMEDIA; + source.sourceClassID = 1; + source.listConnectionFormats = getStandardConnectionFormatList(); + source.listSoundProperties = getStandardSoundPropertyList(); + source.listMainSoundProperties = getStandardMainSoundPropertyList(); + source.listMainNotificationConfigurations=getStandardNotificationConfigurationList(); + source.listNotificationConfigurations=getStandardNotificationConfigurationList(); + source.interruptState = IS_OFF; + source.visible = true; + source.volume = 23; + source.sourceID = 0; + source.sourceState = SS_ON; +} + +void CAmCommonFunctions::createDomain(am_Domain_s & domain) const +{ + + domain.domainID = 0; + domain.name = "AnyDomain"; + domain.nodename = "AnyNode"; + domain.busname = "AnyBusname"; + domain.complete = true; + domain.early = true; + domain.state = DS_CONTROLLED; +} + +void CAmCommonFunctions::createGateway(am_Gateway_s & gateway) +{ + gateway.name = "AnyGateway"; + gateway.sinkID = 1; + gateway.sourceID = 2; + gateway.controlDomainID = 1; + gateway.domainSinkID = 3; + gateway.domainSourceID = 4; + gateway.convertionMatrix = getStandardConvertionMatrix(); + gateway.listSourceFormats = getStandardConnectionFormatList(); + gateway.listSinkFormats = getStandardConnectionFormatList(); + gateway.gatewayID = 0; + +} + +void CAmCommonFunctions::createConverter(am_Converter_s & converter) const +{ + converter.name = "AnyConverter"; + converter.sinkID = 1; + converter.sourceID = 2; + converter.domainID = 1; + converter.convertionMatrix = getStandardConvertionMatrix(); + converter.listSourceFormats = getStandardConnectionFormatList(); + converter.listSinkFormats = getStandardConnectionFormatList(); + converter.converterID = 0; + +} + +void CAmCommonFunctions::createConnection(am_Connection_s & connection) const +{ + connection.connectionID = 0; + connection.sinkID = 1; + connection.sourceID = 2; + connection.delay = -1; + connection.connectionFormat = CF_GENIVI_ANALOG; +} + +std::vector<bool> CAmCommonFunctions::getStandardConvertionMatrix() +{ + std::vector<bool> convMatrix; + convMatrix.push_back(true); + convMatrix.push_back(false); + convMatrix.push_back(true); + convMatrix.push_back(false); + convMatrix.push_back(true); + convMatrix.push_back(true); + return convMatrix; +} + +std::vector<am_NotificationConfiguration_s> am::CAmCommonFunctions::getStandardNotificationConfigurationList() +{ + std::vector<am_NotificationConfiguration_s> listNotificationConfigurations; + am_NotificationConfiguration_s tempNotificationConfiguration; + tempNotificationConfiguration.type=NT_TEST_1; + tempNotificationConfiguration.parameter=12; + tempNotificationConfiguration.status=NS_PERIODIC; + listNotificationConfigurations.push_back(tempNotificationConfiguration); + + tempNotificationConfiguration.type=NT_TEST_2; + tempNotificationConfiguration.parameter=16; + tempNotificationConfiguration.status=NS_CHANGE; + listNotificationConfigurations.push_back(tempNotificationConfiguration); + + return (listNotificationConfigurations); +} + +void CAmCommonFunctions::connectionList2RoutingList(std::vector<am_RoutingElement_s> & routingList, const std::vector<am_Connection_s>& connectionList) +{ + am_RoutingElement_s routingElement; + std::vector<am_Connection_s>::const_iterator cIterator = connectionList.begin(); + for (; cIterator < connectionList.end(); ++cIterator) + { + routingElement.sinkID = cIterator->sinkID; + routingElement.sourceID = cIterator->sourceID; + routingElement.connectionFormat = cIterator->connectionFormat; + routingElement.domainID = 4; //todo: make this test read out the real value + routingList.push_back(routingElement); + } +} + diff --git a/AudioManagerCore/test/CAmCommonFunctions.h b/AudioManagerCore/test/CAmCommonFunctions.h new file mode 100644 index 0000000..9dbdc8f --- /dev/null +++ b/AudioManagerCore/test/CAmCommonFunctions.h @@ -0,0 +1,96 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#ifndef COMMONHEADERS_H_ +#define COMMONHEADERS_H_ + +#include "audiomanagertypes.h" + +namespace am +{ + +static const am_CustomNotificationType_t NT_TEST_1 = 1; +static const am_CustomNotificationType_t NT_TEST_2 = 2; + + +class CAmCommonFunctions +{ +public: + + static std::vector<am_CustomAvailabilityReason_t> getStandardConnectionFormatList(); + static std::vector<am_SoundProperty_s> getStandardSoundPropertyList(); + static std::vector<am_MainSoundProperty_s> getStandardMainSoundPropertyList(); + static std::vector<bool> getStandardConvertionMatrix(); + static std::vector<am_NotificationConfiguration_s> getStandardNotificationConfigurationList(); + bool compareSource(std::vector<am_Source_s>::iterator listIterator, const am_Source_s& sourceData); + bool compareSink(std::vector<am_Sink_s>::iterator listIterator, const am_Sink_s& sinkData); + bool compareGateway(std::vector<am_Gateway_s>::iterator listIterator, const am_Gateway_s& gatewayData); + bool compareGateway1(const am_Gateway_s gateway1, const am_Gateway_s gatewayData); + bool compareConverter(std::vector<am_Converter_s>::iterator listIterator, const am_Converter_s& gatewayData); + bool compareConverter1(const am_Converter_s gateway1, const am_Converter_s gatewayData); + bool compareSinkMainSink(std::vector<am_SinkType_s>::iterator listIterator, const std::vector<am_Sink_s>& sinkList); + bool compareSinkMainSource(std::vector<am_SourceType_s>::iterator listIterator, const std::vector<am_Source_s>& sourceList); + bool compareRoute(am_Route_s a, am_Route_s b); + void createSink(am_Sink_s& sink) const; + void createSource(am_Source_s& source) const; + void createDomain(am_Domain_s& domain) const; + void createGateway(am_Gateway_s& gateway); + void createConnection(am_Connection_s& connection) const; + void createConverter(am_Converter_s & converter) const; + void connectionList2RoutingList(std::vector<am_RoutingElement_s>& routingList, const std::vector<am_Connection_s>& connectionList); + + struct sortBySinkID + { + bool operator()(const am_RoutingElement_s & a, const am_RoutingElement_s & b) const + { + return (a.sinkID < b.sinkID); + } + }; + + struct sortByConnectionFormat + { + bool operator()(const am_CustomAvailabilityReason_t & a, const am_CustomAvailabilityReason_t & b) const + { + return (a < b); + } + }; + + struct sortByMainSoundProperty + { + bool operator()(const am_MainSoundProperty_s & a, const am_MainSoundProperty_s & b) const + { + return (a.type > b.type); + } + }; + + struct sortBySoundProperty + { + bool operator()(const am_SoundProperty_s & a, const am_SoundProperty_s & b) const + { + return (a.type < b.type); + } + }; +}; + +} + +#endif /* COMMONHEADERS_H_ */ diff --git a/AudioManagerCore/test/CMakeLists.txt b/AudioManagerCore/test/CMakeLists.txt new file mode 100644 index 0000000..9dd9007 --- /dev/null +++ b/AudioManagerCore/test/CMakeLists.txt @@ -0,0 +1,35 @@ +# 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 +# +# For further information see http://www.genivi.org/. +# + +cmake_minimum_required(VERSION 3.0) + + +set(EXECUTABLE_OUTPUT_PATH ${TEST_EXECUTABLE_OUTPUT_PATH}) + +#make aunt google stop complaining +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNIT_TEST=1 -DDLT_CONTEXT=AudioManager -Wno-unused-local-typedefs -lz -ldl") + +add_subdirectory (AmControlInterfaceTest) +add_subdirectory (AmMapHandlerTest) +add_subdirectory (AmRouterTest) +add_subdirectory (AmRouterMapTest) +add_subdirectory (AmRoutingInterfaceTest) + +IF(WITH_TELNET) + add_subdirectory (AmTelnetServerTest) +ENDIF(WITH_TELNET) + diff --git a/AudioManagerCore/test/IAmCommandBackdoor.h b/AudioManagerCore/test/IAmCommandBackdoor.h new file mode 100644 index 0000000..b7d2b20 --- /dev/null +++ b/AudioManagerCore/test/IAmCommandBackdoor.h @@ -0,0 +1,47 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#ifndef COMMANDINTERFACEBACKDOOR_H_ +#define COMMANDINTERFACEBACKDOOR_H_ + +#include <IAmCommand.h> +#include "CAmCommandSender.h" + +namespace am +{ + +class CAmCommandSender; + +class IAmCommandBackdoor +{ +public: + IAmCommandBackdoor(); + virtual ~IAmCommandBackdoor(); + bool unloadPlugins(CAmCommandSender *CommandSender); + bool injectInterface(CAmCommandSender* CommandSender, IAmCommandSend* CommandSendInterface); +}; + +} + +//definitions are in CAmCommonFunctions.cpp! + +#endif /* COMMANDINTERFACEBACKDOOR_H_ */ diff --git a/AudioManagerCore/test/IAmControlBackdoor.h b/AudioManagerCore/test/IAmControlBackdoor.h new file mode 100644 index 0000000..b5ba3ef --- /dev/null +++ b/AudioManagerCore/test/IAmControlBackdoor.h @@ -0,0 +1,44 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#ifndef CONTROLINTERFACEBACKDOOR_H_ +#define CONTROLINTERFACEBACKDOOR_H_ + +#include "IAmControl.h" +#include "CAmControlSender.h" + +namespace am +{ + +class CAmControlSender; + +class IAmControlBackdoor +{ +public: + IAmControlBackdoor(); + virtual ~IAmControlBackdoor(); + bool replaceController(CAmControlSender *controlSender, IAmControlSend *newController); +}; + +} + +#endif /* CONTROLINTERFACEBACKDOOR_H_ */ diff --git a/AudioManagerCore/test/IAmRoutingBackdoor.h b/AudioManagerCore/test/IAmRoutingBackdoor.h new file mode 100644 index 0000000..cbdb070 --- /dev/null +++ b/AudioManagerCore/test/IAmRoutingBackdoor.h @@ -0,0 +1,46 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#ifndef ROUTINGINTERFACEBACKDOOR_H_ +#define ROUTINGINTERFACEBACKDOOR_H_ + +#include "CAmRoutingSender.h" + +namespace am +{ + +class CAmRoutingSender; + +class IAmRoutingBackdoor +{ +public: + IAmRoutingBackdoor(); + virtual ~IAmRoutingBackdoor(); + bool unloadPlugins(CAmRoutingSender *RoutingSender); + bool injectInterface(CAmRoutingSender *RoutingSender, IAmRoutingSend *newInterface, const std::string& busname); +}; + +} + +//definitions are in CAmCommonFunctions.cpp! + +#endif /* ROUTINGINTERFACEBACKDOOR_H_ */ diff --git a/AudioManagerCore/test/MockIAmCommandSend.h b/AudioManagerCore/test/MockIAmCommandSend.h new file mode 100644 index 0000000..36bc1cb --- /dev/null +++ b/AudioManagerCore/test/MockIAmCommandSend.h @@ -0,0 +1,94 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#ifndef MOCKCOMMANDINTERFACE_H_ +#define MOCKCOMMANDINTERFACE_H_ + +#include "IAmCommand.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +namespace am { + +class MockIAmCommandSend : public IAmCommandSend { + public: + MOCK_CONST_METHOD1(getInterfaceVersion, + void(std::string& version)); + MOCK_METHOD1(startupInterface, + am_Error_e(IAmCommandReceive* commandreceiveinterface)); + MOCK_METHOD1(setCommandReady, + void(const uint16_t handle)); + MOCK_METHOD1(setCommandRundown, + void(const uint16_t handle)); + MOCK_METHOD1(cbNewMainConnection, + void(const am_MainConnectionType_s& mainConnection)); + MOCK_METHOD1(cbRemovedMainConnection, + void(const am_mainConnectionID_t mainConnection)); + MOCK_METHOD1(cbNewSink, + void(const am_SinkType_s& sink)); + MOCK_METHOD1(cbRemovedSink, + void(const am_sinkID_t sinkID)); + MOCK_METHOD1(cbNewSource, + void(const am_SourceType_s& source)); + MOCK_METHOD1(cbRemovedSource, + void(const am_sourceID_t source)); + MOCK_METHOD0(cbNumberOfSinkClassesChanged, + void()); + MOCK_METHOD0(cbNumberOfSourceClassesChanged, + void()); + MOCK_METHOD2(cbMainConnectionStateChanged, + void(const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState)); + MOCK_METHOD2(cbMainSinkSoundPropertyChanged, + void(const am_sinkID_t sinkID, const am_MainSoundProperty_s& soundProperty)); + MOCK_METHOD2(cbMainSourceSoundPropertyChanged, + void(const am_sourceID_t sourceID, const am_MainSoundProperty_s& soundProperty)); + MOCK_METHOD2(cbSinkAvailabilityChanged, + void(const am_sinkID_t sinkID, const am_Availability_s& availability)); + MOCK_METHOD2(cbSourceAvailabilityChanged, + void(const am_sourceID_t sourceID, const am_Availability_s& availability)); + MOCK_METHOD2(cbVolumeChanged, + void(const am_sinkID_t sinkID, const am_mainVolume_t volume)); + MOCK_METHOD2(cbSinkMuteStateChanged, + void(const am_sinkID_t sinkID, const am_MuteState_e muteState)); + MOCK_METHOD1(cbSystemPropertyChanged, + void(const am_SystemProperty_s& systemProperty)); + MOCK_METHOD2(cbTimingInformationChanged, + void(const am_mainConnectionID_t mainConnectionID, const am_timeSync_t time)); + MOCK_METHOD3(cbSinkUpdated, + void(const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties)); + MOCK_METHOD3(cbSourceUpdated, + void(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties)); + MOCK_METHOD2(cbSinkNotification, + void(const am_sinkID_t sinkID, const am_NotificationPayload_s& notification)); + MOCK_METHOD2(cbSourceNotification, + void(const am_sourceID_t sourceID, const am_NotificationPayload_s& notification)); + MOCK_METHOD2(cbMainSinkNotificationConfigurationChanged, + void(const am_sinkID_t sinkID, const am_NotificationConfiguration_s& mainNotificationConfiguration)); + MOCK_METHOD2(cbMainSourceNotificationConfigurationChanged, + void(const am_sourceID_t sourceID, const am_NotificationConfiguration_s& mainNotificationConfiguration)); + + + +}; + +} // namespace am +#endif /* MOCKCOMMANDINTERFACE_H_ */ diff --git a/AudioManagerCore/test/MockIAmControlSend.h b/AudioManagerCore/test/MockIAmControlSend.h new file mode 100644 index 0000000..e628068 --- /dev/null +++ b/AudioManagerCore/test/MockIAmControlSend.h @@ -0,0 +1,160 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#ifndef MOCKCONTROLINTERFACE_H_ +#define MOCKCONTROLINTERFACE_H_ + +#include "IAmControl.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +namespace am { + +class MockIAmControlSend : public IAmControlSend { + public: + MOCK_CONST_METHOD1(getInterfaceVersion, + void(std::string& version)); + MOCK_METHOD1(startupController, + am_Error_e(IAmControlReceive* controlreceiveinterface)); + MOCK_METHOD0(setControllerReady, + void()); + MOCK_METHOD1(setControllerRundown, + void(const int16_t signal)); + MOCK_METHOD3(hookUserConnectionRequest, + am_Error_e(const am_sourceID_t sourceID, const am_sinkID_t sinkID, am_mainConnectionID_t& mainConnectionID)); + MOCK_METHOD1(hookUserDisconnectionRequest, + am_Error_e(const am_mainConnectionID_t connectionID)); + MOCK_METHOD2(hookUserSetMainSinkSoundProperty, + am_Error_e(const am_sinkID_t sinkID, const am_MainSoundProperty_s& soundProperty)); + MOCK_METHOD2(hookUserSetMainSourceSoundProperty, + am_Error_e(const am_sourceID_t sourceID, const am_MainSoundProperty_s& soundProperty)); + MOCK_METHOD1(hookUserSetSystemProperty, + am_Error_e(const am_SystemProperty_s& property)); + MOCK_METHOD2(hookUserVolumeChange, + am_Error_e(const am_sinkID_t SinkID, const am_mainVolume_t newVolume)); + MOCK_METHOD2(hookUserVolumeStep, + am_Error_e(const am_sinkID_t SinkID, const int16_t increment)); + MOCK_METHOD2(hookUserSetSinkMuteState, + am_Error_e(const am_sinkID_t sinkID, const am_MuteState_e muteState)); + MOCK_METHOD2(hookSystemRegisterDomain, + am_Error_e(const am_Domain_s& domainData, am_domainID_t& domainID)); + MOCK_METHOD1(hookSystemDeregisterDomain, + am_Error_e(const am_domainID_t domainID)); + MOCK_METHOD1(hookSystemDomainRegistrationComplete, + void(const am_domainID_t domainID)); + MOCK_METHOD2(hookSystemRegisterSink, + am_Error_e(const am_Sink_s& sinkData, am_sinkID_t& sinkID)); + MOCK_METHOD1(hookSystemDeregisterSink, + am_Error_e(const am_sinkID_t sinkID)); + MOCK_METHOD2(hookSystemRegisterSource, + am_Error_e(const am_Source_s& sourceData, am_sourceID_t& sourceID)); + MOCK_METHOD1(hookSystemDeregisterSource, + am_Error_e(const am_sourceID_t sourceID)); + MOCK_METHOD2(hookSystemRegisterConverter, + am_Error_e(const am_Converter_s& converterData, am_converterID_t& converterID)); + MOCK_METHOD2(hookSystemRegisterGateway, + am_Error_e(const am_Gateway_s& gatewayData, am_gatewayID_t& gatewayID)); + MOCK_METHOD1(hookSystemDeregisterConverter, + am_Error_e(const am_converterID_t converterID)); + MOCK_METHOD1(hookSystemDeregisterGateway, + am_Error_e(const am_gatewayID_t gatewayID)); + MOCK_METHOD2(hookSystemRegisterCrossfader, + am_Error_e(const am_Crossfader_s& crossfaderData, am_crossfaderID_t& crossfaderID)); + MOCK_METHOD1(hookSystemDeregisterCrossfader, + am_Error_e(const am_crossfaderID_t crossfaderID)); + MOCK_METHOD3(hookSystemSinkVolumeTick, + void(const am_Handle_s handle, const am_sinkID_t sinkID, const am_volume_t volume)); + MOCK_METHOD3(hookSystemSourceVolumeTick, + void(const am_Handle_s handle, const am_sourceID_t sourceID, const am_volume_t volume)); + MOCK_METHOD2(hookSystemInterruptStateChange, + void(const am_sourceID_t sourceID, const am_InterruptState_e interruptState)); + MOCK_METHOD2(hookSystemSinkAvailablityStateChange, + void(const am_sinkID_t sinkID, const am_Availability_s& availability)); + MOCK_METHOD2(hookSystemSourceAvailablityStateChange, + void(const am_sourceID_t sourceID, const am_Availability_s& availability)); + MOCK_METHOD2(hookSystemDomainStateChange, + void(const am_domainID_t domainID, const am_DomainState_e state)); + MOCK_METHOD1(hookSystemReceiveEarlyData, + void(const std::vector<am_EarlyData_s>& data)); + MOCK_METHOD1(hookSystemSpeedChange, + void(const am_speed_t speed)); + MOCK_METHOD2(hookSystemTimingInformationChanged, + void(const am_mainConnectionID_t mainConnectionID, const am_timeSync_t time)); + MOCK_METHOD2(cbAckConnect, + void(const am_Handle_s handle, const am_Error_e errorID)); + MOCK_METHOD2(cbAckDisconnect, + void(const am_Handle_s handle, const am_Error_e errorID)); + MOCK_METHOD3(cbAckCrossFade, + void(const am_Handle_s handle, const am_HotSink_e hostsink, const am_Error_e error)); + MOCK_METHOD3(cbAckSetSinkVolumeChange, + void(const am_Handle_s handle, const am_volume_t volume, const am_Error_e error)); + MOCK_METHOD3(cbAckSetSourceVolumeChange, + void(const am_Handle_s handle, const am_volume_t voulme, const am_Error_e error)); + MOCK_METHOD2(cbAckSetSourceState, + void(const am_Handle_s handle, const am_Error_e error)); + MOCK_METHOD2(cbAckSetSourceSoundProperties, + void(const am_Handle_s handle, const am_Error_e error)); + MOCK_METHOD2(cbAckSetSourceSoundProperty, + void(const am_Handle_s handle, const am_Error_e error)); + MOCK_METHOD2(cbAckSetSinkSoundProperties, + void(const am_Handle_s handle, const am_Error_e error)); + MOCK_METHOD2(cbAckSetSinkSoundProperty, + void(const am_Handle_s handle, const am_Error_e error)); + MOCK_METHOD5(getConnectionFormatChoice, + am_Error_e(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)); + MOCK_METHOD1(confirmCommandReady, + void(const am_Error_e error)); + MOCK_METHOD1(confirmRoutingReady, + void(const am_Error_e error)); + MOCK_METHOD1(confirmCommandRundown, + void(const am_Error_e error)); + MOCK_METHOD1(confirmRoutingRundown, + void(const am_Error_e error)); + MOCK_METHOD5(hookSystemUpdateSink, + am_Error_e(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)); + MOCK_METHOD5(hookSystemUpdateSource, + am_Error_e(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)); + MOCK_METHOD4(hookSystemUpdateConverter, + am_Error_e(const am_converterID_t converterID, const std::vector<am_CustomConnectionFormat_t>& listSourceConnectionFormats, const std::vector<am_CustomConnectionFormat_t>& listSinkConnectionFormats, const std::vector<bool>& convertionMatrix)); + MOCK_METHOD4(hookSystemUpdateGateway, + am_Error_e(const am_gatewayID_t gatewayID, const std::vector<am_CustomConnectionFormat_t>& listSourceConnectionFormats, const std::vector<am_CustomConnectionFormat_t>& listSinkConnectionFormats, const std::vector<bool>& convertionMatrix)); + MOCK_METHOD3(cbAckSetVolumes, + void(const am_Handle_s handle, const std::vector<am_Volumes_s>& listVolumes, const am_Error_e error)); + MOCK_METHOD2(cbAckSetSinkNotificationConfiguration, + void(const am_Handle_s handle, const am_Error_e error)); + MOCK_METHOD2(cbAckSetSourceNotificationConfiguration, + void(const am_Handle_s handle, const am_Error_e error)); + MOCK_METHOD2(hookSinkNotificationDataChanged, + void(const am_sinkID_t sinkID, const am_NotificationPayload_s& payload)); + MOCK_METHOD2(hookSourceNotificationDataChanged, + void(const am_sourceID_t sourceID, const am_NotificationPayload_s& payload)); + MOCK_METHOD2(hookUserSetMainSinkNotificationConfiguration, + am_Error_e(const am_sinkID_t sinkID, const am_NotificationConfiguration_s& notificationConfiguration)); + MOCK_METHOD2(hookUserSetMainSourceNotificationConfiguration, + am_Error_e(const am_sourceID_t sourceID, const am_NotificationConfiguration_s& notificationConfiguration)); + MOCK_METHOD2(hookSystemSingleTimingInformationChanged, + void(const am_connectionID_t connectionID, const am_timeSync_t time)); +}; + + +} // namespace am +#endif /* MOCKCONTROLINTERFACE_H_ */ diff --git a/AudioManagerCore/test/MockIAmRoutingSend.h b/AudioManagerCore/test/MockIAmRoutingSend.h new file mode 100644 index 0000000..748e64e --- /dev/null +++ b/AudioManagerCore/test/MockIAmRoutingSend.h @@ -0,0 +1,83 @@ +/** + * 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 + * + * For further information see http://www.genivi.org/. + * + */ + +#ifndef MOCKROUTINGINTERFACE_H_ +#define MOCKROUTINGINTERFACE_H_ + +#include "IAmRouting.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +namespace am { + +class MockIAmRoutingSend : public IAmRoutingSend { + public: + MOCK_CONST_METHOD1(getInterfaceVersion, + void(std::string& version)); + MOCK_METHOD1(startupInterface, + am_Error_e(IAmRoutingReceive* routingreceiveinterface)); + MOCK_METHOD1(setRoutingReady, + void(const uint16_t handle)); + MOCK_METHOD1(setRoutingRundown, + void(const uint16_t handle)); + MOCK_METHOD1(asyncAbort, + am_Error_e(const am_Handle_s handle)); + MOCK_METHOD5(asyncConnect, + am_Error_e(const am_Handle_s handle, const am_connectionID_t connectionID, const am_sourceID_t sourceID, const am_sinkID_t sinkID, const am_CustomAvailabilityReason_t connectionFormat)); + MOCK_METHOD2(asyncDisconnect, + am_Error_e(const am_Handle_s handle, const am_connectionID_t connectionID)); + MOCK_METHOD5(asyncSetSinkVolume, + am_Error_e(const am_Handle_s handle, const am_sinkID_t sinkID, const am_volume_t volume, const am_CustomRampType_t ramp, const am_time_t time)); + MOCK_METHOD5(asyncSetSourceVolume, + am_Error_e(const am_Handle_s handle, const am_sourceID_t sourceID, const am_volume_t volume, const am_CustomRampType_t ramp, const am_time_t time)); + MOCK_METHOD3(asyncSetSourceState, + am_Error_e(const am_Handle_s handle, const am_sourceID_t sourceID, const am_SourceState_e state)); + MOCK_METHOD3(asyncSetSinkSoundProperties, + am_Error_e(const am_Handle_s handle, const am_sinkID_t sinkID, const std::vector<am_SoundProperty_s>& listSoundProperties)); + MOCK_METHOD3(asyncSetSinkSoundProperty, + am_Error_e(const am_Handle_s handle, const am_sinkID_t sinkID, const am_SoundProperty_s& soundProperty)); + MOCK_METHOD3(asyncSetSourceSoundProperties, + am_Error_e(const am_Handle_s handle, const am_sourceID_t sourceID, const std::vector<am_SoundProperty_s>& listSoundProperties)); + MOCK_METHOD3(asyncSetSourceSoundProperty, + am_Error_e(const am_Handle_s handle, const am_sourceID_t sourceID, const am_SoundProperty_s& soundProperty)); + MOCK_METHOD5(asyncCrossFade, + am_Error_e(const am_Handle_s handle, const am_crossfaderID_t crossfaderID, const am_HotSink_e hotSink, const am_CustomRampType_t rampType, const am_time_t time)); + MOCK_METHOD2(setDomainState, + am_Error_e(const am_domainID_t domainID, const am_DomainState_e domainState)); + MOCK_CONST_METHOD1(returnBusName, + am_Error_e(std::string& BusName)); + MOCK_METHOD2(asyncSetVolumes, + am_Error_e(const am_Handle_s handle, const std::vector<am_Volumes_s>& listVolumes)); + MOCK_METHOD3(asyncSetSinkNotificationConfiguration, + am_Error_e(const am_Handle_s handle, const am_sinkID_t sinkID, const am_NotificationConfiguration_s& notificationConfiguration)); + MOCK_METHOD3(asyncSetSourceNotificationConfiguration, + am_Error_e(const am_Handle_s handle, const am_sourceID_t sourceID, const am_NotificationConfiguration_s& notificationConfiguration)); + MOCK_METHOD2(resyncConnectionState, + am_Error_e(const am_domainID_t domainID, std::vector<am_Connection_s>& listOfExistingConnections)); + + +}; + +} // namespace am + + +#endif /* MOCKROUTINGINTERFACE_H_ */ |