2 * Copyright (C) 2012, BMW AG
4 * This file is part of GENIVI Project AudioManager.
6 * Contributions are licensed to the GENIVI Alliance under one or more
7 * Contribution License Agreements.
10 * This Source Code Form is subject to the terms of the
11 * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
12 * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 * \author Christian Mueller, christian.ei.mueller@bmw.de BMW 2011,2012
17 * \file CAmCommandSender.cpp
18 * For further information see http://www.genivi.org/.
22 #include "CAmCommandSender.h"
26 #include "CAmCommandReceiver.h"
27 #include "TAmPluginTemplate.h"
28 #include "shared/CAmDltWrapper.h"
33 #define REQUIRED_INTERFACE_VERSION_MAJOR 1 //!< major interface version. All versions smaller than this will be rejected
34 #define REQUIRED_INTERFACE_VERSION_MINOR 0 //!< minor interface version. All versions smaller than this will be rejected
36 * macro to call all interfaces
38 #define CALL_ALL_INTERFACES(...) \
39 std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin(); \
40 std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end(); \
41 for (; iter<iterEnd;++iter) \
43 (*iter)->__VA_ARGS__; \
46 CAmCommandSender::CAmCommandSender(const std::vector<std::string>& listOfPluginDirectories) :
48 mListLibraryHandles(), //
49 mListLibraryNames(), //
52 std::vector<std::string> sharedLibraryNameList;
53 std::vector<std::string>::const_iterator dirIter = listOfPluginDirectories.begin();
54 std::vector<std::string>::const_iterator dirIterEnd = listOfPluginDirectories.end();
56 // search communicator plugins in configured directories
57 for (; dirIter < dirIterEnd; ++dirIter)
59 const char* directoryName = dirIter->c_str();
60 logInfo("Searching for CommandPlugins in", *dirIter);
61 DIR *directory = opendir(directoryName);
65 logError("Error opening directory ", *dirIter);
69 // iterate content of directory
70 struct dirent *itemInDirectory = 0;
71 while ((itemInDirectory = readdir(directory)))
73 unsigned char entryType = itemInDirectory->d_type;
74 std::string entryName = itemInDirectory->d_name;
76 bool regularFile = (entryType == DT_REG || entryType == DT_LNK);
77 bool sharedLibExtension = ("so" == entryName.substr(entryName.find_last_of(".") + 1));
79 if (regularFile && sharedLibExtension)
81 std::string name(directoryName);
82 sharedLibraryNameList.push_back(name + "/" + entryName);
88 // iterate all communicator plugins and start them
89 std::vector<std::string>::iterator iter = sharedLibraryNameList.begin();
90 std::vector<std::string>::iterator iterEnd = sharedLibraryNameList.end();
92 for (; iter < iterEnd; ++iter)
94 logInfo("Loading CommandSender plugin", *iter);
95 IAmCommandSend* (*createFunc)();
96 void* tempLibHandle = NULL;
97 createFunc = getCreateFunction<IAmCommandSend*()>(*iter, tempLibHandle);
101 logInfo("Entry point of CommandPlugin not found", *iter);
105 IAmCommandSend* commander = createFunc();
109 logInfo("CommandPlugin initialization failed. Entry Function not callable");
110 dlclose(tempLibHandle);
116 commander->getInterfaceVersion(version);
117 uint16_t minorVersion, majorVersion;
118 std::istringstream(version.substr(0, 1)) >> majorVersion;
119 std::istringstream(version.substr(2, 1)) >> minorVersion;
121 if (majorVersion < REQUIRED_INTERFACE_VERSION_MAJOR || ((majorVersion == REQUIRED_INTERFACE_VERSION_MAJOR) && (minorVersion > REQUIRED_INTERFACE_VERSION_MINOR)))
123 logInfo("CommandInterface initialization failed. Version of Interface to old");
124 dlclose(tempLibHandle);
128 mListInterfaces.push_back(commander);
129 mListLibraryHandles.push_back(tempLibHandle);
130 mListLibraryNames.push_back(iter->c_str());
134 CAmCommandSender::~CAmCommandSender()
139 am_Error_e CAmCommandSender::startupInterfaces(CAmCommandReceiver *iCommandReceiver)
141 mCommandReceiver = iCommandReceiver;
142 am_Error_e returnError = E_OK;
144 std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin();
145 std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end();
146 for (; iter < iterEnd; ++iter)
148 am_Error_e error = (*iter)->startupInterface(iCommandReceiver);
154 return (returnError);
157 void CAmCommandSender::cbNumberOfSinkClassesChanged()
159 CALL_ALL_INTERFACES(cbNumberOfSinkClassesChanged())
162 void CAmCommandSender::cbNumberOfSourceClassesChanged()
164 CALL_ALL_INTERFACES(cbNumberOfSourceClassesChanged())
167 void CAmCommandSender::cbMainConnectionStateChanged(const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState)
169 CALL_ALL_INTERFACES(cbMainConnectionStateChanged(connectionID,connectionState))
172 void CAmCommandSender::cbMainSinkSoundPropertyChanged(const am_sinkID_t sinkID, const am_MainSoundProperty_s& SoundProperty)
174 CALL_ALL_INTERFACES(cbMainSinkSoundPropertyChanged(sinkID,SoundProperty))
177 void CAmCommandSender::cbMainSourceSoundPropertyChanged(const am_sourceID_t sourceID, const am_MainSoundProperty_s& SoundProperty)
179 CALL_ALL_INTERFACES(cbMainSourceSoundPropertyChanged(sourceID,SoundProperty))
182 void CAmCommandSender::cbSinkAvailabilityChanged(const am_sinkID_t sinkID, const am_Availability_s & availability)
184 CALL_ALL_INTERFACES(cbSinkAvailabilityChanged(sinkID,availability))
187 void CAmCommandSender::cbSourceAvailabilityChanged(const am_sourceID_t sourceID, const am_Availability_s & availability)
189 CALL_ALL_INTERFACES(cbSourceAvailabilityChanged(sourceID,availability))
192 void CAmCommandSender::cbVolumeChanged(const am_sinkID_t sinkID, const am_mainVolume_t volume)
194 CALL_ALL_INTERFACES(cbVolumeChanged(sinkID,volume))
197 void CAmCommandSender::cbSinkMuteStateChanged(const am_sinkID_t sinkID, const am_MuteState_e muteState)
199 CALL_ALL_INTERFACES(cbSinkMuteStateChanged(sinkID,muteState))
202 void CAmCommandSender::cbSystemPropertyChanged(const am_SystemProperty_s & SystemProperty)
204 CALL_ALL_INTERFACES(cbSystemPropertyChanged(SystemProperty))
207 void CAmCommandSender::cbTimingInformationChanged(const am_mainConnectionID_t mainConnection, const am_timeSync_t time)
209 CALL_ALL_INTERFACES(cbTimingInformationChanged(mainConnection,time))
212 void CAmCommandSender::cbNewMainConnection(const am_MainConnectionType_s mainConnection)
214 CALL_ALL_INTERFACES(cbNewMainConnection(mainConnection))
217 void CAmCommandSender::cbRemovedMainConnection(const am_mainConnectionID_t mainConnection)
219 CALL_ALL_INTERFACES(cbRemovedMainConnection(mainConnection))
222 void CAmCommandSender::cbNewSink(const am_SinkType_s sink)
224 CALL_ALL_INTERFACES(cbNewSink(sink))
227 void CAmCommandSender::cbRemovedSink(const am_sinkID_t sink)
229 CALL_ALL_INTERFACES(cbRemovedSink(sink))
232 void CAmCommandSender::cbNewSource(const am_SourceType_s source)
234 CALL_ALL_INTERFACES(cbNewSource(source))
237 void CAmCommandSender::cbRemovedSource(const am_sourceID_t source)
239 CALL_ALL_INTERFACES(cbRemovedSource(source))
242 void CAmCommandSender::setCommandReady()
244 mCommandReceiver->waitOnStartup(false);
246 //create a list of handles
247 std::vector<uint16_t> listStartupHandles;
248 for (size_t i = 0; i < mListInterfaces.size(); i++)
250 listStartupHandles.push_back(mCommandReceiver->getStartupHandle());
253 //set the receiver ready to wait for replies
254 mCommandReceiver->waitOnStartup(true);
257 std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin();
258 std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end();
259 std::vector<uint16_t>::const_iterator handleIter(listStartupHandles.begin());
260 for (; iter < iterEnd; ++iter)
262 (*iter)->setCommandReady(*(handleIter++));
266 void CAmCommandSender::setCommandRundown()
268 mCommandReceiver->waitOnRundown(false);
269 //create a list of handles
270 std::vector<uint16_t> listStartupHandles;
271 for (size_t i = 0; i < mListInterfaces.size(); i++)
273 listStartupHandles.push_back(mCommandReceiver->getRundownHandle());
276 //set the receiver ready to wait for replies
277 mCommandReceiver->waitOnRundown(true);
280 std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin();
281 std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end();
282 std::vector<uint16_t>::const_iterator handleIter(listStartupHandles.begin());
283 for (; iter < iterEnd; ++iter)
285 (*iter)->setCommandRundown(*(handleIter++));
289 void CAmCommandSender::getInterfaceVersion(std::string & version) const
291 version = CommandSendVersion;
294 am_Error_e am::CAmCommandSender::getListPlugins(std::vector<std::string> & interfaces) const
296 interfaces = mListLibraryNames;
300 void CAmCommandSender::cbSinkUpdated(const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties)
302 CALL_ALL_INTERFACES(cbSinkUpdated(sinkID,sinkClassID,listMainSoundProperties));
305 void CAmCommandSender::cbSourceUpdated(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties)
307 CALL_ALL_INTERFACES(cbSourceUpdated(sourceID,sourceClassID,listMainSoundProperties));
310 void CAmCommandSender::cbSinkNotification(const am_sinkID_t sinkID, const am_NotificationPayload_s& notification)
312 CALL_ALL_INTERFACES(cbSinkNotification(sinkID,notification));
315 void CAmCommandSender::cbSourceNotification(const am_sourceID_t sourceID, const am_NotificationPayload_s& notification)
317 CALL_ALL_INTERFACES(cbSourceNotification(sourceID,notification));
320 void CAmCommandSender::cbSinkMainNotificationConfigurationChanged(const am_sinkID_t sinkID, const am_NotificationConfiguration_s& mainNotificationConfiguration)
322 CALL_ALL_INTERFACES(cbMainSinkNotificationConfigurationChanged(sinkID,mainNotificationConfiguration));
325 void CAmCommandSender::cbSourceMainNotificationConfigurationChanged(const am_sourceID_t sourceID, const am_NotificationConfiguration_s& mainNotificationConfiguration)
327 CALL_ALL_INTERFACES(cbMainSourceNotificationConfigurationChanged(sourceID,mainNotificationConfiguration));
330 void CAmCommandSender::unloadLibraries(void)
332 std::vector<void*>::iterator iterator = mListLibraryHandles.begin();
333 for (; iterator < mListLibraryHandles.end(); ++iterator)
337 mListLibraryHandles.clear();