AudioManager  7.6.6
Native Application Runtime Environment
CAmCommandSender.cpp
Go to the documentation of this file.
1 
24 #include "CAmCommandSender.h"
25 #include <dirent.h>
26 #include <errno.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <sstream>
30 #include <string>
31 #include <cstring>
32 #include <stdexcept>
33 #include "CAmCommandReceiver.h"
34 #include "TAmPluginTemplate.h"
35 #include "CAmDltWrapper.h"
36 #include "audiomanagerconfig.h"
37 
38 #define __METHOD_NAME__ std::string (std::string("CAmCommandSender::") + __func__)
39 
40 namespace am
41 {
42 
46 #define CALL_ALL_INTERFACES(...) \
47  std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin(); \
48  std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end(); \
49  for (; iter<iterEnd;++iter) \
50  { \
51  (*iter)->__VA_ARGS__; \
52  }
53 
54 CAmCommandSender::CAmCommandSender(const std::vector<std::string>& listOfPluginDirectories, CAmSocketHandler *iSocketHandler) :
55  CAmDatabaseHandlerMap::AmDatabaseObserverCallbacks(),
56  mListInterfaces(), //
57  mListLibraryHandles(), //
58  mListLibraryNames(), //
59  mCommandReceiver(),
60  mSerializer(iSocketHandler)
61 {
62  loadPlugins(listOfPluginDirectories);
63 
64  dboNewMainConnection = [&](const am_MainConnectionType_s& mainConnection) {
65  mSerializer.asyncCall(this, &CAmCommandSender::cbNewMainConnection, mainConnection);
66  };
67  dboRemovedMainConnection = [&](const am_mainConnectionID_t mainConnection) {
68  mSerializer.asyncCall(this, &CAmCommandSender::cbRemovedMainConnection, mainConnection);
69  };
70  dboNewSink = [&](const am_Sink_s& sink) {
71  if (sink.visible)
72  {
73  am_SinkType_s s;
74  s.availability = sink.available;
75  s.muteState = sink.muteState;
76  s.name = sink.name;
77  s.sinkClassID = sink.sinkClassID;
78  s.sinkID = sink.sinkID;
79  s.volume = sink.mainVolume;
80  typedef void(CAmCommandSender::*TMeth)(am::am_SinkType_s);
82  }
83  };
84  dboNewSource = [&](const am_Source_s& source) {
85  if (source.visible)
86  {
88  s.availability = source.available;
89  s.name = source.name;
90  s.sourceClassID = source.sourceClassID;
91  s.sourceID = source.sourceID;
92  typedef void(CAmCommandSender::*TMeth)(am::am_SourceType_s);
94  }
95  };
96 
97  dboRemovedSink = [&](const am_sinkID_t sinkID, const bool visible) {
98  if (visible)
99  mSerializer.asyncCall(this, &CAmCommandSender::cbRemovedSink, sinkID);
100  };
101  dboRemovedSource = [&](const am_sourceID_t sourceID, const bool visible) {
102  if (visible)
103  mSerializer.asyncCall(this, &CAmCommandSender::cbRemovedSource, sourceID);
104  };
107  };
110  };
111  dboMainConnectionStateChanged = [&](const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState) {
112  mSerializer.asyncCall(this, &CAmCommandSender::cbMainConnectionStateChanged, connectionID, connectionState);
113  };
114  dboMainSinkSoundPropertyChanged = [&](const am_sinkID_t sinkID, const am_MainSoundProperty_s& SoundProperty) {
115  mSerializer.asyncCall(this, &CAmCommandSender::cbMainSinkSoundPropertyChanged, sinkID, SoundProperty);
116  };
117  dboMainSourceSoundPropertyChanged = [&](const am_sourceID_t sourceID, const am_MainSoundProperty_s& SoundProperty) {
118  mSerializer.asyncCall(this, &CAmCommandSender::cbMainSourceSoundPropertyChanged, sourceID, SoundProperty);
119  };
120  dboSinkAvailabilityChanged = [&](const am_sinkID_t sinkID, const am_Availability_s & availability) {
121  mSerializer.asyncCall(this, &CAmCommandSender::cbSinkAvailabilityChanged, sinkID, availability);
122  };
123  dboSourceAvailabilityChanged = [&](const am_sourceID_t sourceID, const am_Availability_s & availability) {
124  mSerializer.asyncCall(this, &CAmCommandSender::cbSourceAvailabilityChanged, sourceID, availability);
125  };
126  dboVolumeChanged = [&](const am_sinkID_t sinkID, const am_mainVolume_t volume) {
127  mSerializer.asyncCall(this, &CAmCommandSender::cbVolumeChanged, sinkID, volume);
128  };
129  dboSinkMuteStateChanged = [&](const am_sinkID_t sinkID, const am_MuteState_e muteState) {
130  mSerializer.asyncCall(this, &CAmCommandSender::cbSinkMuteStateChanged, sinkID, muteState);
131  };
132  dboSystemPropertyChanged = [&](const am_SystemProperty_s& SystemProperty) {
133  mSerializer.asyncCall(this, &CAmCommandSender::cbSystemPropertyChanged, SystemProperty);
134  };
135  dboTimingInformationChanged = [&](const am_mainConnectionID_t mainConnection, const am_timeSync_t time) {
136  mSerializer.asyncCall(this, &CAmCommandSender::cbTimingInformationChanged, mainConnection, time);
137  };
138  dboSinkUpdated = [&](const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible) {
139  if (visible)
140  mSerializer.asyncCall(this, &CAmCommandSender::cbSinkUpdated, sinkID, sinkClassID, listMainSoundProperties);
141  };
142  dboSourceUpdated = [&](const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible) {
143  if (visible)
144  mSerializer.asyncCall(this, &CAmCommandSender::cbSinkUpdated, sourceID, sourceClassID, listMainSoundProperties);
145  };
146  dboSinkMainNotificationConfigurationChanged = [&](const am_sinkID_t sinkID, const am_NotificationConfiguration_s mainNotificationConfiguration) {
147  mSerializer.asyncCall(this, &CAmCommandSender::cbSinkMainNotificationConfigurationChanged, sinkID, mainNotificationConfiguration);
148  };
149  dboSourceMainNotificationConfigurationChanged = [&](const am_sourceID_t sourceID, const am_NotificationConfiguration_s mainNotificationConfiguration) {
150  mSerializer.asyncCall(this, &CAmCommandSender::cbSourceMainNotificationConfigurationChanged, sourceID, mainNotificationConfiguration);
151  };
152 }
153 
154 void CAmCommandSender::loadPlugins(const std::vector<std::string>& listOfPluginDirectories)
155 {
156  if (listOfPluginDirectories.empty())
157  {
158  logError(__METHOD_NAME__,"List of commandplugins is empty");
159  }
160 
161  std::vector<std::string> sharedLibraryNameList;
162  std::vector<std::string>::const_iterator dirIter = listOfPluginDirectories.begin();
163  std::vector<std::string>::const_iterator dirIterEnd = listOfPluginDirectories.end();
164 
165  // search communicator plugins in configured directories
166  for (; dirIter < dirIterEnd; ++dirIter)
167  {
168  const char* directoryName = dirIter->c_str();
169  logInfo(__METHOD_NAME__,"Searching for CommandPlugins in", *dirIter);
170  DIR *directory = opendir(directoryName);
171 
172  if (!directory)
173  {
174  logError(__METHOD_NAME__,"Error opening directory ", *dirIter);
175  continue;
176  }
177 
178  // iterate content of directory
179  struct dirent *itemInDirectory = 0;
180  while ((itemInDirectory = readdir(directory)))
181  {
182  unsigned char entryType = itemInDirectory->d_type;
183  std::string entryName = itemInDirectory->d_name;
184  std::string fullName = *dirIter + "/" + entryName;
185 
186  bool regularFile = (entryType == DT_REG || entryType == DT_LNK);
187  bool sharedLibExtension = ("so" == entryName.substr(entryName.find_last_of(".") + 1));
188 
189  // Handle cases where readdir() could not determine the file type
190  if (entryType == DT_UNKNOWN)
191  {
192  struct stat buf;
193 
194  if (stat(fullName.c_str(), &buf))
195  {
196  logInfo(__METHOD_NAME__,"Failed to stat file: ", entryName, errno);
197  continue;
198  }
199 
200  regularFile = S_ISREG(buf.st_mode);
201  }
202 
203  if (regularFile && sharedLibExtension)
204  {
205  std::string name(directoryName);
206  sharedLibraryNameList.push_back(name + "/" + entryName);
207  }
208  }
209  closedir(directory);
210  }
211 
212  // iterate all communicator plugins and start them
213  std::vector<std::string>::iterator iter = sharedLibraryNameList.begin();
214  std::vector<std::string>::iterator iterEnd = sharedLibraryNameList.end();
215 
216  for (; iter < iterEnd; ++iter)
217  {
218  logInfo(__METHOD_NAME__,"Loading CommandSender plugin", *iter);
219  IAmCommandSend* (*createFunc)();
220  void* tempLibHandle = NULL;
221  createFunc = getCreateFunction<IAmCommandSend*()>(*iter, tempLibHandle);
222 
223  if (!createFunc)
224  {
225  logInfo(__METHOD_NAME__,"Entry point of CommandPlugin not found", *iter);
226  continue;
227  }
228 
229  IAmCommandSend* commander = createFunc();
230 
231  if (!commander)
232  {
233  logInfo(__METHOD_NAME__,"CommandPlugin initialization failed. Entry Function not callable");
234  dlclose(tempLibHandle);
235  continue;
236  }
237 
238  //check libversion
239  std::string version, cVersion(CommandVersion);
240  commander->getInterfaceVersion(version);
241  uint16_t minorVersion, majorVersion, cMinorVersion, cMajorVersion;
242  std::istringstream(version.substr(0, 1)) >> majorVersion;
243  std::istringstream(version.substr(2, 1)) >> minorVersion;
244  std::istringstream(cVersion.substr(0, 1)) >> cMajorVersion;
245  std::istringstream(cVersion.substr(2, 1)) >> cMinorVersion;
246 
247  if (majorVersion < cMajorVersion || ((majorVersion == cMajorVersion) && (minorVersion > cMinorVersion)))
248  {
249  logError(__METHOD_NAME__,"CommandInterface initialization failed. Version of Interface to old");
250  dlclose(tempLibHandle);
251  continue;
252  }
253 
254  mListInterfaces.push_back(commander);
255  mListLibraryHandles.push_back(tempLibHandle);
256  mListLibraryNames.push_back(iter->c_str());
257  }
258 }
259 
261 {
262  //unloadLibraries();
263 }
264 
266 {
267  mCommandReceiver = iCommandReceiver;
268  am_Error_e returnError = E_OK;
269 
270  std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin();
271  std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end();
272  for (; iter < iterEnd; ++iter)
273  {
274  am_Error_e error = (*iter)->startupInterface(iCommandReceiver);
275  if (error != E_OK)
276  {
277  returnError = error;
278  }
279  }
280  return (returnError);
281 }
282 
284 {
286 }
287 
289 {
291 }
292 
294 {
295  CALL_ALL_INTERFACES(cbMainConnectionStateChanged(connectionID,connectionState))
296 }
297 
299 {
301 }
302 
304 {
306 }
307 
309 {
310  CALL_ALL_INTERFACES(cbSinkAvailabilityChanged(sinkID,availability))
311 }
312 
314 {
315  CALL_ALL_INTERFACES(cbSourceAvailabilityChanged(sourceID,availability))
316 }
317 
319 {
320  CALL_ALL_INTERFACES(cbVolumeChanged(sinkID,volume))
321 }
322 
324 {
326 }
327 
329 {
331 }
332 
334 {
335  CALL_ALL_INTERFACES(cbTimingInformationChanged(mainConnection,time))
336 }
337 
339 {
341 }
342 
344 {
346 }
347 
349 {
351 }
352 
354 {
356 }
357 
359 {
361 }
362 
364 {
366 }
367 
369 {
370  mCommandReceiver->waitOnStartup(false);
371 
372  //create a list of handles
373  std::vector<uint16_t> listStartupHandles;
374  for (size_t i = 0; i < mListInterfaces.size(); i++)
375  {
376  listStartupHandles.push_back(mCommandReceiver->getStartupHandle());
377  }
378 
379  //set the receiver ready to wait for replies
380  mCommandReceiver->waitOnStartup(true);
381 
382  //now do the calls
383  std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin();
384  std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end();
385  std::vector<uint16_t>::const_iterator handleIter(listStartupHandles.begin());
386  for (; iter < iterEnd; ++iter)
387  {
388  (*iter)->setCommandReady(*(handleIter++));
389  }
390 }
391 
393 {
394  mCommandReceiver->waitOnRundown(false);
395  //create a list of handles
396  std::vector<uint16_t> listStartupHandles;
397  for (size_t i = 0; i < mListInterfaces.size(); i++)
398  {
399  listStartupHandles.push_back(mCommandReceiver->getRundownHandle());
400  }
401 
402  //set the receiver ready to wait for replies
403  mCommandReceiver->waitOnRundown(true);
404 
405  //now do the calls
406  std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin();
407  std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end();
408  std::vector<uint16_t>::const_iterator handleIter(listStartupHandles.begin());
409  for (; iter < iterEnd; ++iter)
410  {
411  (*iter)->setCommandRundown(*(handleIter++));
412  }
413 }
414 
415 void CAmCommandSender::getInterfaceVersion(std::string & version) const
416 {
417  version = CommandVersion;
418 }
419 
420 am_Error_e am::CAmCommandSender::getListPlugins(std::vector<std::string> & interfaces) const
421 {
422  interfaces = mListLibraryNames;
423  return (E_OK);
424 }
425 
426 void CAmCommandSender::cbSinkUpdated(const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties)
427 {
428  CALL_ALL_INTERFACES(cbSinkUpdated(sinkID,sinkClassID,listMainSoundProperties));
429 }
430 
431 void CAmCommandSender::cbSourceUpdated(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties)
432 {
433  CALL_ALL_INTERFACES(cbSourceUpdated(sourceID,sourceClassID,listMainSoundProperties));
434 }
435 
437 {
438  CALL_ALL_INTERFACES(cbSinkNotification(sinkID,notification));
439 }
440 
442 {
443  CALL_ALL_INTERFACES(cbSourceNotification(sourceID,notification));
444 }
445 
447 {
448  CALL_ALL_INTERFACES(cbMainSinkNotificationConfigurationChanged(sinkID,mainNotificationConfiguration));
449 }
450 
452 {
453  CALL_ALL_INTERFACES(cbMainSourceNotificationConfigurationChanged(sourceID,mainNotificationConfiguration));
454 }
455 
456 void CAmCommandSender::unloadLibraries(void)
457 {
458  std::vector<void*>::iterator iterator = mListLibraryHandles.begin();
459  for (; iterator < mListLibraryHandles.end(); ++iterator)
460  {
461  dlclose(*iterator);
462  }
463  mListLibraryHandles.clear();
464 }
465 
466 }
am_Error_e getListPlugins(std::vector< std::string > &interfaces) const
void cbNewSink(am_SinkType_s sink)
SPDX license identifier: MPL-2.0.
std::function< void(const am_sourceID_t, const bool)> dboRemovedSource
This class realizes the command Interface.
uint16_t getRundownHandle()
returns a rundown handle
std::function< void(const am_Sink_s &)> dboNewSink
#define CommandVersion
Definition: IAmCommand.h:37
std::function< void(const am_SystemProperty_s &)> dboSystemPropertyChanged
A Common-API wrapper class, which loads the common-api runtime and instantiates all necessary objects...
am_Error_e startupInterfaces(CAmCommandReceiver *iCommandReceiver)
#define __METHOD_NAME__
uint16_t am_sinkClass_t
am_Error_e
the errors of the audiomanager.
This struct holds information about the configuration for notifications.
void logInfo(T value, TArgs...args)
logs given values with infolevel with the default context
std::function< void(const am_sinkID_t, const am_sinkClass_t, const std::vector< am_MainSoundProperty_s > &, const bool)> dboSinkUpdated
void cbSystemPropertyChanged(const am_SystemProperty_s &systemProperty)
void cbSinkUpdated(const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector< am_MainSoundProperty_s > &listMainSoundProperties)
std::function< void(const am_sinkID_t, const bool)> dboRemovedSink
void cbNewMainConnection(const am_MainConnectionType_s mainConnection)
This struct describes the attribiutes of a sink.
This struct holds the payload of a notification.
std::function< void(const am_mainConnectionID_t, const am_timeSync_t)> dboTimingInformationChanged
std::function< void(const am_sourceID_t, const am_MainSoundProperty_s &)> dboMainSourceSoundPropertyChanged
virtual void getInterfaceVersion(std::string &version) const =0
returns the interface version as string.
#define CALL_ALL_INTERFACES(...)
macro to call all interfaces
std::string name
The name of the source.
void cbSourceNotification(const am_sourceID_t sourceID, const am_NotificationPayload_s &notification)
The am::CAmSocketHandler implements a mainloop for the AudioManager.
std::function< void(const am_mainConnectionID_t)> dboRemovedMainConnection
std::function< void(const am_sinkID_t, const am_Availability_s &)> dboSinkAvailabilityChanged
this type holds all information of sinks relevant to the HMI
std::function< void(const am_mainConnectionID_t, const am_ConnectionState_e)> dboMainConnectionStateChanged
int16_t am_timeSync_t
offset time that is introduced in milli seconds.
am_Availability_s availability
the availability of the source
std::function< void(const am_sourceID_t, const am_NotificationConfiguration_s)> dboSourceMainNotificationConfigurationChanged
void cbMainSinkSoundPropertyChanged(const am_sinkID_t sinkID, const am_MainSoundProperty_s &soundProperty)
SPDX license identifier: MPL-2.0.
std::function< void(const am_Source_s &)> dboNewSource
void cbMainSourceSoundPropertyChanged(const am_sourceID_t sourceID, const am_MainSoundProperty_s &soundProperty)
void cbRemovedSource(const am_sourceID_t source)
void cbTimingInformationChanged(const am_mainConnectionID_t mainConnectionID, const am_timeSync_t time)
void cbNewSource(const am_SourceType_s source)
std::function< void(const am_sourceID_t, const am_Availability_s &)> dboSourceAvailabilityChanged
CAmCommandSender(const std::vector< std::string > &listOfPluginDirectories, CAmSocketHandler *iSocketHandler)
struct describing system properties
void waitOnRundown(bool rundown)
tells the ComandReceiver to start waiting for all handles to be confirmed
SPDX license identifier: MPL-2.0.
am_sourceID_t sourceID
This is the ID of the source, it is unique in the system.
struct describung mainsound property
am_Availability_s availability
This attribute reflects the availability of the sink.
std::function< void(const am_sourceID_t, const am_sourceClass_t, const std::vector< am_MainSoundProperty_s > &, const bool)> dboSourceUpdated
void getInterfaceVersion(std::string &version) const
uint16_t am_sourceID_t
a source ID
void cbSinkNotification(const am_sinkID_t sinkID, const am_NotificationPayload_s &notification)
am_sinkID_t sinkID
This is the ID of the sink, it is unique in the system.
std::function< void(const am_sinkID_t, const am_MuteState_e)> dboSinkMuteStateChanged
am_sourceClass_t sourceClassID
the sourceClassID, indicates the class the source is in.
std::function< void(const am_sinkID_t, const am_MainSoundProperty_s &)> dboMainSinkSoundPropertyChanged
std::function< void(const am_sinkID_t, const am_NotificationConfiguration_s)> dboSinkMainNotificationConfigurationChanged
am_mainVolume_t volume
This is the representation of the Volume for the commandInterface.
am_ConnectionState_e
represents the connection state
void cbSourceMainNotificationConfigurationChanged(const am_sourceID_t sourceID, const am_NotificationConfiguration_s &mainNotificationConfiguration)
am_MuteState_e muteState
this type holds all information of connections relevant to the HMI
void cbSourceUpdated(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector< am_MainSoundProperty_s > &listMainSoundProperties)
void cbSinkMuteStateChanged(const am_sinkID_t sinkID, const am_MuteState_e muteState)
uint16_t am_sourceClass_t
void cbRemovedMainConnection(const am_mainConnectionID_t mainConnection)
this describes the availability of a sink or a source together with the latest change ...
void logError(T value, TArgs...args)
logs given values with errorlevel with the default context
void cbSinkAvailabilityChanged(const am_sinkID_t sinkID, const am_Availability_s &availability)
void waitOnStartup(bool startup)
tells the ComandReceiver to start waiting for all handles to be confirmed
void cbVolumeChanged(const am_sinkID_t sinkID, const am_mainVolume_t volume)
void cbSinkMainNotificationConfigurationChanged(const am_sinkID_t sinkID, const am_NotificationConfiguration_s &mainNotificationConfiguration)
void cbMainConnectionStateChanged(const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState)
SPDX license identifier: MPL-2.0.
int16_t am_mainVolume_t
This is the volume presented on the command interface.
no error - positive reply
void cbSourceAvailabilityChanged(const am_sourceID_t sourceID, const am_Availability_s &availability)
uint16_t getStartupHandle()
returns a startup handle
this type holds all information of sources relevant to the HMI
This struct describes the attribiutes of a source.
std::string name
The name of the sink.
This class is used to send data to the CommandInterface.
uint16_t am_sinkID_t
a sink ID
uint16_t am_mainConnectionID_t
a mainConnection ID
This class handles and abstracts the database.
void asyncCall(TClass *instance, TMeth method, TArgs &&...arguments)
calls a function with variadic arguments threadsafe
am_sinkClass_t sinkClassID
The sinkClassID references to a sinkClass.
This interface handles all communication from the AudioManagerDaemon towards the system.
Definition: IAmCommand.h:243
std::function< void(const am_sinkID_t, const am_mainVolume_t)> dboVolumeChanged
std::function< void(const am_MainConnectionType_s &)> dboNewMainConnection
void cbRemovedSink(const am_sinkID_t sink)