AudioManager  7.6.6
Native Application Runtime Environment
CAmCommonAPIWrapper.cpp
Go to the documentation of this file.
1 
18 #include "audiomanagerconfig.h"
19 #include <fstream>
20 #include <sstream>
21 #include <algorithm>
22 #include <cstdlib>
23 #include <stdexcept>
24 #include <poll.h>
25 #include <tuple>
26 #include <sstream>
27 #include <vector>
28 #include "audiomanagertypes.h"
29 #include "CAmSocketHandler.h"
30 #include "CAmDltWrapper.h"
31 #include "CAmCommonAPIWrapper.h"
32 
33 
34 namespace am
35 {
36 static CAmCommonAPIWrapper* pSingleCommonAPIInstance = NULL;
37 
38 
39 CAmCommonAPIWrapper::CAmCommonAPIWrapper(CAmSocketHandler* socketHandler, const std::string & applicationName):
40  pCommonPrepareCallback(this,&CAmCommonAPIWrapper::commonPrepareCallback), //
41  pCommonDispatchCallback(this, &CAmCommonAPIWrapper::commonDispatchCallback), //
42  pCommonFireCallback(this, &CAmCommonAPIWrapper::commonFireCallback), //
43  pCommonCheckCallback(this, &CAmCommonAPIWrapper::commonCheckCallback), //
44  pCommonTimerCallback(this, &CAmCommonAPIWrapper::commonTimerCallback), //
45  mpSocketHandler(socketHandler), //
46  mWatchToCheck(NULL)
47 {
48  assert(NULL!=socketHandler);
49 //Get the runtime
50  mRuntime = CommonAPI::Runtime::get();
51  assert(NULL!=mRuntime);
52 
53  //Create the context
54  if(applicationName.size())
55  mContext = std::make_shared<CommonAPI::MainLoopContext>(applicationName);
56  else
57  mContext = std::make_shared<CommonAPI::MainLoopContext>();
58  assert(NULL!=mContext);
59  logInfo(__func__,"CommonAPI main loop context with name '", mContext->getName(), "' has been created!");
60 
61 //Make subscriptions
62  mDispatchSourceListenerSubscription = mContext->subscribeForDispatchSources(
63  std::bind(&CAmCommonAPIWrapper::registerDispatchSource, this, std::placeholders::_1, std::placeholders::_2),
64  std::bind(&CAmCommonAPIWrapper::deregisterDispatchSource, this, std::placeholders::_1));
65  mWatchListenerSubscription = mContext->subscribeForWatches(
66  std::bind(&CAmCommonAPIWrapper::registerWatch, this, std::placeholders::_1, std::placeholders::_2),
67  std::bind(&CAmCommonAPIWrapper::deregisterWatch, this, std::placeholders::_1));
68  mTimeoutSourceListenerSubscription = mContext->subscribeForTimeouts(
69  std::bind(&CAmCommonAPIWrapper::registerTimeout, this, std::placeholders::_1, std::placeholders::_2),
70  std::bind(&CAmCommonAPIWrapper::deregisterTimeout, this, std::placeholders::_1));
71 }
72 
74 {
75  mContext->unsubscribeForDispatchSources(mDispatchSourceListenerSubscription);
76  mContext->unsubscribeForWatches(mWatchListenerSubscription);
77  mContext->unsubscribeForTimeouts(mTimeoutSourceListenerSubscription);
78  mContext.reset();
79  mpSocketHandler = NULL;
80  mWatchToCheck = NULL;
81 }
82 
83 CAmCommonAPIWrapper* CAmCommonAPIWrapper::instantiateOnce(CAmSocketHandler* socketHandler, const std::string & applicationName)
84 {
85  if(NULL==pSingleCommonAPIInstance)
86  {
87  if(NULL==socketHandler)
88  throw std::runtime_error(std::string("Expected a valid socket handler. The socket handler pointer must not be NULL."));
89  else
90  pSingleCommonAPIInstance = new CAmCommonAPIWrapper(socketHandler, applicationName);
91  }
92  else
93  throw std::logic_error(std::string("The singleton instance has been already instantiated. This method should be called only once."));
94  return pSingleCommonAPIInstance;
95 }
96 
98 {
99  try
100  {
101  if (pSingleCommonAPIInstance!=NULL)
102  delete pSingleCommonAPIInstance;
103 
104  pSingleCommonAPIInstance=NULL;
105  }
106  catch(...)
107  {
108  logError(__func__,"error while deleting CAPIWrapper instance");
109  }
110 }
111 
113 {
114  assert(NULL!=pSingleCommonAPIInstance);
115  return pSingleCommonAPIInstance;
116 }
117 
118 bool CAmCommonAPIWrapper::commonDispatchCallback(const sh_pollHandle_t handle, void *userData)
119 {
120  (void) handle;
121  (void) userData;
122 
123  std::list<CommonAPI::DispatchSource*>::iterator iterator(mSourcesToDispatch.begin());
124  for(;iterator!=mSourcesToDispatch.end();)
125  {
126  CommonAPI::DispatchSource* source = *iterator;
127  if (!source->dispatch()) {
128  iterator=mSourcesToDispatch.erase(iterator);
129  }
130  else
131  iterator++;
132  }
133  if (!mSourcesToDispatch.empty())
134  return (true);
135 
136  return false;
137 }
138 
139 bool CAmCommonAPIWrapper::commonCheckCallback(const sh_pollHandle_t, void *)
140 {
141  std::vector<CommonAPI::DispatchSource*> vecDispatch=mWatchToCheck->getDependentDispatchSources();
142  mSourcesToDispatch.insert(mSourcesToDispatch.end(), vecDispatch.begin(), vecDispatch.end());
143 
144  return (mWatchToCheck || !mSourcesToDispatch.empty());
145 }
146 
147 void CAmCommonAPIWrapper::commonFireCallback(const pollfd pollfd, const sh_pollHandle_t, void *)
148 {
149  mWatchToCheck=NULL;
150  try
151  {
152  mWatchToCheck=mMapWatches.at(pollfd.fd);
153  }
154  catch (const std::out_of_range& error) {
155  logInfo(__PRETTY_FUNCTION__,error.what());
156  return;
157  }
158 
159  mWatchToCheck->dispatch(pollfd.events);
160 }
161 
162 void CAmCommonAPIWrapper::commonPrepareCallback(const sh_pollHandle_t, void*)
163 {
164  for (auto dispatchSourceIterator = mRegisteredDispatchSources.begin();
165  dispatchSourceIterator != mRegisteredDispatchSources.end();
166  dispatchSourceIterator++)
167  {
168  int64_t dispatchTimeout(CommonAPI::TIMEOUT_INFINITE);
169  if(dispatchSourceIterator->second->prepare(dispatchTimeout))
170  {
171  while (dispatchSourceIterator->second->dispatch());
172  }
173  }
174 }
175 
176 void CAmCommonAPIWrapper::registerDispatchSource(CommonAPI::DispatchSource* dispatchSource, const CommonAPI::DispatchPriority dispatchPriority)
177 {
178  mRegisteredDispatchSources.insert({dispatchPriority, dispatchSource});
179 }
180 
181 void CAmCommonAPIWrapper::deregisterDispatchSource(CommonAPI::DispatchSource* dispatchSource)
182 {
183  for(auto dispatchSourceIterator = mRegisteredDispatchSources.begin();
184  dispatchSourceIterator != mRegisteredDispatchSources.end();
185  dispatchSourceIterator++) {
186 
187  if(dispatchSourceIterator->second == dispatchSource) {
188  mRegisteredDispatchSources.erase(dispatchSourceIterator);
189  break;
190  }
191  }
192 }
193 
194 void CAmCommonAPIWrapper::deregisterWatch(CommonAPI::Watch* watch)
195 {
196  for(std::map<int,CommonAPI::Watch*>::iterator iter(mMapWatches.begin());iter!=mMapWatches.end();iter++)
197  {
198  if (iter->second == watch)
199  {
200  mMapWatches.erase(iter);
201  break;
202  }
203  }
204 }
205 
206 void CAmCommonAPIWrapper::registerTimeout(CommonAPI::Timeout* timeout, const CommonAPI::DispatchPriority)
207 {
208  timespec pollTimeout;
209  int64_t localTimeout = timeout->getTimeoutInterval();
210 
211  pollTimeout.tv_sec = localTimeout / 1000;
212  pollTimeout.tv_nsec = (localTimeout % 1000) * 1000000;
213 
214  //prepare handle and callback. new is eval, but there is no other choice because we need the pointer!
215  sh_timerHandle_t handle;
216 
217  //add the timer to the pollLoop
218  mpSocketHandler->addTimer(pollTimeout, &pCommonTimerCallback, handle, timeout);
219 
220  timerHandles myHandle({handle,timeout});
221  mpListTimerhandles.push_back(myHandle);
222 
223  return;
224 }
225 
226 void CAmCommonAPIWrapper::deregisterTimeout(CommonAPI::Timeout* timeout)
227 {
228  for( std::vector<timerHandles>::iterator iter(mpListTimerhandles.begin());iter!=mpListTimerhandles.end();iter++)
229  {
230  if(iter->timeout==timeout)
231  {
232  mpSocketHandler->removeTimer(iter->handle);
233  }
234  }
235 }
236 
237 void CAmCommonAPIWrapper::registerWatch(CommonAPI::Watch* watch, const CommonAPI::DispatchPriority)
238 {
239  logInfo(__PRETTY_FUNCTION__);
240  pollfd pollfd_ (watch->getAssociatedFileDescriptor());
241  sh_pollHandle_t handle (0);
242 
243  am_Error_e error = mpSocketHandler->addFDPoll(pollfd_.fd, pollfd_.events, &pCommonPrepareCallback, &pCommonFireCallback, &pCommonCheckCallback, &pCommonDispatchCallback, watch, handle);
244 
245  //if everything is alright, add the watch and the handle to our map so we know this relationship
246  if (error == !am_Error_e::E_OK || handle == 0)
247  logError(__func__,"entering watch failed");
248 
249  mMapWatches.insert(std::make_pair(pollfd_.fd,watch));
250 }
251 
252 void CAmCommonAPIWrapper::commonTimerCallback(sh_timerHandle_t handle, void *)
253 {
254  for( std::vector<timerHandles>::iterator iter(mpListTimerhandles.begin());iter!=mpListTimerhandles.end();iter++)
255  {
256  if(iter->handle==handle)
257  {
258  iter->timeout->dispatch();
259  }
260  }
261 }
262 
264 
265 }
CAmCommonAPIWrapper(CAmSocketHandler *socketHandler, const std::string &applicationName="")
SPDX license identifier: MPL-2.0.
A Common-API wrapper class, which loads the common-api runtime and instantiates all necessary objects...
am_Error_e
the errors of the audiomanager.
void logInfo(T value, TArgs...args)
logs given values with infolevel with the default context
static CAmCommonAPIWrapper * instantiateOnce(CAmSocketHandler *socketHandler, const std::string &applicationName="")
Creates a singleton instance attached to the provided socket handler object.
The am::CAmSocketHandler implements a mainloop for the AudioManager.
uint16_t sh_pollHandle_t
this is a handle for a filedescriptor to be used with the SocketHandler
SPDX license identifier: MPL-2.0.
am_Error_e removeTimer(const sh_timerHandle_t handle)
removes a timer from the list of timers
static void deleteInstance()
Deletes the instanciated object.
static CAmCommonAPIWrapper * getInstance()
Returns an already instantiated object.
am_Error_e addFDPoll(const int fd, const short event, std::function< void(const sh_pollHandle_t handle, void *userData)> prepare, std::function< void(const pollfd pollfd, const sh_pollHandle_t handle, void *userData)> fired, std::function< bool(const sh_pollHandle_t handle, void *userData)> check, std::function< bool(const sh_pollHandle_t handle, void *userData)> dispatch, void *userData, sh_pollHandle_t &handle)
Adds a filedescriptor to the polling loop.
Copyright (C) 2012 - 2014, BMW AG.
SPDX license identifier: MPL-2.0.
void logError(T value, TArgs...args)
logs given values with errorlevel with the default context
no error - positive reply
sh_pollHandle_t sh_timerHandle_t
this is a handle for a timer to be used with the SocketHandler
am_Error_e addTimer(const timespec &timeouts, IAmShTimerCallBack *callback, sh_timerHandle_t &handle, void *userData, const bool __attribute__((__unused__)) repeats=false)