* fix [GAM-28] problems in routingsender.cpp
[profile/ivi/genivi/genivi-audio-manager.git] / PluginRoutingInterfaceAsync / include / CAmRoutingSenderAsync.h
1 /**
2  * Copyright (C) 2011, BMW AG
3  *
4  * GeniviAudioMananger DbusPlugin
5  *
6  * \file CAmRoutingSender.h
7  *
8  * \date 20-Oct-2011 3:42:04 PM
9  * \author Christian Mueller (christian.ei.mueller@bmw.de)
10  *
11  * \section License
12  * GNU Lesser General Public License, version 2.1, with special exception (GENIVI clause)
13  * Copyright (C) 2011, BMW AG Christian Mueller  Christian.ei.mueller@bmw.de
14  *
15  * This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License, version 2.1, as published by the Free Software Foundation.
16  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License, version 2.1, for more details.
17  * You should have received a copy of the GNU Lesser General Public License, version 2.1, along with this program; if not, see <http://www.gnu.org/licenses/lgpl-2.1.html>.
18  * Note that the copyright holders assume that the GNU Lesser General Public License, version 2.1, may also be applicable to programs even in cases in which the program is not a library in the technical sense.
19  * Linking AudioManager statically or dynamically with other modules is making a combined work based on AudioManager. You may license such other modules under the GNU Lesser General Public License, version 2.1. If you do not want to license your linked modules under the GNU Lesser General Public License, version 2.1, you may use the program under the following exception.
20  * As a special exception, the copyright holders of AudioManager give you permission to combine AudioManager with software programs or libraries that are released under any license unless such a combination is not permitted by the license of such a software program or library. You may copy and distribute such a system following the terms of the GNU Lesser General Public License, version 2.1, including this special exception, for AudioManager and the licenses of the other code concerned.
21  * Note that people who make modified versions of AudioManager are not obligated to grant this special exception for their modified versions; it is their choice whether to do so. The GNU Lesser General Public License, version 2.1, gives permission to release a modified version without this exception; this exception also makes it possible to release a modified version which carries forward this exception.
22  *
23  * THIS CODE HAS BEEN GENERATED BY ENTERPRISE ARCHITECT GENIVI MODEL. PLEASE CHANGE ONLY IN ENTERPRISE ARCHITECT AND GENERATE AGAIN
24  */
25
26 #ifndef ROUTINGSENDER_H_
27 #define ROUTINGSENDER_H_
28
29 #include "routing/IAmRoutingSend.h"
30 #include "IAmRoutingReceiverShadow.h"
31 #include <semaphore.h>
32 #include <memory.h>
33
34 namespace am
35 {
36
37 class CAmWorkerThreadPool;
38
39 /**
40  * Base class for workers implements everything that is needed to implement a workerthread
41  * inherit from this class when adding new workers
42  */
43 class CAmWorker
44 {
45 public:
46     CAmWorker(CAmWorkerThreadPool* pool);
47     virtual ~CAmWorker()
48     {};
49     /**
50      * needs to be overwritten, this function is called when the worker should start to work
51      */
52     void virtual start2work()=0;
53
54     /**
55      * needs to be overwritten, this function is called when the worker thread is canceled. Should be used for
56      * clean up and sending important messages
57      */
58     void virtual cancelWork()=0;
59     /**
60      * waits for a semaphore with a timeout. This leaves the Threadpool the chance to interrupt the processing
61      * You should call whenever waiting on some event, even with time=0 in order to make sure that cancel events are
62      * received
63      * @param time time until timeout in timespec format
64      * @return true if thread is canceled. Then just return start2work function so that the thread is given back to the pool
65      */
66     bool timedWait(timespec time);
67
68     /**
69      * the semaphore for cancellation is set by the thread automatically...
70      * @param cancel
71      */
72     void setCancelSempaphore(sem_t* cancel);
73     CAmWorkerThreadPool* pPool;
74 private:
75     sem_t* mCancelSem; //<! semaphore for cancellation
76 };
77
78 /**
79  * This class handles the threadpool
80  */
81 class CAmWorkerThreadPool
82 {
83 public:
84     /**
85      * creates the pool. Give the max number of threads as argument
86      * @param numThreads max number of threads
87      */
88     CAmWorkerThreadPool(int numThreads);
89     virtual ~CAmWorkerThreadPool();
90
91     /**
92      * assigns a thread to a worker class and starts working.
93      * @param worker
94      * @return the actual assigned workerID or -1 in case no thread is free
95      */
96     int16_t startWork(CAmWorker* worker);
97     /**
98      * cancels a thread
99      * @param workerID thread to be canceled
100      * @return true if thread was found, false if not
101      */
102     bool cancelWork(int workerID);
103
104     /**
105      * the workers call this function upon completion of their task
106      * @param threadID
107      */
108     void finishedWork(pthread_t threadID);
109
110 private:
111     static void* CAmWorkerThread(void* data);
112     int mNumThreads;
113     struct threadInfo_s
114     {
115         uint16_t workerID;
116         pthread_t threadID;
117         bool busy;
118         sem_t block;
119         sem_t cancel;
120         CAmWorker *worker;
121     };
122     std::vector<threadInfo_s> mListWorkers; //<! list of all workers
123     static pthread_mutex_t mBlockingMutex; //<! mutex to block the acces of the list
124 };
125
126 class CAmRoutingSenderAsync: public IAmRoutingSend
127 {
128 public:
129     CAmRoutingSenderAsync();
130     virtual ~CAmRoutingSenderAsync();
131     am_Error_e startupInterface(IAmRoutingReceive* routingreceiveinterface) ;
132     void setRoutingReady(const uint16_t handle) ;
133     void setRoutingRundown(const uint16_t handle) ;
134     am_Error_e asyncAbort(const am_Handle_s handle) ;
135     am_Error_e asyncConnect(const am_Handle_s handle, const am_connectionID_t connectionID, const am_sourceID_t sourceID, const am_sinkID_t sinkID, const am_ConnectionFormat_e connectionFormat) ;
136     am_Error_e asyncDisconnect(const am_Handle_s handle, const am_connectionID_t connectionID) ;
137     am_Error_e asyncSetSinkVolume(const am_Handle_s handle, const am_sinkID_t sinkID, const am_volume_t volume, const am_RampType_e ramp, const am_time_t time) ;
138     am_Error_e asyncSetSourceVolume(const am_Handle_s handle, const am_sourceID_t sourceID, const am_volume_t volume, const am_RampType_e ramp, const am_time_t time) ;
139     am_Error_e asyncSetSourceState(const am_Handle_s handle, const am_sourceID_t sourceID, const am_SourceState_e state) ;
140     am_Error_e asyncSetSinkSoundProperties(const am_Handle_s handle, const am_sinkID_t sinkID, const std::vector<am_SoundProperty_s>& listSoundProperties) ;
141     am_Error_e asyncSetSinkSoundProperty(const am_Handle_s handle, const am_sinkID_t sinkID, const am_SoundProperty_s& soundProperty) ;
142     am_Error_e asyncSetSourceSoundProperties(const am_Handle_s handle, const am_sourceID_t sourceID, const std::vector<am_SoundProperty_s>& listSoundProperties) ;
143     am_Error_e asyncSetSourceSoundProperty(const am_Handle_s handle, const am_sourceID_t sourceID, const am_SoundProperty_s& soundProperty) ;
144     am_Error_e asyncCrossFade(const am_Handle_s handle, const am_crossfaderID_t crossfaderID, const am_HotSink_e hotSink, const am_RampType_e rampType, const am_time_t time) ;
145     am_Error_e setDomainState(const am_domainID_t domainID, const am_DomainState_e domainState) ;
146     am_Error_e returnBusName(std::string& BusName) const ;
147     void getInterfaceVersion(std::string& version) const ;
148
149     /**
150      * threadafe insert of route and connectionID
151      * @param connectionID
152      * @param route
153      */
154     void insertConnectionSafe(am_connectionID_t connectionID, am_RoutingElement_s route);
155
156     /**
157      * threadsafe removal of a connection
158      * @param
159      */
160     void removeConnectionSafe(am_connectionID_t);
161
162     /**
163      * threadsafe remove of a handle
164      * @param handle
165      */
166     void removeHandleSafe(uint16_t handle);
167
168     /**
169      * threadsafe update of Sinkvolume
170      * @param sinkID
171      * @param volume
172      */
173     void updateSinkVolumeSafe(am_sinkID_t sinkID, am_volume_t volume);
174
175     /**
176      * threadsafe update of SourceVolume
177      * @param sourceID
178      * @param volume
179      */
180     void updateSourceVolumeSafe(am_sourceID_t sourceID, am_volume_t volume);
181
182     /**
183      * threadsafe update of sourceState
184      * @param sourceID
185      * @param state
186      */
187     void updateSourceStateSafe(am_sourceID_t sourceID, am_SourceState_e state);
188
189     /**
190      * threadsafe update of sinkSoundProperty
191      * @param sinkID
192      * @param soundProperty
193      */
194     void updateSinkSoundPropertySafe(am_sinkID_t sinkID, am_SoundProperty_s soundProperty);
195
196     /**
197      * threadsafe update of sourceSoundProperty
198      * @param sourceID
199      * @param soundProperty
200      */
201     void updateSourceSoundPropertySafe(am_sourceID_t sourceID, am_SoundProperty_s soundProperty);
202
203     /**
204      * threadsafe update of domainstate
205      * @param domainID
206      * @param domainState
207      */
208     void updateDomainstateSafe(am_domainID_t domainID, am_DomainState_e domainState);
209
210     void updateDomainListSafe(std::vector<am_Domain_s> listDomains);
211
212     void updateSourceListSafe(std::vector<am_Source_s> listSource);
213
214     void updateSinkListSafe(std::vector<am_Sink_s> listSinks);
215
216 private:
217     /**
218      * Extra thread that handles dbus stimulation for interrupt tests
219      * This is a very very very basic implementation of the dbus interface
220      * there is not failure handling, nothing.
221      * it is used just for testing, not intended to be used otherwise...
222      * @param data
223      */
224     std::vector<am_Domain_s> createDomainTable();
225     std::vector<am_Sink_s> createSinkTable();
226     std::vector<am_Source_s> createSourceTable();
227     std::vector<am_Gateway_s> createGatewayTable();
228     IAmRoutingReceiverShadow* mShadow;
229     IAmRoutingReceive* mReceiveInterface;
230     CAmSocketHandler *mSocketHandler;
231     std::vector<am_Domain_s> mDomains;
232     std::vector<am_Sink_s> mSinks;
233     std::vector<am_Source_s> mSources;
234     std::vector<am_Gateway_s> mGateways;
235     std::map<uint16_t, int16_t> mMapHandleWorker;
236     std::map<am_connectionID_t, am_RoutingElement_s> mMapConnectionIDRoute;
237     CAmWorkerThreadPool mPool;
238     pthread_t mInterruptThread;
239     static pthread_mutex_t mMapConnectionMutex;
240     static pthread_mutex_t mMapHandleWorkerMutex;
241     static pthread_mutex_t mSinksMutex;
242     static pthread_mutex_t mSourcesMutex;
243     static pthread_mutex_t mDomainsMutex;
244 };
245
246 /**
247  * worker to for connection
248  */
249 class asycConnectWorker: public CAmWorker
250 {
251 public:
252     asycConnectWorker(CAmRoutingSenderAsync * asyncSender, CAmWorkerThreadPool* pool, IAmRoutingReceiverShadow* shadow, const am_Handle_s handle, const am_connectionID_t connectionID, const am_sourceID_t sourceID, const am_sinkID_t sinkID, const am_ConnectionFormat_e connectionFormat);
253     void start2work();
254     void cancelWork();
255 private:
256     CAmRoutingSenderAsync * mAsyncSender;
257     IAmRoutingReceiverShadow *mShadow;
258     am_Handle_s mHandle;
259     am_connectionID_t mConnectionID;
260     am_sourceID_t mSourceID;
261     am_sinkID_t mSinkID;
262     am_ConnectionFormat_e mConnectionFormat;
263 };
264
265 /**
266  * worker for disconnecting
267  */
268 class asycDisConnectWorker: public CAmWorker
269 {
270 public:
271     asycDisConnectWorker(CAmRoutingSenderAsync * asyncSender, CAmWorkerThreadPool* pool, IAmRoutingReceiverShadow* shadow, const am_Handle_s handle, const am_connectionID_t connectionID);
272     void start2work();
273     void cancelWork();
274 private:
275     CAmRoutingSenderAsync * mAsyncSender;
276     IAmRoutingReceiverShadow *mShadow;
277     am_Handle_s mHandle;
278     am_connectionID_t mConnectionID;
279     am_ConnectionFormat_e mConnectionFormat;
280 };
281
282 /**
283  * worker to for connection
284  */
285
286 #include <semaphore.h>
287 #include <sys/signalfd.h>
288 #include <signal.h>
289
290 class asyncSetSinkVolumeWorker: public CAmWorker
291 {
292 public:
293     asyncSetSinkVolumeWorker(CAmRoutingSenderAsync * asyncSender, CAmWorkerThreadPool* pool, IAmRoutingReceiverShadow* shadow, const am_volume_t currentVolume, const am_Handle_s handle, const am_sinkID_t sinkID, const am_volume_t volume, const am_RampType_e ramp, const am_time_t time);
294     void start2work();
295     void cancelWork();
296 private:
297     CAmRoutingSenderAsync * mAsyncSender;
298     IAmRoutingReceiverShadow *mShadow;
299     am_volume_t mCurrentVolume;
300     am_Handle_s mHandle;
301     am_sinkID_t mSinkID;
302     am_volume_t mVolume;
303     am_RampType_e mRamp;
304     am_time_t mTime;
305 };
306
307 class asyncSetSourceVolumeWorker: public CAmWorker
308 {
309 public:
310     asyncSetSourceVolumeWorker(CAmRoutingSenderAsync * asyncSender, CAmWorkerThreadPool* pool, IAmRoutingReceiverShadow* shadow, const am_volume_t currentVolume, const am_Handle_s handle, const am_sourceID_t SourceID, const am_volume_t volume, const am_RampType_e ramp, const am_time_t time);
311     void start2work();
312     void cancelWork();
313 private:
314     CAmRoutingSenderAsync * mAsyncSender;
315     IAmRoutingReceiverShadow *mShadow;
316     am_volume_t mCurrentVolume;
317     am_Handle_s mHandle;
318     am_sourceID_t mSourceID;
319     am_volume_t mVolume;
320     am_RampType_e mRamp;
321     am_time_t mTime;
322 };
323
324 class asyncSetSourceStateWorker: public CAmWorker
325 {
326 public:
327     asyncSetSourceStateWorker(CAmRoutingSenderAsync * asyncSender, CAmWorkerThreadPool* pool, IAmRoutingReceiverShadow* shadow, const am_Handle_s handle, const am_sourceID_t sourceID, const am_SourceState_e state);
328     void start2work();
329     void cancelWork();
330 private:
331     CAmRoutingSenderAsync * mAsyncSender;
332     IAmRoutingReceiverShadow *mShadow;
333     am_Handle_s mHandle;
334     am_sourceID_t mSourceID;
335     am_SourceState_e mSourcestate;
336 };
337
338 class asyncSetSinkSoundPropertyWorker: public CAmWorker
339 {
340 public:
341     asyncSetSinkSoundPropertyWorker(CAmRoutingSenderAsync * asyncSender, CAmWorkerThreadPool* pool, IAmRoutingReceiverShadow* shadow, const am_Handle_s handle, const am_SoundProperty_s soundProperty, const am_sinkID_t sinkID);
342     void start2work();
343     void cancelWork();
344 private:
345     CAmRoutingSenderAsync * mAsyncSender;
346     IAmRoutingReceiverShadow *mShadow;
347     am_Handle_s mHandle;
348     am_sinkID_t mSinkID;
349     am_SoundProperty_s mSoundProperty;
350 };
351
352 class asyncSetSourceSoundPropertyWorker: public CAmWorker
353 {
354 public:
355     asyncSetSourceSoundPropertyWorker(CAmRoutingSenderAsync * asyncSender, CAmWorkerThreadPool* pool, IAmRoutingReceiverShadow* shadow, const am_Handle_s handle, const am_SoundProperty_s soundProperty, const am_sourceID_t sourceID);
356     void start2work();
357     void cancelWork();
358 private:
359     CAmRoutingSenderAsync * mAsyncSender;
360     IAmRoutingReceiverShadow *mShadow;
361     am_Handle_s mHandle;
362     am_sourceID_t mSourceID;
363     am_SoundProperty_s mSoundProperty;
364 };
365
366 class asyncDomainStateChangeWorker: public CAmWorker
367 {
368 public:
369     asyncDomainStateChangeWorker(CAmRoutingSenderAsync * asyncSender, CAmWorkerThreadPool* pool, IAmRoutingReceiverShadow* shadow, const am_domainID_t domainID, const am_DomainState_e domainState);
370     void start2work();
371     void cancelWork();
372 private:
373     CAmRoutingSenderAsync * mAsyncSender;
374     IAmRoutingReceiverShadow *mShadow;
375     am_domainID_t mDomainID;
376     am_DomainState_e mDomainState;
377 };
378
379 class syncRegisterWorker: public CAmWorker
380 {
381 public:
382     syncRegisterWorker(CAmRoutingSenderAsync * asyncSender, CAmWorkerThreadPool* pool, IAmRoutingReceiverShadow* shadow, const std::vector<am_Domain_s> domains, const std::vector<am_Sink_s> sinks, const std::vector<am_Source_s> sources, const  uint16_t handle);
383     void start2work();
384     void cancelWork();
385 private:
386     CAmRoutingSenderAsync * mAsyncSender;
387     IAmRoutingReceiverShadow *mShadow;
388     std::vector<am_Domain_s> mListDomains;
389     std::vector<am_Sink_s> mListSinks;
390     std::vector<am_Source_s> mListSources;
391     uint16_t mHandle;
392 };
393
394 }
395
396 #endif /* ROUTINGSENDER_H_ */