* fix for Bug 92 - sinkID wrongly reported to DatabaseObserver
[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         return (returnVal);
218     }
219
220     return (E_NON_EXISTENT);
221 }
222
223 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 {
225     am_handleData_c handleData;
226     SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
227     iter = mMapSinkInterface.find(sinkID);
228     if (iter != mMapSinkInterface.end())
229     {
230         handleData.sinkID = sinkID;
231         handleData.volume = volume;
232         handle = createHandle(handleData, H_SETSINKVOLUME);
233         mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
234         return (iter->second->asyncSetSinkVolume(handle, sinkID, volume, ramp, time));
235     }
236     return (E_NON_EXISTENT);
237 }
238
239 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 {
241     am_handleData_c handleData;
242     SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
243     iter = mMapSourceInterface.find(sourceID);
244     if (iter != mMapSourceInterface.end())
245     {
246         handleData.sourceID = sourceID;
247         handleData.volume = volume;
248         handle = createHandle(handleData, H_SETSOURCEVOLUME);
249         mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
250         return (iter->second->asyncSetSourceVolume(handle, sourceID, volume, ramp, time));
251     }
252     return (E_NON_EXISTENT);
253 }
254
255 am_Error_e CAmRoutingSender::asyncSetSourceState(am_Handle_s& handle, const am_sourceID_t sourceID, const am_SourceState_e state)
256 {
257     am_handleData_c handleData;
258     SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
259     iter = mMapSourceInterface.find(sourceID);
260     if (iter != mMapSourceInterface.end())
261     {
262         handleData.sourceID = sourceID;
263         handleData.sourceState = state;
264         handle = createHandle(handleData, H_SETSOURCESTATE);
265         mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
266         return (iter->second->asyncSetSourceState(handle, sourceID, state));
267     }
268     return (E_NON_EXISTENT);
269 }
270
271 am_Error_e CAmRoutingSender::asyncSetSinkSoundProperty(am_Handle_s& handle, const am_sinkID_t sinkID, const am_SoundProperty_s & soundProperty)
272 {
273     am_handleData_c handleData;
274     SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
275     iter = mMapSinkInterface.find(sinkID);
276     if (iter != mMapSinkInterface.end())
277     {
278         handleData.sinkID = sinkID;
279         handleData.soundPropery = soundProperty;
280         handle = createHandle(handleData, H_SETSINKSOUNDPROPERTY);
281         mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
282         return (iter->second->asyncSetSinkSoundProperty(handle, sinkID, soundProperty));
283     }
284     return (E_NON_EXISTENT);
285 }
286
287 am_Error_e CAmRoutingSender::asyncSetSourceSoundProperty(am_Handle_s& handle, const am_sourceID_t sourceID, const am_SoundProperty_s & soundProperty)
288 {
289     am_handleData_c handleData;
290     SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
291     iter = mMapSourceInterface.find(sourceID);
292     if (iter != mMapSourceInterface.end())
293     {
294         handleData.sourceID = sourceID;
295         handleData.soundPropery = soundProperty;
296         handle = createHandle(handleData, H_SETSOURCESOUNDPROPERTY);
297         mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
298         return (iter->second->asyncSetSourceSoundProperty(handle, sourceID, soundProperty));
299     }
300     return (E_NON_EXISTENT);
301 }
302
303 am_Error_e CAmRoutingSender::asyncSetSourceSoundProperties(am_Handle_s& handle, const std::vector<am_SoundProperty_s> & listSoundProperties, const am_sourceID_t sourceID)
304 {
305     am_handleData_c handleData;
306     SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
307     iter = mMapSourceInterface.find(sourceID);
308     if (iter != mMapSourceInterface.end())
309     {
310         handleData.sourceID = sourceID;
311         handleData.soundProperties = new std::vector<am_SoundProperty_s>(listSoundProperties);
312         handle = createHandle(handleData, H_SETSOURCESOUNDPROPERTIES);
313         mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
314         return (iter->second->asyncSetSourceSoundProperties(handle, sourceID, listSoundProperties));
315     }
316     return (E_NON_EXISTENT);
317 }
318
319 am_Error_e CAmRoutingSender::asyncSetSinkSoundProperties(am_Handle_s& handle, const std::vector<am_SoundProperty_s> & listSoundProperties, const am_sinkID_t sinkID)
320 {
321     am_handleData_c handleData;
322     SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
323     iter = mMapSinkInterface.find(sinkID);
324     if (iter != mMapSinkInterface.end())
325     {
326         handleData.sinkID = sinkID;
327         handleData.soundProperties = new std::vector<am_SoundProperty_s>(listSoundProperties);
328         handle = createHandle(handleData, H_SETSINKSOUNDPROPERTIES);
329         mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
330         return (iter->second->asyncSetSinkSoundProperties(handle, sinkID, listSoundProperties));
331     }
332     return (E_NON_EXISTENT);
333
334 }
335
336 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 {
338     am_handleData_c handleData;
339     CrossfaderInterfaceMap::iterator iter = mMapCrossfaderInterface.begin();
340     iter = mMapCrossfaderInterface.find(crossfaderID);
341     if (iter != mMapCrossfaderInterface.end())
342     {
343         handleData.crossfaderID = crossfaderID;
344         handleData.hotSink = hotSink;
345         handle = createHandle(handleData, H_CROSSFADE);
346         mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
347         return (iter->second->asyncCrossFade(handle, crossfaderID, hotSink, rampType, time));
348     }
349     return (E_NON_EXISTENT);
350 }
351
352 am_Error_e CAmRoutingSender::setDomainState(const am_domainID_t domainID, const am_DomainState_e domainState)
353 {
354     DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
355     iter = mMapDomainInterface.find(domainID);
356     if (iter != mMapDomainInterface.end())
357         return (iter->second->setDomainState(domainID, domainState));
358     return (E_NON_EXISTENT);
359 }
360
361 /**
362  * @author Christian
363  * this adds the domain to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface.
364  * This must be done whenever a domain is registered.
365  */
366 am_Error_e CAmRoutingSender::addDomainLookup(const am_Domain_s& domainData)
367 {
368     std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin();
369     std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end();
370     for (; iter < iterEnd; ++iter)
371     {
372         if ((*iter).busName.compare(domainData.busname) == 0)
373         {
374             mMapDomainInterface.insert(std::make_pair(domainData.domainID, (*iter).routingInterface));
375             return (E_OK);
376         }
377     }
378     logError(__PRETTY_FUNCTION__," Could not find busname for bus",domainData.busname);
379     return (E_UNKNOWN);
380 }
381
382 /**
383  * @author Christian
384  * this adds the Source to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface.
385  * This must be done whenever a Source is registered.
386  */
387 am_Error_e CAmRoutingSender::addSourceLookup(const am_Source_s& sourceData)
388 {
389     DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
390     iter = mMapDomainInterface.find(sourceData.domainID);
391     if (iter != mMapDomainInterface.end())
392     {
393         mMapSourceInterface.insert(std::make_pair(sourceData.sourceID, iter->second));
394         return (E_OK);
395     }
396     logError(__PRETTY_FUNCTION__," Could not find domainInterface for domainID",sourceData.domainID);
397     return (E_UNKNOWN);
398 }
399
400 /**
401  * @author Christian
402  * this adds the Sink to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface.
403  * This must be done whenever a Sink is registered.
404  */
405 am_Error_e CAmRoutingSender::addSinkLookup(const am_Sink_s& sinkData)
406 {
407     DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
408     iter = mMapDomainInterface.find(sinkData.domainID);
409     if (iter != mMapDomainInterface.end())
410     {
411         mMapSinkInterface.insert(std::make_pair(sinkData.sinkID, iter->second));
412         return (E_OK);
413     }
414     logError(__PRETTY_FUNCTION__,"Could not find domainInterface for domainID",sinkData.domainID);
415     return (E_UNKNOWN);
416 }
417
418 /**
419  * @author Christian
420  * this adds the Crossfader to the lookup table of the Router. The data is used to have a quick lookup of the correct pluginInterface.
421  * This must be done whenever a Crossfader is registered.
422  */
423 am_Error_e CAmRoutingSender::addCrossfaderLookup(const am_Crossfader_s& crossfaderData)
424 {
425     DomainInterfaceMap::iterator iter = mMapSourceInterface.begin();
426     iter = mMapSourceInterface.find(crossfaderData.sourceID);
427     if (iter != mMapSourceInterface.end())
428     {
429         mMapSourceInterface.insert(std::make_pair(crossfaderData.crossfaderID, iter->second));
430         return (E_OK);
431     }
432     logError(__PRETTY_FUNCTION__," Could not find sourceInterface for source",crossfaderData.sourceID);
433     return (E_UNKNOWN);
434 }
435
436 /**
437  * @author Christian
438  * this removes the Domain to the lookup table of the Router. This must be done everytime a domain is deregistered.
439  */
440 am_Error_e CAmRoutingSender::removeDomainLookup(const am_domainID_t domainID)
441 {
442     DomainInterfaceMap::iterator iter = mMapDomainInterface.begin();
443     iter = mMapDomainInterface.find(domainID);
444     if (iter != mMapDomainInterface.end())
445     {
446         mMapDomainInterface.erase(iter);
447         return (E_OK);
448     }
449
450     return (E_NON_EXISTENT);
451 }
452
453 /**
454  * @author Christian
455  * this removes the Source to the lookup table of the Router. This must be done everytime a source is deregistered.
456  */
457 am_Error_e CAmRoutingSender::removeSourceLookup(const am_sourceID_t sourceID)
458 {
459     SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
460     iter = mMapSourceInterface.find(sourceID);
461     if (iter != mMapSourceInterface.end())
462     {
463         mMapSourceInterface.erase(iter);
464         return (E_OK);
465     }
466
467     return (E_NON_EXISTENT);
468 }
469
470 /**
471  * @author Christian
472  * this removes the Sink to the lookup table of the Router. This must be done everytime a sink is deregistered.
473  */
474 am_Error_e CAmRoutingSender::removeSinkLookup(const am_sinkID_t sinkID)
475 {
476     SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
477     iter = mMapSinkInterface.find(sinkID);
478     if (iter != mMapSinkInterface.end())
479     {
480         mMapSinkInterface.erase(iter);
481         return (E_OK);
482     }
483
484     return (E_NON_EXISTENT);
485 }
486
487 /**
488  * @author Christian
489  * this removes the Crossfader to the lookup table of the Router. This must be done everytime a crossfader is deregistered.
490  */
491 am_Error_e CAmRoutingSender::removeCrossfaderLookup(const am_crossfaderID_t crossfaderID)
492 {
493     CrossfaderInterfaceMap::iterator iter = mMapCrossfaderInterface.begin();
494     iter = mMapCrossfaderInterface.find(crossfaderID);
495     if (iter != mMapCrossfaderInterface.end())
496     {
497         mMapCrossfaderInterface.erase(iter);
498         return (E_OK);
499     }
500
501     return (E_NON_EXISTENT);
502 }
503
504 /**
505  * removes a handle from the list
506  * @param handle to be removed
507  * @return E_OK in case of success
508  */
509 am_Error_e CAmRoutingSender::removeHandle(const am_Handle_s& handle)
510 {
511     if (mlistActiveHandles.erase(handle))
512         return (E_OK);
513     return (E_UNKNOWN);
514 }
515
516 am_Error_e CAmRoutingSender::getListHandles(std::vector<am_Handle_s> & listHandles) const
517 {
518     listHandles.clear();
519     HandlesMap::const_iterator it = mlistActiveHandles.begin();
520     for (; it != mlistActiveHandles.end(); ++it)
521     {
522         listHandles.push_back(it->first);
523     }
524     return (E_OK);
525 }
526
527 /**
528  * creates a handle and adds it to the list of handles
529  * @param handleData the data that should be saves together with the handle
530  * @param type the type of handle to be created
531  * @return the handle
532  */
533 am_Handle_s CAmRoutingSender::createHandle(const am_handleData_c& handleData, const am_Handle_e type)
534 {
535     am_Handle_s handle;
536     if (++mHandleCount>=1024) //defined by 10 bit (out if structure!)
537         mHandleCount=1;
538     handle.handle = mHandleCount;
539     handle.handleType = type;
540     mlistActiveHandles.insert(std::make_pair(handle, handleData));
541     if ((mlistActiveHandles.size()%100) == 0)
542         logInfo("CAmRoutingSender::createHandle warning: too many open handles, number of handles: ", mlistActiveHandles.size());
543     return (handle);
544 }
545
546 /**
547  * returns the data that belong to handles
548  * @param handle the handle
549  * @return a class holding the handle data
550  */
551 CAmRoutingSender::am_handleData_c CAmRoutingSender::returnHandleData(const am_Handle_s handle) const
552 {
553
554     HandlesMap::const_iterator it = mlistActiveHandles.begin();
555     it = mlistActiveHandles.find(handle);
556     if (it!=mlistActiveHandles.end())
557         return (it->second);
558     am_handleData_c handleData;
559     handleData.sinkID=0;
560     return (handleData);
561 }
562
563 void CAmRoutingSender::setRoutingReady()
564 {
565     mpRoutingReceiver->waitOnStartup(false);
566
567     //create a list of handles
568     std::vector<uint16_t> listStartupHandles;
569     for (size_t i = 0; i < mListInterfaces.size(); i++)
570     {
571         listStartupHandles.push_back(mpRoutingReceiver->getStartupHandle());
572     }
573
574     //set the receiver ready to wait for replies
575     mpRoutingReceiver->waitOnStartup(true);
576
577     std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin();
578     std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end();
579     std::vector<uint16_t>::const_iterator handleIter(listStartupHandles.begin());
580     for (; iter < iterEnd; ++iter)
581     {
582         (*iter).routingInterface->setRoutingReady(*(handleIter++));
583     }
584 }
585
586 void CAmRoutingSender::setRoutingRundown()
587 {
588     mpRoutingReceiver->waitOnRundown(false);
589     //create a list of handles
590     std::vector<uint16_t> listStartupHandles;
591     for (size_t i = 0; i < mListInterfaces.size(); i++)
592     {
593         listStartupHandles.push_back(mpRoutingReceiver->getRundownHandle());
594     }
595
596     //set the receiver ready to wait for replies
597     mpRoutingReceiver->waitOnRundown(true);
598
599     std::vector<InterfaceNamePairs>::iterator iter = mListInterfaces.begin();
600     std::vector<InterfaceNamePairs>::iterator iterEnd = mListInterfaces.end();
601     std::vector<uint16_t>::const_iterator handleIter(listStartupHandles.begin());
602     for (; iter < iterEnd; ++iter)
603     {
604         (*iter).routingInterface->setRoutingRundown(*(handleIter++));
605     }
606 }
607
608 am_Error_e CAmRoutingSender::asyncSetVolumes(am_Handle_s& handle, const std::vector<am_Volumes_s>& listVolumes)
609 {
610     am_handleData_c handleData;
611     IAmRoutingSend* pRoutingInterface(NULL);
612     if (listVolumes.empty())
613         return (E_NOT_POSSIBLE);
614
615     //we need an interface so lets get either the sink or source ID from the first entry in the listVolumes
616     if (listVolumes[0].volumeType==VT_SINK)
617     {
618         am_sinkID_t sinkID=listVolumes[0].volumeID.sink;
619         SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
620         iter = mMapSinkInterface.find(sinkID);
621         if(iter!=mMapSinkInterface.end())
622             pRoutingInterface=iter->second;
623         else
624             return(E_NON_EXISTENT);
625     }
626
627     else if (listVolumes[0].volumeType==VT_SOURCE)
628     {
629         am_sourceID_t sourceID=listVolumes[0].volumeID.source;
630         SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
631         iter = mMapSourceInterface.find(sourceID);
632         if (iter!=mMapSourceInterface.end())
633             pRoutingInterface=iter->second;
634         else
635             return(E_NON_EXISTENT);
636     }
637     else
638         return (E_NON_EXISTENT);
639
640     handleData.volumeID=listVolumes[0].volumeID;
641     handleData.listVolumes= new std::vector<am_Volumes_s>(listVolumes);
642     handle = createHandle(handleData, H_SETVOLUMES);
643
644     mMapHandleInterface.insert(std::make_pair(+ handle.handle, pRoutingInterface));
645     return (pRoutingInterface->asyncSetVolumes(handle, listVolumes));
646 }
647
648 am_Error_e CAmRoutingSender::asyncSetSinkNotificationConfiguration(am_Handle_s& handle, const am_sinkID_t sinkID, const am_NotificationConfiguration_s& notificationConfiguration)
649 {
650     am_handleData_c handleData;
651     SinkInterfaceMap::iterator iter = mMapSinkInterface.begin();
652     iter = mMapSinkInterface.find(sinkID);
653     if (iter != mMapSinkInterface.end())
654     {
655         handleData.sinkID = sinkID;
656         handleData.notificationConfiguration = new am_NotificationConfiguration_s(notificationConfiguration);
657         handle = createHandle(handleData, H_SETSINKNOTIFICATION);
658         mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
659         return (iter->second->asyncSetSinkNotificationConfiguration(handle, sinkID,notificationConfiguration));
660     }
661     return (E_NON_EXISTENT);
662 }
663
664 am_Error_e CAmRoutingSender::asyncSetSourceNotificationConfiguration(am_Handle_s& handle, const am_sourceID_t sourceID, const am_NotificationConfiguration_s& notificationConfiguration)
665 {
666     am_handleData_c handleData;
667     SourceInterfaceMap::iterator iter = mMapSourceInterface.begin();
668     iter = mMapSourceInterface.find(sourceID);
669     if (iter != mMapSourceInterface.end())
670     {
671         handleData.sourceID = sourceID;
672         handleData.notificationConfiguration = new am_NotificationConfiguration_s(notificationConfiguration);
673         handle = createHandle(handleData, H_SETSOURCENOTIFICATION);
674         mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second));
675         return (iter->second->asyncSetSourceNotificationConfiguration(handle, sourceID,notificationConfiguration));
676     }
677     return (E_NON_EXISTENT);
678 }
679
680 void CAmRoutingSender::unloadLibraries(void)
681 {
682     std::vector<void*>::iterator iterator = mListLibraryHandles.begin();
683     for (; iterator < mListLibraryHandles.end(); ++iterator)
684     {
685         dlclose(*iterator);
686     }
687     mListLibraryHandles.clear();
688 }
689
690 am_Error_e CAmRoutingSender::getListPlugins(std::vector<std::string>& interfaces) const
691 {
692     std::vector<InterfaceNamePairs>::const_iterator it = mListInterfaces.begin();
693     for (; it != mListInterfaces.end(); ++it)
694     {
695         interfaces.push_back(it->busName);
696     }
697     return (E_OK);
698 }
699
700 void CAmRoutingSender::getInterfaceVersion(std::string & version) const
701 {
702     version = RoutingSendVersion;
703 }
704 }