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");
119 InterfaceNamePairs routerInterface;
120 routerInterface.routingInterface = router;
124 router->getInterfaceVersion(version);
125 uint16_t minorVersion, majorVersion;
126 std::istringstream(version.substr(0, 1)) >> majorVersion;
127 std::istringstream(version.substr(2, 1)) >> minorVersion;
128 if (majorVersion < REQUIRED_INTERFACE_VERSION_MAJOR || ((majorVersion == REQUIRED_INTERFACE_VERSION_MAJOR) && (minorVersion > REQUIRED_INTERFACE_VERSION_MINOR)))
130 logInfo("RoutingPlugin initialization failed. Version of Interface to old");
134 //here, the busname is saved together with the interface. Later The domains will register with the name and sinks, sources etc with the domain....
135 router->returnBusName(routerInterface.busName);
136 assert(!routerInterface.busName.empty());
137 mListInterfaces.push_back(routerInterface);
138 mListLibraryHandles.push_back(tempLibHandle);
142 CAmRoutingSender::~CAmRoutingSender()
145 HandlesMap::iterator it = mlistActiveHandles.begin();
147 //clean up heap if existent
148 for (; it != mlistActiveHandles.end(); ++it)
150 if (it->first.handleType == H_SETSINKSOUNDPROPERTIES || it->first.handleType == H_SETSOURCESOUNDPROPERTIES)
152 delete it->second.soundProperties;
157 am_Error_e CAmRoutingSender::startupInterfaces(CAmRoutingReceiver *iRoutingReceiver)
159 mpRoutingReceiver = iRoutingReceiver;
160 am_Error_e returnError = E_OK;
162 std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin();
163 std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end();
164 for (; iter < iterEnd; ++iter)
166 am_Error_e error = (*iter).routingInterface->startupInterface(iRoutingReceiver);
172 return (returnError);
175 am_Error_e CAmRoutingSender::asyncAbort(const am_Handle_s& handle)
177 HandleInterfaceMap::iterator iter = mMapHandleInterface.begin();
178 iter = mMapHandleInterface.find(handle.handle);
179 if (iter != mMapHandleInterface.end())
181 return (iter->second->asyncAbort(handle));
184 return (E_NON_EXISTENT);
187 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)
189 am_handleData_c handleData;
190 SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
191 iter = mMapSinkInterface.find(sinkID);
192 if (iter != mMapSinkInterface.end())
194 handleData.connectionID = connectionID;
195 handle = createHandle(handleData, H_CONNECT);
196 mMapConnectionInterface.insert(std::make_pair(connectionID, iter->second));
197 mMapHandleInterface.insert(std::make_pair(handle.handle, iter->second));
198 return (iter->second->asyncConnect(handle, connectionID, sourceID, sinkID, connectionFormat));
201 return (E_NON_EXISTENT);
204 am_Error_e CAmRoutingSender::asyncDisconnect(am_Handle_s& handle, const am_connectionID_t connectionID)
206 am_handleData_c handleData;
207 ConnectionInterfaceMap::iterator iter = mMapConnectionInterface.begin();
208 iter = mMapConnectionInterface.find(connectionID);
209 if (iter != mMapConnectionInterface.end())
211 handleData.connectionID = connectionID;
212 handle = createHandle(handleData, H_DISCONNECT);
213 mMapHandleInterface.insert(std::make_pair(handle.handle, iter->second));
214 am_Error_e returnVal = iter->second->asyncDisconnect(handle, connectionID);
215 mMapConnectionInterface.erase(iter);
219 return (E_NON_EXISTENT);
222 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)
224 am_handleData_c handleData;
225 SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
226 iter = mMapSinkInterface.find(sinkID);
227 if (iter != mMapSinkInterface.end())
229 handleData.sinkID = sinkID;
230 handleData.volume = volume;
231 handle = createHandle(handleData, H_SETSINKVOLUME);
232 mMapHandleInterface.insert(std::make_pair(handle.handle, iter->second));
233 return (iter->second->asyncSetSinkVolume(handle, sinkID, volume, ramp, time));
235 return (E_NON_EXISTENT);
238 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)
240 am_handleData_c handleData;
241 SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
242 iter = mMapSourceInterface.find(sourceID);
243 if (iter != mMapSourceInterface.end())
245 handleData.sourceID = sourceID;
246 handleData.volume = volume;
247 handle = createHandle(handleData, H_SETSOURCEVOLUME);
248 mMapHandleInterface.insert(std::make_pair(handle.handle, iter->second));
249 return (iter->second->asyncSetSourceVolume(handle, sourceID, volume, ramp, time));
251 return (E_NON_EXISTENT);
254 am_Error_e CAmRoutingSender::asyncSetSourceState(am_Handle_s& handle, const am_sourceID_t sourceID, const am_SourceState_e state)
256 am_handleData_c handleData;
257 SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
258 iter = mMapSourceInterface.find(sourceID);
259 if (iter != mMapSourceInterface.end())
261 handleData.sourceID = sourceID;
262 handleData.sourceState = state;
263 handle = createHandle(handleData, H_SETSOURCESTATE);
264 mMapHandleInterface.insert(std::make_pair(handle.handle, iter->second));
265 return (iter->second->asyncSetSourceState(handle, sourceID, state));
267 return (E_NON_EXISTENT);
270 am_Error_e CAmRoutingSender::asyncSetSinkSoundProperty(am_Handle_s& handle, const am_sinkID_t sinkID, const am_SoundProperty_s & soundProperty)
272 am_handleData_c handleData;
273 SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
274 iter = mMapSinkInterface.find(sinkID);
275 if (iter != mMapSinkInterface.end())
277 handleData.sinkID = sinkID;
278 handleData.soundPropery = soundProperty;
279 handle = createHandle(handleData, H_SETSINKSOUNDPROPERTY);
280 mMapHandleInterface.insert(std::make_pair(handle.handle, iter->second));
281 return (iter->second->asyncSetSinkSoundProperty(handle, sinkID, soundProperty));
283 return (E_NON_EXISTENT);
286 am_Error_e CAmRoutingSender::asyncSetSourceSoundProperty(am_Handle_s& handle, const am_sourceID_t sourceID, const am_SoundProperty_s & soundProperty)
288 am_handleData_c handleData;
289 SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
290 iter = mMapSourceInterface.find(sourceID);
291 if (iter != mMapSourceInterface.end())
293 handleData.sourceID = sourceID;
294 handleData.soundPropery = soundProperty;
295 handle = createHandle(handleData, H_SETSOURCESOUNDPROPERTY);
296 mMapHandleInterface.insert(std::make_pair(handle.handle, iter->second));
297 return (iter->second->asyncSetSourceSoundProperty(handle, sourceID, soundProperty));
299 return (E_NON_EXISTENT);
302 am_Error_e CAmRoutingSender::asyncSetSourceSoundProperties(am_Handle_s& handle, const std::vector<am_SoundProperty_s> & listSoundProperties, const am_sourceID_t sourceID)
304 am_handleData_c handleData;
305 SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
306 iter = mMapSourceInterface.find(sourceID);
307 if (iter != mMapSourceInterface.end())
309 handleData.sourceID = sourceID;
310 handleData.soundProperties = new std::vector<am_SoundProperty_s>(listSoundProperties);
311 handle = createHandle(handleData, H_SETSOURCESOUNDPROPERTIES);
312 mMapHandleInterface.insert(std::make_pair(handle.handle, iter->second));
313 return (iter->second->asyncSetSourceSoundProperties(handle, sourceID, listSoundProperties));
315 return (E_NON_EXISTENT);
318 am_Error_e CAmRoutingSender::asyncSetSinkSoundProperties(am_Handle_s& handle, const std::vector<am_SoundProperty_s> & listSoundProperties, const am_sinkID_t sinkID)
320 am_handleData_c handleData;
321 SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
322 iter = mMapSinkInterface.find(sinkID);
323 if (iter != mMapSinkInterface.end())
325 handleData.sinkID = sinkID;
326 handleData.soundProperties = new std::vector<am_SoundProperty_s>(listSoundProperties);
327 handle = createHandle(handleData, H_SETSINKSOUNDPROPERTIES);
328 mMapHandleInterface.insert(std::make_pair(handle.handle, iter->second));
329 return (iter->second->asyncSetSinkSoundProperties(handle, sinkID, listSoundProperties));
331 return (E_NON_EXISTENT);
335 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)
337 am_handleData_c handleData;
338 CrossfaderInterfaceMap::iterator iter = mMapCrossfaderInterface.begin();
339 iter = mMapCrossfaderInterface.find(crossfaderID);
340 if (iter != mMapCrossfaderInterface.end())
342 handleData.crossfaderID = crossfaderID;
343 handleData.hotSink = hotSink;
344 handle = createHandle(handleData, H_CROSSFADE);
345 mMapHandleInterface.insert(std::make_pair(handle.handle, iter->second));
346 return (iter->second->asyncCrossFade(handle, crossfaderID, hotSink, rampType, time));
348 return (E_NON_EXISTENT);
351 am_Error_e CAmRoutingSender::setDomainState(const am_domainID_t domainID, const am_DomainState_e domainState)
353 DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
354 iter = mMapDomainInterface.find(domainID);
355 if (iter != mMapDomainInterface.end())
356 return (iter->second->setDomainState(domainID, domainState));
357 return (E_NON_EXISTENT);
362 * this adds the domain to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface.
363 * This must be done whenever a domain is registered.
365 am_Error_e CAmRoutingSender::addDomainLookup(const am_Domain_s& domainData)
367 std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin();
368 std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end();
369 for (; iter < iterEnd; ++iter)
371 if ((*iter).busName.compare(domainData.busname) == 0)
373 mMapDomainInterface.insert(std::make_pair(domainData.domainID, (*iter).routingInterface));
383 * this adds the Source to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface.
384 * This must be done whenever a Source is registered.
386 am_Error_e CAmRoutingSender::addSourceLookup(const am_Source_s& sourceData)
388 DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
389 iter = mMapDomainInterface.find(sourceData.domainID);
390 if (iter != mMapDomainInterface.end())
392 mMapSourceInterface.insert(std::make_pair(sourceData.sourceID, iter->second));
401 * this adds the Sink to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface.
402 * This must be done whenever a Sink is registered.
404 am_Error_e CAmRoutingSender::addSinkLookup(const am_Sink_s& sinkData)
406 DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
407 iter = mMapDomainInterface.find(sinkData.domainID);
408 if (iter != mMapDomainInterface.end())
410 mMapSinkInterface.insert(std::make_pair(sinkData.sinkID, iter->second));
419 * this adds the Crossfader to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface.
420 * This must be done whenever a Crossfader is registered.
422 am_Error_e CAmRoutingSender::addCrossfaderLookup(const am_Crossfader_s& crossfaderData)
424 DomainInterfaceMap::iterator iter = mMapSourceInterface.begin();
425 iter = mMapSourceInterface.find(crossfaderData.sourceID);
426 if (iter != mMapSourceInterface.end())
428 mMapSourceInterface.insert(std::make_pair(crossfaderData.crossfaderID, iter->second));
437 * this removes the Domain to the lookup table of the Router. This must be done everytime a domain is deregistered.
439 am_Error_e CAmRoutingSender::removeDomainLookup(const am_domainID_t domainID)
441 DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
442 iter = mMapDomainInterface.find(domainID);
443 if (iter != mMapDomainInterface.end())
445 mMapDomainInterface.erase(iter);
449 return (E_NON_EXISTENT);
454 * this removes the Source to the lookup table of the Router. This must be done everytime a source is deregistered.
456 am_Error_e CAmRoutingSender::removeSourceLookup(const am_sourceID_t sourceID)
458 SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
459 iter = mMapSourceInterface.find(sourceID);
460 if (iter != mMapSourceInterface.end())
462 mMapSourceInterface.erase(iter);
466 return (E_NON_EXISTENT);
471 * this removes the Sink to the lookup table of the Router. This must be done everytime a sink is deregistered.
473 am_Error_e CAmRoutingSender::removeSinkLookup(const am_sinkID_t sinkID)
475 SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
476 iter = mMapSinkInterface.find(sinkID);
477 if (iter != mMapSinkInterface.end())
479 mMapSinkInterface.erase(iter);
483 return (E_NON_EXISTENT);
488 * this removes the Crossfader to the lookup table of the Router. This must be done everytime a crossfader is deregistered.
490 am_Error_e CAmRoutingSender::removeCrossfaderLookup(const am_crossfaderID_t crossfaderID)
492 CrossfaderInterfaceMap::iterator iter = mMapCrossfaderInterface.begin();
493 iter = mMapCrossfaderInterface.find(crossfaderID);
494 if (iter != mMapCrossfaderInterface.end())
496 mMapCrossfaderInterface.erase(iter);
500 return (E_NON_EXISTENT);
504 * removes a handle from the list
505 * @param handle to be removed
506 * @return E_OK in case of success
508 am_Error_e CAmRoutingSender::removeHandle(const am_Handle_s& handle)
510 if (mlistActiveHandles.erase(handle))
515 am_Error_e CAmRoutingSender::getListHandles(std::vector<am_Handle_s> & listHandles) const
518 HandlesMap::const_iterator it = mlistActiveHandles.begin();
519 for (; it != mlistActiveHandles.end(); ++it)
521 listHandles.push_back(it->first);
527 * creates a handle and adds it to the list of handles
528 * @param handleData the data that should be saves together with the handle
529 * @param type the type of handle to be created
532 am_Handle_s CAmRoutingSender::createHandle(const am_handleData_c& handleData, const am_Handle_e type)
535 handle.handle = ++mHandleCount; //todo: handle overflows here...
536 handle.handleType = type;
537 mlistActiveHandles.insert(std::make_pair(handle, handleData));
542 * returns the data that belong to handles
543 * @param handle the handle
544 * @return a class holding the handle data
546 CAmRoutingSender::am_handleData_c CAmRoutingSender::returnHandleData(const am_Handle_s handle) const
548 HandlesMap::const_iterator it = mlistActiveHandles.begin();
549 it = mlistActiveHandles.find(handle);
553 void CAmRoutingSender::setRoutingReady()
555 mpRoutingReceiver->waitOnStartup(false);
556 std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin();
557 std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end();
558 for (; iter < iterEnd; ++iter)
560 (*iter).routingInterface->setRoutingReady(mpRoutingReceiver->getStartupHandle());
562 mpRoutingReceiver->waitOnStartup(true);
565 void CAmRoutingSender::setRoutingRundown()
567 mpRoutingReceiver->waitOnRundown(false);
568 std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin();
569 std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end();
570 for (; iter < iterEnd; ++iter)
572 (*iter).routingInterface->setRoutingRundown(mpRoutingReceiver->getStartupHandle());
574 mpRoutingReceiver->waitOnRundown(true);
577 void CAmRoutingSender::unloadLibraries(void)
579 std::vector<void*>::iterator iterator = mListLibraryHandles.begin();
580 for (; iterator < mListLibraryHandles.end(); ++iterator)
584 mListLibraryHandles.clear();
587 am_Error_e CAmRoutingSender::getListPlugins(std::vector<std::string>& interfaces) const
589 std::vector<InterfaceNamePairs>::const_iterator it = mListInterfaces.begin();
590 for (; it != mListInterfaces.end(); ++it)
592 interfaces.push_back(it->busName);
597 void CAmRoutingSender::getInterfaceVersion(std::string & version) const
599 version = RoutingSendVersion;