* [GAM-74] resolving issues found by coverity scan
[profile/ivi/genivi/genivi-audio-manager.git] / AudioManagerDaemon / src / CAmCommandSender.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 CAmCommandSender.cpp
18  * For further information see http://www.genivi.org/.
19  *
20  */
21
22 #include "CAmCommandSender.h"
23 #include <dirent.h>
24 #include <sstream>
25 #include <string>
26 #include "CAmCommandReceiver.h"
27 #include "TAmPluginTemplate.h"
28 #include "shared/CAmDltWrapper.h"
29
30 namespace am
31 {
32
33 #define REQUIRED_INTERFACE_VERSION_MAJOR 1  //!< major interface version. All versions smaller than this will be rejected
34 #define REQUIRED_INTERFACE_VERSION_MINOR 0 //!< minor interface version. All versions smaller than this will be rejected
35 /**
36  *  macro to call all interfaces
37  */
38 #define CALL_ALL_INTERFACES(...)                                                                                                                 \
39                 std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin();           \
40                 std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end();          \
41                 for (; iter<iterEnd;++iter)                                                                                                              \
42                 {                                                                                                                                                                \
43                         (*iter)->__VA_ARGS__;                                                                                                            \
44                 }
45
46 CAmCommandSender::CAmCommandSender(const std::vector<std::string>& listOfPluginDirectories) :
47         mListInterfaces(), //
48         mListLibraryHandles(), //
49         mListLibraryNames(), //
50         mCommandReceiver()
51 {
52     std::vector<std::string> sharedLibraryNameList;
53     std::vector<std::string>::const_iterator dirIter = listOfPluginDirectories.begin();
54     std::vector<std::string>::const_iterator dirIterEnd = listOfPluginDirectories.end();
55
56     // search communicator plugins in configured directories
57     for (; dirIter < dirIterEnd; ++dirIter)
58     {
59         const char* directoryName = dirIter->c_str();
60         logInfo("Searching for CommandPlugins in", *dirIter);
61         DIR *directory = opendir(directoryName);
62
63         if (!directory)
64         {
65             logError("Error opening directory ", *dirIter);
66             continue;
67         }
68
69         // iterate content of directory
70         struct dirent *itemInDirectory = 0;
71         while ((itemInDirectory = readdir(directory)))
72         {
73             unsigned char entryType = itemInDirectory->d_type;
74             std::string entryName = itemInDirectory->d_name;
75
76             bool regularFile = (entryType == DT_REG || entryType == DT_LNK);
77             bool sharedLibExtension = ("so" == entryName.substr(entryName.find_last_of(".") + 1));
78
79             if (regularFile && sharedLibExtension)
80             {
81                 std::string name(directoryName);
82                 sharedLibraryNameList.push_back(name + "/" + entryName);
83             }
84         }
85         closedir(directory);
86     }
87
88     // iterate all communicator plugins and start them
89     std::vector<std::string>::iterator iter = sharedLibraryNameList.begin();
90     std::vector<std::string>::iterator iterEnd = sharedLibraryNameList.end();
91
92     for (; iter < iterEnd; ++iter)
93     {
94         logInfo("Loading CommandSender plugin", *iter);
95         IAmCommandSend* (*createFunc)();
96         void* tempLibHandle = NULL;
97         createFunc = getCreateFunction<IAmCommandSend*()>(*iter, tempLibHandle);
98
99         if (!createFunc)
100         {
101             logInfo("Entry point of CommandPlugin not found", *iter);
102             continue;
103         }
104
105         IAmCommandSend* commander = createFunc();
106
107         if (!commander)
108         {
109             logInfo("CommandPlugin initialization failed. Entry Function not callable");
110             dlclose(tempLibHandle);
111             continue;
112         }
113
114         //check libversion
115         std::string version;
116         commander->getInterfaceVersion(version);
117         uint16_t minorVersion, majorVersion;
118         std::istringstream(version.substr(0, 1)) >> majorVersion;
119         std::istringstream(version.substr(2, 1)) >> minorVersion;
120
121         if (majorVersion < REQUIRED_INTERFACE_VERSION_MAJOR || ((majorVersion == REQUIRED_INTERFACE_VERSION_MAJOR) && (minorVersion > REQUIRED_INTERFACE_VERSION_MINOR)))
122         {
123             logInfo("CommandInterface initialization failed. Version of Interface to old");
124             dlclose(tempLibHandle);
125             continue;
126         }
127
128         mListInterfaces.push_back(commander);
129         mListLibraryHandles.push_back(tempLibHandle);
130         mListLibraryNames.push_back(iter->c_str());
131     }
132 }
133
134 CAmCommandSender::~CAmCommandSender()
135 {
136     unloadLibraries();
137 }
138
139 am_Error_e CAmCommandSender::startupInterfaces(CAmCommandReceiver *iCommandReceiver)
140 {
141     mCommandReceiver = iCommandReceiver;
142     am_Error_e returnError = E_OK;
143
144     std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin();
145     std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end();
146     for (; iter < iterEnd; ++iter)
147     {
148         am_Error_e error = (*iter)->startupInterface(iCommandReceiver);
149         if (error != E_OK)
150         {
151             returnError = error;
152         }
153     }
154     return (returnError);
155 }
156
157 void CAmCommandSender::cbNumberOfSinkClassesChanged()
158 {
159     CALL_ALL_INTERFACES(cbNumberOfSinkClassesChanged())
160 }
161
162 void CAmCommandSender::cbNumberOfSourceClassesChanged()
163 {
164     CALL_ALL_INTERFACES(cbNumberOfSourceClassesChanged())
165 }
166
167 void CAmCommandSender::cbMainConnectionStateChanged(const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState)
168 {
169     CALL_ALL_INTERFACES(cbMainConnectionStateChanged(connectionID,connectionState))
170 }
171
172 void CAmCommandSender::cbMainSinkSoundPropertyChanged(const am_sinkID_t sinkID, const am_MainSoundProperty_s& SoundProperty)
173 {
174     CALL_ALL_INTERFACES(cbMainSinkSoundPropertyChanged(sinkID,SoundProperty))
175 }
176
177 void CAmCommandSender::cbMainSourceSoundPropertyChanged(const am_sourceID_t sourceID, const am_MainSoundProperty_s& SoundProperty)
178 {
179     CALL_ALL_INTERFACES(cbMainSourceSoundPropertyChanged(sourceID,SoundProperty))
180 }
181
182 void CAmCommandSender::cbSinkAvailabilityChanged(const am_sinkID_t sinkID, const am_Availability_s & availability)
183 {
184     CALL_ALL_INTERFACES(cbSinkAvailabilityChanged(sinkID,availability))
185 }
186
187 void CAmCommandSender::cbSourceAvailabilityChanged(const am_sourceID_t sourceID, const am_Availability_s & availability)
188 {
189     CALL_ALL_INTERFACES(cbSourceAvailabilityChanged(sourceID,availability))
190 }
191
192 void CAmCommandSender::cbVolumeChanged(const am_sinkID_t sinkID, const am_mainVolume_t volume)
193 {
194     CALL_ALL_INTERFACES(cbVolumeChanged(sinkID,volume))
195 }
196
197 void CAmCommandSender::cbSinkMuteStateChanged(const am_sinkID_t sinkID, const am_MuteState_e muteState)
198 {
199     CALL_ALL_INTERFACES(cbSinkMuteStateChanged(sinkID,muteState))
200 }
201
202 void CAmCommandSender::cbSystemPropertyChanged(const am_SystemProperty_s & SystemProperty)
203 {
204     CALL_ALL_INTERFACES(cbSystemPropertyChanged(SystemProperty))
205 }
206
207 void CAmCommandSender::cbTimingInformationChanged(const am_mainConnectionID_t mainConnection, const am_timeSync_t time)
208 {
209     CALL_ALL_INTERFACES(cbTimingInformationChanged(mainConnection,time))
210 }
211
212 void CAmCommandSender::cbNewMainConnection(const am_MainConnectionType_s mainConnection)
213 {
214     CALL_ALL_INTERFACES(cbNewMainConnection(mainConnection))
215 }
216
217 void CAmCommandSender::cbRemovedMainConnection(const am_mainConnectionID_t mainConnection)
218 {
219     CALL_ALL_INTERFACES(cbRemovedMainConnection(mainConnection))
220 }
221
222 void CAmCommandSender::cbNewSink(const am_SinkType_s sink)
223 {
224     CALL_ALL_INTERFACES(cbNewSink(sink))
225 }
226
227 void CAmCommandSender::cbRemovedSink(const am_sinkID_t sink)
228 {
229     CALL_ALL_INTERFACES(cbRemovedSink(sink))
230 }
231
232 void CAmCommandSender::cbNewSource(const am_SourceType_s source)
233 {
234     CALL_ALL_INTERFACES(cbNewSource(source))
235 }
236
237 void CAmCommandSender::cbRemovedSource(const am_sourceID_t source)
238 {
239     CALL_ALL_INTERFACES(cbRemovedSource(source))
240 }
241
242 void CAmCommandSender::setCommandReady()
243 {
244     mCommandReceiver->waitOnStartup(false);
245
246     //create a list of handles
247     std::vector<uint16_t> listStartupHandles;
248     for (size_t i = 0; i <= mListInterfaces.size(); i++)
249     {
250         listStartupHandles.push_back(mCommandReceiver->getStartupHandle());
251     }
252
253     //set the receiver ready to wait for replies
254     mCommandReceiver->waitOnStartup(true);
255
256     //now do the calls
257     std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin();
258     std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end();
259     std::vector<uint16_t>::const_iterator handleIter(listStartupHandles.begin());
260     for (; iter < iterEnd; ++iter)
261     {
262         (*iter)->setCommandReady(*(handleIter++));
263     }
264 }
265
266 void CAmCommandSender::setCommandRundown()
267 {
268     mCommandReceiver->waitOnRundown(false);
269     //create a list of handles
270     std::vector<uint16_t> listStartupHandles;
271     for (size_t i = 0; i <= mListInterfaces.size(); i++)
272     {
273         listStartupHandles.push_back(mCommandReceiver->getRundownHandle());
274     }
275
276     //set the receiver ready to wait for replies
277     mCommandReceiver->waitOnRundown(true);
278
279     //now do the calls
280     std::vector<IAmCommandSend*>::iterator iter = mListInterfaces.begin();
281     std::vector<IAmCommandSend*>::iterator iterEnd = mListInterfaces.end();
282     std::vector<uint16_t>::const_iterator handleIter(listStartupHandles.begin());
283     for (; iter < iterEnd; ++iter)
284     {
285         (*iter)->setCommandRundown(*(handleIter++));
286     }
287 }
288
289 void CAmCommandSender::getInterfaceVersion(std::string & version) const
290 {
291     version = CommandSendVersion;
292 }
293
294 am_Error_e am::CAmCommandSender::getListPlugins(std::vector<std::string> & interfaces) const
295 {
296     interfaces = mListLibraryNames;
297     return (E_OK);
298 }
299
300 void CAmCommandSender::unloadLibraries(void)
301 {
302     std::vector<void*>::iterator iterator = mListLibraryHandles.begin();
303     for (; iterator < mListLibraryHandles.end(); ++iterator)
304     {
305         dlclose(*iterator);
306     }
307     mListLibraryHandles.clear();
308 }
309 }