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 CAmRoutingSender.cpp
18 * For further information see http://www.genivi.org/.
22 #include "CAmRoutingSender.h"
29 #include "CAmRoutingReceiver.h"
30 #include "TAmPluginTemplate.h"
31 #include "shared/CAmDltWrapper.h"
36 #define REQUIRED_INTERFACE_VERSION_MAJOR 1 //!< major interface version. All versions smaller than this will be rejected
37 #define REQUIRED_INTERFACE_VERSION_MINOR 0 //!< minor interface version. All versions smaller than this will be rejected
39 CAmRoutingSender::CAmRoutingSender(const std::vector<std::string>& listOfPluginDirectories) :
41 mlistActiveHandles(), //
43 mMapConnectionInterface(), //
44 mMapCrossfaderInterface(), //
45 mMapDomainInterface(), //
46 mMapSinkInterface(), //
47 mMapSourceInterface(), //
48 mMapHandleInterface(), //
51 std::vector<std::string> sharedLibraryNameList;
52 std::vector<std::string>::const_iterator dirIter = listOfPluginDirectories.begin();
53 std::vector<std::string>::const_iterator dirIterEnd = listOfPluginDirectories.end();
55 // search communicator plugins in configured directories
56 for (; dirIter < dirIterEnd; ++dirIter)
58 const char* directoryName = dirIter->c_str();
59 logInfo("Searching for HookPlugins in", directoryName);
60 DIR *directory = opendir(directoryName);
64 logError("RoutingSender::RoutingSender Error opening directory: ", directoryName);
68 // iterate content of directory
69 struct dirent *itemInDirectory = 0;
70 while ((itemInDirectory = readdir(directory)))
72 unsigned char entryType = itemInDirectory->d_type;
73 std::string entryName = itemInDirectory->d_name;
75 bool regularFile = (entryType == DT_REG || entryType == DT_LNK);
76 bool sharedLibExtension = ("so" == entryName.substr(entryName.find_last_of(".") + 1));
78 if (regularFile && sharedLibExtension)
80 logInfo("RoutingSender::RoutingSender adding file: ", entryName);
81 std::string name(directoryName);
82 sharedLibraryNameList.push_back(name + "/" + entryName);
86 logInfo("RoutingSender::RoutingSender PluginSearch ignoring file :", entryName);
93 // iterate all communicator plugins and start them
94 std::vector<std::string>::iterator iter = sharedLibraryNameList.begin();
95 std::vector<std::string>::iterator iterEnd = sharedLibraryNameList.end();
97 for (; iter != iterEnd; ++iter)
99 logInfo("RoutingSender::RoutingSender try loading: ", *iter);
101 IAmRoutingSend* (*createFunc)();
102 void* tempLibHandle = NULL;
103 createFunc = getCreateFunction<IAmRoutingSend*()>(*iter, tempLibHandle);
107 logError("RoutingSender::RoutingSender Entry point of RoutingPlugin not found");
111 IAmRoutingSend* router = createFunc();
115 logError("RoutingSender::RoutingSender RoutingPlugin initialization failed. Entry Function not callable");
116 dlclose(tempLibHandle);
120 InterfaceNamePairs routerInterface;
121 routerInterface.routingInterface = router;
125 router->getInterfaceVersion(version);
126 uint16_t minorVersion, majorVersion;
127 std::istringstream(version.substr(0, 1)) >> majorVersion;
128 std::istringstream(version.substr(2, 1)) >> minorVersion;
129 if (majorVersion < REQUIRED_INTERFACE_VERSION_MAJOR || ((majorVersion == REQUIRED_INTERFACE_VERSION_MAJOR) && (minorVersion > REQUIRED_INTERFACE_VERSION_MINOR)))
131 logInfo("RoutingPlugin initialization failed. Version of Interface to old");
132 dlclose(tempLibHandle);
136 //here, the busname is saved together with the interface. Later The domains will register with the name and sinks, sources etc with the domain....
137 router->returnBusName(routerInterface.busName);
138 assert(!routerInterface.busName.empty());
139 mListInterfaces.push_back(routerInterface);
140 mListLibraryHandles.push_back(tempLibHandle);
144 CAmRoutingSender::~CAmRoutingSender()
147 HandlesMap::iterator it = mlistActiveHandles.begin();
149 //clean up heap if existent
150 for (; it != mlistActiveHandles.end(); ++it)
152 if (it->first.handleType == H_SETSINKSOUNDPROPERTIES || it->first.handleType == H_SETSOURCESOUNDPROPERTIES)
154 delete it->second.soundProperties;
159 am_Error_e CAmRoutingSender::startupInterfaces(CAmRoutingReceiver *iRoutingReceiver)
161 mpRoutingReceiver = iRoutingReceiver;
162 am_Error_e returnError = E_OK;
164 std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin();
165 std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end();
166 for (; iter < iterEnd; ++iter)
168 am_Error_e error = (*iter).routingInterface->startupInterface(iRoutingReceiver);
174 return (returnError);
177 am_Error_e CAmRoutingSender::asyncAbort(const am_Handle_s& handle)
179 HandleInterfaceMap::iterator iter = mMapHandleInterface.begin();
180 iter = mMapHandleInterface.find(handle.handle);
181 if (iter != mMapHandleInterface.end())
183 return (iter->second->asyncAbort(handle));
186 return (E_NON_EXISTENT);
189 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_ConnectionFormat_e connectionFormat)
191 am_handleData_c handleData;
192 SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
193 iter = mMapSinkInterface.find(sinkID);
194 if (iter != mMapSinkInterface.end())
196 handleData.connectionID = connectionID;
197 handle = createHandle(handleData, H_CONNECT);
198 mMapConnectionInterface.insert(std::make_pair(connectionID, iter->second));
199 mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
200 return (iter->second->asyncConnect(handle, connectionID, sourceID, sinkID, connectionFormat));
203 return (E_NON_EXISTENT);
206 am_Error_e CAmRoutingSender::asyncDisconnect(am_Handle_s& handle, const am_connectionID_t connectionID)
208 am_handleData_c handleData;
209 ConnectionInterfaceMap::iterator iter = mMapConnectionInterface.begin();
210 iter = mMapConnectionInterface.find(connectionID);
211 if (iter != mMapConnectionInterface.end())
213 handleData.connectionID = connectionID;
214 handle = createHandle(handleData, H_DISCONNECT);
215 mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
216 am_Error_e returnVal = iter->second->asyncDisconnect(handle, connectionID);
217 mMapConnectionInterface.erase(iter);
221 return (E_NON_EXISTENT);
224 am_Error_e CAmRoutingSender::asyncSetSinkVolume(am_Handle_s& handle, const am_sinkID_t sinkID, const am_volume_t volume, const am_RampType_e ramp, const am_time_t time)
226 am_handleData_c handleData;
227 SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
228 iter = mMapSinkInterface.find(sinkID);
229 if (iter != mMapSinkInterface.end())
231 handleData.sinkID = sinkID;
232 handleData.volume = volume;
233 handle = createHandle(handleData, H_SETSINKVOLUME);
234 mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
235 return (iter->second->asyncSetSinkVolume(handle, sinkID, volume, ramp, time));
237 return (E_NON_EXISTENT);
240 am_Error_e CAmRoutingSender::asyncSetSourceVolume(am_Handle_s& handle, const am_sourceID_t sourceID, const am_volume_t volume, const am_RampType_e ramp, const am_time_t time)
242 am_handleData_c handleData;
243 SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
244 iter = mMapSourceInterface.find(sourceID);
245 if (iter != mMapSourceInterface.end())
247 handleData.sourceID = sourceID;
248 handleData.volume = volume;
249 handle = createHandle(handleData, H_SETSOURCEVOLUME);
250 mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
251 return (iter->second->asyncSetSourceVolume(handle, sourceID, volume, ramp, time));
253 return (E_NON_EXISTENT);
256 am_Error_e CAmRoutingSender::asyncSetSourceState(am_Handle_s& handle, const am_sourceID_t sourceID, const am_SourceState_e state)
258 am_handleData_c handleData;
259 SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
260 iter = mMapSourceInterface.find(sourceID);
261 if (iter != mMapSourceInterface.end())
263 handleData.sourceID = sourceID;
264 handleData.sourceState = state;
265 handle = createHandle(handleData, H_SETSOURCESTATE);
266 mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
267 return (iter->second->asyncSetSourceState(handle, sourceID, state));
269 return (E_NON_EXISTENT);
272 am_Error_e CAmRoutingSender::asyncSetSinkSoundProperty(am_Handle_s& handle, const am_sinkID_t sinkID, const am_SoundProperty_s & soundProperty)
274 am_handleData_c handleData;
275 SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
276 iter = mMapSinkInterface.find(sinkID);
277 if (iter != mMapSinkInterface.end())
279 handleData.sinkID = sinkID;
280 handleData.soundPropery = soundProperty;
281 handle = createHandle(handleData, H_SETSINKSOUNDPROPERTY);
282 mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
283 return (iter->second->asyncSetSinkSoundProperty(handle, sinkID, soundProperty));
285 return (E_NON_EXISTENT);
288 am_Error_e CAmRoutingSender::asyncSetSourceSoundProperty(am_Handle_s& handle, const am_sourceID_t sourceID, const am_SoundProperty_s & soundProperty)
290 am_handleData_c handleData;
291 SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
292 iter = mMapSourceInterface.find(sourceID);
293 if (iter != mMapSourceInterface.end())
295 handleData.sourceID = sourceID;
296 handleData.soundPropery = soundProperty;
297 handle = createHandle(handleData, H_SETSOURCESOUNDPROPERTY);
298 mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
299 return (iter->second->asyncSetSourceSoundProperty(handle, sourceID, soundProperty));
301 return (E_NON_EXISTENT);
304 am_Error_e CAmRoutingSender::asyncSetSourceSoundProperties(am_Handle_s& handle, const std::vector<am_SoundProperty_s> & listSoundProperties, const am_sourceID_t sourceID)
306 am_handleData_c handleData;
307 SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
308 iter = mMapSourceInterface.find(sourceID);
309 if (iter != mMapSourceInterface.end())
311 handleData.sourceID = sourceID;
312 handleData.soundProperties = new std::vector<am_SoundProperty_s>(listSoundProperties);
313 handle = createHandle(handleData, H_SETSOURCESOUNDPROPERTIES);
314 mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
315 return (iter->second->asyncSetSourceSoundProperties(handle, sourceID, listSoundProperties));
317 return (E_NON_EXISTENT);
320 am_Error_e CAmRoutingSender::asyncSetSinkSoundProperties(am_Handle_s& handle, const std::vector<am_SoundProperty_s> & listSoundProperties, const am_sinkID_t sinkID)
322 am_handleData_c handleData;
323 SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
324 iter = mMapSinkInterface.find(sinkID);
325 if (iter != mMapSinkInterface.end())
327 handleData.sinkID = sinkID;
328 handleData.soundProperties = new std::vector<am_SoundProperty_s>(listSoundProperties);
329 handle = createHandle(handleData, H_SETSINKSOUNDPROPERTIES);
330 mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
331 return (iter->second->asyncSetSinkSoundProperties(handle, sinkID, listSoundProperties));
333 return (E_NON_EXISTENT);
337 am_Error_e CAmRoutingSender::asyncCrossFade(am_Handle_s& handle, const am_crossfaderID_t crossfaderID, const am_HotSink_e hotSink, const am_RampType_e rampType, const am_time_t time)
339 am_handleData_c handleData;
340 CrossfaderInterfaceMap::iterator iter = mMapCrossfaderInterface.begin();
341 iter = mMapCrossfaderInterface.find(crossfaderID);
342 if (iter != mMapCrossfaderInterface.end())
344 handleData.crossfaderID = crossfaderID;
345 handleData.hotSink = hotSink;
346 handle = createHandle(handleData, H_CROSSFADE);
347 mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
348 return (iter->second->asyncCrossFade(handle, crossfaderID, hotSink, rampType, time));
350 return (E_NON_EXISTENT);
353 am_Error_e CAmRoutingSender::setDomainState(const am_domainID_t domainID, const am_DomainState_e domainState)
355 DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
356 iter = mMapDomainInterface.find(domainID);
357 if (iter != mMapDomainInterface.end())
358 return (iter->second->setDomainState(domainID, domainState));
359 return (E_NON_EXISTENT);
364 * this adds the domain to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface.
365 * This must be done whenever a domain is registered.
367 am_Error_e CAmRoutingSender::addDomainLookup(const am_Domain_s& domainData)
369 std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin();
370 std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end();
371 for (; iter < iterEnd; ++iter)
373 if ((*iter).busName.compare(domainData.busname) == 0)
375 mMapDomainInterface.insert(std::make_pair(domainData.domainID, (*iter).routingInterface));
385 * this adds the Source to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface.
386 * This must be done whenever a Source is registered.
388 am_Error_e CAmRoutingSender::addSourceLookup(const am_Source_s& sourceData)
390 DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
391 iter = mMapDomainInterface.find(sourceData.domainID);
392 if (iter != mMapDomainInterface.end())
394 mMapSourceInterface.insert(std::make_pair(sourceData.sourceID, iter->second));
403 * this adds the Sink to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface.
404 * This must be done whenever a Sink is registered.
406 am_Error_e CAmRoutingSender::addSinkLookup(const am_Sink_s& sinkData)
408 DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
409 iter = mMapDomainInterface.find(sinkData.domainID);
410 if (iter != mMapDomainInterface.end())
412 mMapSinkInterface.insert(std::make_pair(sinkData.sinkID, iter->second));
421 * this adds the Crossfader to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface.
422 * This must be done whenever a Crossfader is registered.
424 am_Error_e CAmRoutingSender::addCrossfaderLookup(const am_Crossfader_s& crossfaderData)
426 DomainInterfaceMap::iterator iter = mMapSourceInterface.begin();
427 iter = mMapSourceInterface.find(crossfaderData.sourceID);
428 if (iter != mMapSourceInterface.end())
430 mMapSourceInterface.insert(std::make_pair(crossfaderData.crossfaderID, iter->second));
439 * this removes the Domain to the lookup table of the Router. This must be done everytime a domain is deregistered.
441 am_Error_e CAmRoutingSender::removeDomainLookup(const am_domainID_t domainID)
443 DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
444 iter = mMapDomainInterface.find(domainID);
445 if (iter != mMapDomainInterface.end())
447 mMapDomainInterface.erase(iter);
451 return (E_NON_EXISTENT);
456 * this removes the Source to the lookup table of the Router. This must be done everytime a source is deregistered.
458 am_Error_e CAmRoutingSender::removeSourceLookup(const am_sourceID_t sourceID)
460 SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
461 iter = mMapSourceInterface.find(sourceID);
462 if (iter != mMapSourceInterface.end())
464 mMapSourceInterface.erase(iter);
468 return (E_NON_EXISTENT);
473 * this removes the Sink to the lookup table of the Router. This must be done everytime a sink is deregistered.
475 am_Error_e CAmRoutingSender::removeSinkLookup(const am_sinkID_t sinkID)
477 SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
478 iter = mMapSinkInterface.find(sinkID);
479 if (iter != mMapSinkInterface.end())
481 mMapSinkInterface.erase(iter);
485 return (E_NON_EXISTENT);
490 * this removes the Crossfader to the lookup table of the Router. This must be done everytime a crossfader is deregistered.
492 am_Error_e CAmRoutingSender::removeCrossfaderLookup(const am_crossfaderID_t crossfaderID)
494 CrossfaderInterfaceMap::iterator iter = mMapCrossfaderInterface.begin();
495 iter = mMapCrossfaderInterface.find(crossfaderID);
496 if (iter != mMapCrossfaderInterface.end())
498 mMapCrossfaderInterface.erase(iter);
502 return (E_NON_EXISTENT);
506 * removes a handle from the list
507 * @param handle to be removed
508 * @return E_OK in case of success
510 am_Error_e CAmRoutingSender::removeHandle(const am_Handle_s& handle)
512 if (mlistActiveHandles.erase(handle))
517 am_Error_e CAmRoutingSender::getListHandles(std::vector<am_Handle_s> & listHandles) const
520 HandlesMap::const_iterator it = mlistActiveHandles.begin();
521 for (; it != mlistActiveHandles.end(); ++it)
523 listHandles.push_back(it->first);
529 * creates a handle and adds it to the list of handles
530 * @param handleData the data that should be saves together with the handle
531 * @param type the type of handle to be created
534 am_Handle_s CAmRoutingSender::createHandle(const am_handleData_c& handleData, const am_Handle_e type)
537 handle.handle = ++mHandleCount; //todo: handle overflows here...
538 handle.handleType = type;
539 mlistActiveHandles.insert(std::make_pair(handle, handleData));
544 * returns the data that belong to handles
545 * @param handle the handle
546 * @return a class holding the handle data
548 CAmRoutingSender::am_handleData_c CAmRoutingSender::returnHandleData(const am_Handle_s handle) const
550 HandlesMap::const_iterator it = mlistActiveHandles.begin();
551 it = mlistActiveHandles.find(handle);
555 void CAmRoutingSender::setRoutingReady()
557 mpRoutingReceiver->waitOnStartup(false);
559 //create a list of handles
560 std::vector<uint16_t> listStartupHandles;
561 for (size_t i = 0; i <= mListInterfaces.size(); i++)
563 listStartupHandles.push_back(mpRoutingReceiver->getStartupHandle());
566 //set the receiver ready to wait for replies
567 mpRoutingReceiver->waitOnStartup(true);
569 std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin();
570 std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end();
571 std::vector<uint16_t>::const_iterator handleIter(listStartupHandles.begin());
572 for (; iter < iterEnd; ++iter)
574 (*iter).routingInterface->setRoutingReady(*(handleIter++));
578 void CAmRoutingSender::setRoutingRundown()
580 mpRoutingReceiver->waitOnRundown(false);
581 //create a list of handles
582 std::vector<uint16_t> listStartupHandles;
583 for (size_t i = 0; i <= mListInterfaces.size(); i++)
585 listStartupHandles.push_back(mpRoutingReceiver->getRundownHandle());
588 //set the receiver ready to wait for replies
589 mpRoutingReceiver->waitOnRundown(true);
591 std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin();
592 std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end();
593 std::vector<uint16_t>::const_iterator handleIter(listStartupHandles.begin());
594 for (; iter < iterEnd; ++iter)
596 (*iter).routingInterface->setRoutingRundown(*(handleIter++));
600 void CAmRoutingSender::unloadLibraries(void)
602 std::vector<void*>::iterator iterator = mListLibraryHandles.begin();
603 for (; iterator < mListLibraryHandles.end(); ++iterator)
607 mListLibraryHandles.clear();
610 am_Error_e CAmRoutingSender::getListPlugins(std::vector<std::string>& interfaces) const
612 std::vector<InterfaceNamePairs>::const_iterator it = mListInterfaces.begin();
613 for (; it != mListInterfaces.end(); ++it)
615 interfaces.push_back(it->busName);
620 void CAmRoutingSender::getInterfaceVersion(std::string & version) const
622 version = RoutingSendVersion;