* [GAM-74] resolving issues found by coverity scan
[profile/ivi/genivi/genivi-audio-manager.git] / AudioManagerDaemon / src / CAmRoutingSender.cpp
1 /**
2  * Copyright (C) 2012, BMW AG
3  *
4  * This file is part of GENIVI Project AudioManager.
5  *
6  * Contributions are licensed to the GENIVI Alliance under one or more
7  * Contribution License Agreements.
8  *
9  * \copyright
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/.
13  *
14  *
15  * \author Christian Mueller, christian.ei.mueller@bmw.de BMW 2011,2012
16  *
17  * \file CAmRoutingSender.cpp
18  * For further information see http://www.genivi.org/.
19  *
20  */
21
22 #include "CAmRoutingSender.h"
23 #include <utility>
24 #include <dirent.h>
25 #include <dlfcn.h>
26 #include <cassert>
27 #include <iostream>
28 #include <sstream>
29 #include "CAmRoutingReceiver.h"
30 #include "TAmPluginTemplate.h"
31 #include "shared/CAmDltWrapper.h"
32
33 namespace am
34 {
35
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
38
39 CAmRoutingSender::CAmRoutingSender(const std::vector<std::string>& listOfPluginDirectories) :
40         mHandleCount(0), //
41         mlistActiveHandles(), //
42         mListInterfaces(), //
43         mMapConnectionInterface(), //
44         mMapCrossfaderInterface(), //
45         mMapDomainInterface(), //
46         mMapSinkInterface(), //
47         mMapSourceInterface(), //
48         mMapHandleInterface(), //
49         mpRoutingReceiver()
50 {
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();
54
55     // search communicator plugins in configured directories
56     for (; dirIter < dirIterEnd; ++dirIter)
57     {
58         const char* directoryName = dirIter->c_str();
59         logInfo("Searching for HookPlugins in", directoryName);
60         DIR *directory = opendir(directoryName);
61
62         if (!directory)
63         {
64             logError("RoutingSender::RoutingSender Error opening directory: ", directoryName);
65             continue;
66         }
67
68         // iterate content of directory
69         struct dirent *itemInDirectory = 0;
70         while ((itemInDirectory = readdir(directory)))
71         {
72             unsigned char entryType = itemInDirectory->d_type;
73             std::string entryName = itemInDirectory->d_name;
74
75             bool regularFile = (entryType == DT_REG || entryType == DT_LNK);
76             bool sharedLibExtension = ("so" == entryName.substr(entryName.find_last_of(".") + 1));
77
78             if (regularFile && sharedLibExtension)
79             {
80                 logInfo("RoutingSender::RoutingSender adding file: ", entryName);
81                 std::string name(directoryName);
82                 sharedLibraryNameList.push_back(name + "/" + entryName);
83             }
84             else
85             {
86                 logInfo("RoutingSender::RoutingSender PluginSearch ignoring file :", entryName);
87             }
88         }
89
90         closedir(directory);
91     }
92
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();
96
97     for (; iter != iterEnd; ++iter)
98     {
99         logInfo("RoutingSender::RoutingSender try loading: ", *iter);
100
101         IAmRoutingSend* (*createFunc)();
102         void* tempLibHandle = NULL;
103         createFunc = getCreateFunction<IAmRoutingSend*()>(*iter, tempLibHandle);
104
105         if (!createFunc)
106         {
107             logError("RoutingSender::RoutingSender Entry point of RoutingPlugin not found");
108             continue;
109         }
110
111         IAmRoutingSend* router = createFunc();
112
113         if (!router)
114         {
115             logError("RoutingSender::RoutingSender RoutingPlugin initialization failed. Entry Function not callable");
116             dlclose(tempLibHandle);
117             continue;
118         }
119
120         InterfaceNamePairs routerInterface;
121         routerInterface.routingInterface = router;
122
123         //check libversion
124         std::string version;
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)))
130         {
131             logInfo("RoutingPlugin initialization failed. Version of Interface to old");
132             dlclose(tempLibHandle);
133             continue;
134         }
135
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);
141     }
142 }
143
144 CAmRoutingSender::~CAmRoutingSender()
145 {
146     unloadLibraries();
147     HandlesMap::iterator it = mlistActiveHandles.begin();
148
149     //clean up heap if existent
150     for (; it != mlistActiveHandles.end(); ++it)
151     {
152         if (it->first.handleType == H_SETSINKSOUNDPROPERTIES || it->first.handleType == H_SETSOURCESOUNDPROPERTIES)
153         {
154             delete it->second.soundProperties;
155         }
156     }
157 }
158
159 am_Error_e CAmRoutingSender::startupInterfaces(CAmRoutingReceiver *iRoutingReceiver)
160 {
161     mpRoutingReceiver = iRoutingReceiver;
162     am_Error_e returnError = E_OK;
163
164     std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin();
165     std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end();
166     for (; iter < iterEnd; ++iter)
167     {
168         am_Error_e error = (*iter).routingInterface->startupInterface(iRoutingReceiver);
169         if (error != E_OK)
170         {
171             returnError = error;
172         }
173     }
174     return (returnError);
175 }
176
177 am_Error_e CAmRoutingSender::asyncAbort(const am_Handle_s& handle)
178 {
179     HandleInterfaceMap::iterator iter = mMapHandleInterface.begin();
180     iter = mMapHandleInterface.find(handle.handle);
181     if (iter != mMapHandleInterface.end())
182     {
183         return (iter->second->asyncAbort(handle));
184     }
185
186     return (E_NON_EXISTENT);
187 }
188
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)
190 {
191     am_handleData_c handleData;
192     SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
193     iter = mMapSinkInterface.find(sinkID);
194     if (iter != mMapSinkInterface.end())
195     {
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));
201     }
202
203     return (E_NON_EXISTENT);
204 }
205
206 am_Error_e CAmRoutingSender::asyncDisconnect(am_Handle_s& handle, const am_connectionID_t connectionID)
207 {
208     am_handleData_c handleData;
209     ConnectionInterfaceMap::iterator iter = mMapConnectionInterface.begin();
210     iter = mMapConnectionInterface.find(connectionID);
211     if (iter != mMapConnectionInterface.end())
212     {
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);
218         return (returnVal);
219     }
220
221     return (E_NON_EXISTENT);
222 }
223
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)
225 {
226     am_handleData_c handleData;
227     SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
228     iter = mMapSinkInterface.find(sinkID);
229     if (iter != mMapSinkInterface.end())
230     {
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));
236     }
237     return (E_NON_EXISTENT);
238 }
239
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)
241 {
242     am_handleData_c handleData;
243     SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
244     iter = mMapSourceInterface.find(sourceID);
245     if (iter != mMapSourceInterface.end())
246     {
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));
252     }
253     return (E_NON_EXISTENT);
254 }
255
256 am_Error_e CAmRoutingSender::asyncSetSourceState(am_Handle_s& handle, const am_sourceID_t sourceID, const am_SourceState_e state)
257 {
258     am_handleData_c handleData;
259     SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
260     iter = mMapSourceInterface.find(sourceID);
261     if (iter != mMapSourceInterface.end())
262     {
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));
268     }
269     return (E_NON_EXISTENT);
270 }
271
272 am_Error_e CAmRoutingSender::asyncSetSinkSoundProperty(am_Handle_s& handle, const am_sinkID_t sinkID, const am_SoundProperty_s & soundProperty)
273 {
274     am_handleData_c handleData;
275     SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
276     iter = mMapSinkInterface.find(sinkID);
277     if (iter != mMapSinkInterface.end())
278     {
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));
284     }
285     return (E_NON_EXISTENT);
286 }
287
288 am_Error_e CAmRoutingSender::asyncSetSourceSoundProperty(am_Handle_s& handle, const am_sourceID_t sourceID, const am_SoundProperty_s & soundProperty)
289 {
290     am_handleData_c handleData;
291     SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
292     iter = mMapSourceInterface.find(sourceID);
293     if (iter != mMapSourceInterface.end())
294     {
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));
300     }
301     return (E_NON_EXISTENT);
302 }
303
304 am_Error_e CAmRoutingSender::asyncSetSourceSoundProperties(am_Handle_s& handle, const std::vector<am_SoundProperty_s> & listSoundProperties, const am_sourceID_t sourceID)
305 {
306     am_handleData_c handleData;
307     SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
308     iter = mMapSourceInterface.find(sourceID);
309     if (iter != mMapSourceInterface.end())
310     {
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));
316     }
317     return (E_NON_EXISTENT);
318 }
319
320 am_Error_e CAmRoutingSender::asyncSetSinkSoundProperties(am_Handle_s& handle, const std::vector<am_SoundProperty_s> & listSoundProperties, const am_sinkID_t sinkID)
321 {
322     am_handleData_c handleData;
323     SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
324     iter = mMapSinkInterface.find(sinkID);
325     if (iter != mMapSinkInterface.end())
326     {
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));
332     }
333     return (E_NON_EXISTENT);
334
335 }
336
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)
338 {
339     am_handleData_c handleData;
340     CrossfaderInterfaceMap::iterator iter = mMapCrossfaderInterface.begin();
341     iter = mMapCrossfaderInterface.find(crossfaderID);
342     if (iter != mMapCrossfaderInterface.end())
343     {
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));
349     }
350     return (E_NON_EXISTENT);
351 }
352
353 am_Error_e CAmRoutingSender::setDomainState(const am_domainID_t domainID, const am_DomainState_e domainState)
354 {
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);
360 }
361
362 /**
363  * @author Christian
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.
366  */
367 am_Error_e CAmRoutingSender::addDomainLookup(const am_Domain_s& domainData)
368 {
369     std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin();
370     std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end();
371     for (; iter < iterEnd; ++iter)
372     {
373         if ((*iter).busName.compare(domainData.busname) == 0)
374         {
375             mMapDomainInterface.insert(std::make_pair(domainData.domainID, (*iter).routingInterface));
376             return (E_OK);
377         }
378     }
379
380     return (E_UNKNOWN);
381 }
382
383 /**
384  * @author Christian
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.
387  */
388 am_Error_e CAmRoutingSender::addSourceLookup(const am_Source_s& sourceData)
389 {
390     DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
391     iter = mMapDomainInterface.find(sourceData.domainID);
392     if (iter != mMapDomainInterface.end())
393     {
394         mMapSourceInterface.insert(std::make_pair(sourceData.sourceID, iter->second));
395         return (E_OK);
396     }
397
398     return (E_UNKNOWN);
399 }
400
401 /**
402  * @author Christian
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.
405  */
406 am_Error_e CAmRoutingSender::addSinkLookup(const am_Sink_s& sinkData)
407 {
408     DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
409     iter = mMapDomainInterface.find(sinkData.domainID);
410     if (iter != mMapDomainInterface.end())
411     {
412         mMapSinkInterface.insert(std::make_pair(sinkData.sinkID, iter->second));
413         return (E_OK);
414     }
415
416     return (E_UNKNOWN);
417 }
418
419 /**
420  * @author Christian
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.
423  */
424 am_Error_e CAmRoutingSender::addCrossfaderLookup(const am_Crossfader_s& crossfaderData)
425 {
426     DomainInterfaceMap::iterator iter = mMapSourceInterface.begin();
427     iter = mMapSourceInterface.find(crossfaderData.sourceID);
428     if (iter != mMapSourceInterface.end())
429     {
430         mMapSourceInterface.insert(std::make_pair(crossfaderData.crossfaderID, iter->second));
431         return (E_OK);
432     }
433
434     return (E_UNKNOWN);
435 }
436
437 /**
438  * @author Christian
439  * this removes the Domain to the lookup table of the Router. This must be done everytime a domain is deregistered.
440  */
441 am_Error_e CAmRoutingSender::removeDomainLookup(const am_domainID_t domainID)
442 {
443     DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
444     iter = mMapDomainInterface.find(domainID);
445     if (iter != mMapDomainInterface.end())
446     {
447         mMapDomainInterface.erase(iter);
448         return (E_OK);
449     }
450
451     return (E_NON_EXISTENT);
452 }
453
454 /**
455  * @author Christian
456  * this removes the Source to the lookup table of the Router. This must be done everytime a source is deregistered.
457  */
458 am_Error_e CAmRoutingSender::removeSourceLookup(const am_sourceID_t sourceID)
459 {
460     SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
461     iter = mMapSourceInterface.find(sourceID);
462     if (iter != mMapSourceInterface.end())
463     {
464         mMapSourceInterface.erase(iter);
465         return (E_OK);
466     }
467
468     return (E_NON_EXISTENT);
469 }
470
471 /**
472  * @author Christian
473  * this removes the Sink to the lookup table of the Router. This must be done everytime a sink is deregistered.
474  */
475 am_Error_e CAmRoutingSender::removeSinkLookup(const am_sinkID_t sinkID)
476 {
477     SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
478     iter = mMapSinkInterface.find(sinkID);
479     if (iter != mMapSinkInterface.end())
480     {
481         mMapSinkInterface.erase(iter);
482         return (E_OK);
483     }
484
485     return (E_NON_EXISTENT);
486 }
487
488 /**
489  * @author Christian
490  * this removes the Crossfader to the lookup table of the Router. This must be done everytime a crossfader is deregistered.
491  */
492 am_Error_e CAmRoutingSender::removeCrossfaderLookup(const am_crossfaderID_t crossfaderID)
493 {
494     CrossfaderInterfaceMap::iterator iter = mMapCrossfaderInterface.begin();
495     iter = mMapCrossfaderInterface.find(crossfaderID);
496     if (iter != mMapCrossfaderInterface.end())
497     {
498         mMapCrossfaderInterface.erase(iter);
499         return (E_OK);
500     }
501
502     return (E_NON_EXISTENT);
503 }
504
505 /**
506  * removes a handle from the list
507  * @param handle to be removed
508  * @return E_OK in case of success
509  */
510 am_Error_e CAmRoutingSender::removeHandle(const am_Handle_s& handle)
511 {
512     if (mlistActiveHandles.erase(handle))
513         return (E_OK);
514     return (E_UNKNOWN);
515 }
516
517 am_Error_e CAmRoutingSender::getListHandles(std::vector<am_Handle_s> & listHandles) const
518 {
519     listHandles.clear();
520     HandlesMap::const_iterator it = mlistActiveHandles.begin();
521     for (; it != mlistActiveHandles.end(); ++it)
522     {
523         listHandles.push_back(it->first);
524     }
525     return (E_OK);
526 }
527
528 /**
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
532  * @return the handle
533  */
534 am_Handle_s CAmRoutingSender::createHandle(const am_handleData_c& handleData, const am_Handle_e type)
535 {
536     am_Handle_s handle;
537     handle.handle = ++mHandleCount; //todo: handle overflows here...
538     handle.handleType = type;
539     mlistActiveHandles.insert(std::make_pair(handle, handleData));
540     return (handle);
541 }
542
543 /**
544  * returns the data that belong to handles
545  * @param handle the handle
546  * @return a class holding the handle data
547  */
548 CAmRoutingSender::am_handleData_c CAmRoutingSender::returnHandleData(const am_Handle_s handle) const
549 {
550     HandlesMap::const_iterator it = mlistActiveHandles.begin();
551     it = mlistActiveHandles.find(handle);
552     return (it->second);
553 }
554
555 void CAmRoutingSender::setRoutingReady()
556 {
557     mpRoutingReceiver->waitOnStartup(false);
558
559     //create a list of handles
560     std::vector<uint16_t> listStartupHandles;
561     for (size_t i = 0; i <= mListInterfaces.size(); i++)
562     {
563         listStartupHandles.push_back(mpRoutingReceiver->getStartupHandle());
564     }
565
566     //set the receiver ready to wait for replies
567     mpRoutingReceiver->waitOnStartup(true);
568
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)
573     {
574         (*iter).routingInterface->setRoutingReady(*(handleIter++));
575     }
576 }
577
578 void CAmRoutingSender::setRoutingRundown()
579 {
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++)
584     {
585         listStartupHandles.push_back(mpRoutingReceiver->getRundownHandle());
586     }
587
588     //set the receiver ready to wait for replies
589     mpRoutingReceiver->waitOnRundown(true);
590
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)
595     {
596         (*iter).routingInterface->setRoutingRundown(*(handleIter++));
597     }
598 }
599
600 void CAmRoutingSender::unloadLibraries(void)
601 {
602     std::vector<void*>::iterator iterator = mListLibraryHandles.begin();
603     for (; iterator < mListLibraryHandles.end(); ++iterator)
604     {
605         dlclose(*iterator);
606     }
607     mListLibraryHandles.clear();
608 }
609
610 am_Error_e CAmRoutingSender::getListPlugins(std::vector<std::string>& interfaces) const
611 {
612     std::vector<InterfaceNamePairs>::const_iterator it = mListInterfaces.begin();
613     for (; it != mListInterfaces.end(); ++it)
614     {
615         interfaces.push_back(it->busName);
616     }
617     return (E_OK);
618 }
619
620 void CAmRoutingSender::getInterfaceVersion(std::string & version) const
621 {
622     version = RoutingSendVersion;
623 }
624 }