* make AudioManager rundown cleaner. Now an extra created pipe is used to trigger...
[profile/ivi/genivi/genivi-audio-manager.git] / include / shared / CAmSocketHandler.h
1 /**
2  *  Copyright (C) 2012, BMW AG
3  *
4  *  \author Christian Mueller, christian.ei.mueller@bmw.de BMW 2011,2012
5  *
6  *  \copyright
7  *  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction,
8  *  including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
9  *  subject to the following conditions:
10  *  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
11  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12  *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
13  *  THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14  *
15  *  \file CAmSocketHandler.h
16  *  For further information see http://www.genivi.org/.
17  */
18
19 #ifndef SOCKETHANDLER_H_
20 #define SOCKETHANDLER_H_
21
22 #include "audiomanagertypes.h"
23 #include <sys/socket.h>
24 #include <stdint.h>
25 #include <sys/poll.h>
26 #include <list>
27 #include <map>
28 #include <signal.h>
29
30 #include <iostream> //todo: remove me
31 namespace am
32 {
33
34 #define MAX_NS 1000000000L
35
36 static volatile sig_atomic_t gDispatchDone = 1; //this global is used to stop the mainloop
37
38 typedef uint16_t sh_timerHandle_t; //!<this is a handle for a timer to be used with the SocketHandler
39 typedef uint16_t sh_pollHandle_t; //!<this is a handle for a filedescriptor to be used with the SocketHandler
40
41 /**
42  * prototype for poll prepared callback
43  */
44 class IAmShPollPrepare
45 {
46 public:
47     virtual void Call(const sh_pollHandle_t handle, void* userData)=0;
48     virtual ~IAmShPollPrepare()
49     {
50     }
51     ;
52 };
53
54 /**
55  * prototype for poll fired callback
56  */
57 class IAmShPollFired
58 {
59 public:
60     virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)=0;
61     virtual ~ IAmShPollFired()
62     {
63     }
64     ;
65 };
66
67 /**
68  * prototype for poll check callback
69  */
70 class IAmShPollCheck
71 {
72 public:
73     virtual bool Call(const sh_pollHandle_t handle, void* userData)=0;
74     virtual ~ IAmShPollCheck()
75     {
76     }
77     ;
78 };
79
80 /**
81  * prototype for dispatch callback
82  */
83 class IAmShPollDispatch
84 {
85 public:
86     virtual bool Call(const sh_pollHandle_t handle, void* userData)=0;
87     virtual ~ IAmShPollDispatch()
88     {
89     }
90     ;
91 };
92
93 /**
94  * prototype for the timer callback
95  */
96 class IAmShTimerCallBack
97 {
98 public:
99     virtual void Call(const sh_timerHandle_t handle, void* userData)=0;
100     virtual ~IAmShTimerCallBack()
101     {
102     }
103     ;
104 };
105
106 /**
107  * The am::CAmSocketHandler implements a mainloop for the AudioManager. Plugins and different parts of the AudioManager add their filedescriptors to the handler
108  * to get called on communication of the filedescriptors.\n
109  * More information can be found here : \ref mainl
110  */
111 class CAmSocketHandler
112 {
113 public:
114     template<class TClass> class TAmShPollFired: public IAmShPollFired
115     {
116     private:
117         TClass* mInstance;
118         void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
119
120     public:
121         TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) :
122                 mInstance(instance), //
123                 mFunction(function) {};
124
125         virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
126         {
127             (*mInstance.*mFunction)(pollfd, handle, userData);
128         };
129     };
130
131     template<class TClass> class TAmShPollCheck: public IAmShPollCheck
132     {
133     private:
134         TClass* mInstance;
135         bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
136
137     public:
138         TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
139                 mInstance(instance), //
140                 mFunction(function) {};
141
142         virtual bool Call(const sh_pollHandle_t handle, void* userData)
143         {
144             return ((*mInstance.*mFunction)(handle, userData));
145         };
146     };
147
148     CAmSocketHandler();
149     ~CAmSocketHandler();
150
151     am_Error_e addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void* userData, sh_pollHandle_t& handle);
152     am_Error_e removeFDPoll(const sh_pollHandle_t handle);
153     am_Error_e updateEventFlags(const sh_pollHandle_t handle, const short events);
154     am_Error_e addTimer(const timespec timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void* userData);
155     am_Error_e removeTimer(const sh_timerHandle_t handle);
156     am_Error_e restartTimer(const sh_timerHandle_t handle);
157     am_Error_e updateTimer(const sh_timerHandle_t handle, const timespec timeouts);
158     am_Error_e stopTimer(const sh_timerHandle_t handle);
159     void start_listenting();
160     void stop_listening();
161     void exit_mainloop();
162     static void static_exit_mainloop();
163     void receiverCallback(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
164         {
165             (void) pollfd;
166             (void) handle;
167             (void) userData;
168         };
169     bool checkerCallback(const sh_pollHandle_t handle, void* userData)
170         {
171             (void) handle;
172             (void) userData;
173             return (false);
174         };
175
176     TAmShPollFired<CAmSocketHandler> receiverCallbackT;
177     TAmShPollCheck<CAmSocketHandler> checkerCallbackT;
178
179 private:
180
181     static CAmSocketHandler* mInstance;
182     int mPipe[2];
183
184     struct sh_timer_s //!<struct that holds information of timers
185     {
186         sh_timerHandle_t handle; //!<the handle of the timer
187         timespec countdown; //!<the countdown, this value is decreased every time the timer is up
188         IAmShTimerCallBack* callback; //!<the callbackfunction
189         void * userData; //!<saves a void pointer together with the rest.
190     };
191
192     typedef std::reverse_iterator<sh_timer_s> rListTimerIter; //!<typedef for reverseiterator on timer lists
193
194     struct sh_poll_s //!<struct that holds information about polls
195     {
196         sh_pollHandle_t handle; //!<handle to uniquely adress a filedesriptor
197         IAmShPollPrepare *prepareCB; //!<pointer to preperation callback
198         IAmShPollFired *firedCB; //!<pointer to fired callback
199         IAmShPollCheck *checkCB; //!< pointer to check callback
200         IAmShPollDispatch *dispatchCB; //!<pointer to dispatch callback
201         pollfd pollfdValue; //!<the array for polling the filedescriptors
202         void *userData; //!<userdata saved together with the callback.
203     };
204
205     typedef std::vector<pollfd> mListPollfd_t; //!<vector of filedescriptors
206     typedef std::vector<sh_poll_s> mListPoll_t; //!<list for the callbacks
207
208     bool fdIsValid(const int fd) const;
209     void timerUp();
210     void timerCorrection();
211     timespec* insertTime(timespec& buffertime);
212
213     /**
214      * compares countdown values
215      * @param a
216      * @param b
217      * @return true if b greater a
218      */
219     inline static bool compareCountdown(const sh_timer_s& a, const sh_timer_s& b)
220     {
221         return ((a.countdown.tv_sec == b.countdown.tv_sec) ? (a.countdown.tv_nsec < b.countdown.tv_nsec) : (a.countdown.tv_sec < b.countdown.tv_sec));
222     }
223
224     /**
225      * Subtracts b from a
226      * @param a
227      * @param b
228      * @return subtracted value
229      */
230     inline static timespec timespecSub(const timespec& a, const timespec& b)
231     {
232         timespec result;
233
234         if ((a.tv_sec < b.tv_sec) || ((a.tv_sec == b.tv_sec) && (a.tv_nsec <= b.tv_nsec)))
235         {
236             result.tv_sec = result.tv_nsec = 0;
237         }
238         else
239         {
240             result.tv_sec = a.tv_sec - b.tv_sec;
241             if (a.tv_nsec < b.tv_nsec)
242             {
243                 result.tv_nsec = a.tv_nsec + MAX_NS - b.tv_nsec;
244                 result.tv_sec--; /* Borrow a second. */
245             }
246             else
247             {
248                 result.tv_nsec = a.tv_nsec - b.tv_nsec;
249             }
250         }
251         return (result);
252     }
253
254     /**
255      * adds timespec values
256      * @param a
257      * @param b
258      * @return the added values
259      */
260     inline timespec timespecAdd(const timespec& a, const timespec& b)
261     {
262         timespec result;
263         result.tv_sec = a.tv_sec + b.tv_sec;
264         result.tv_nsec = a.tv_nsec + b.tv_nsec;
265         if (result.tv_nsec >= MAX_NS)
266         {
267             result.tv_sec++;
268             result.tv_nsec = result.tv_nsec - MAX_NS;
269         }
270         return (result);
271     }
272
273     /**
274      * comapares timespec values
275      * @param a
276      * @param b
277      * @return
278      */
279     inline int timespecCompare(const timespec& a, const timespec& b)
280     {
281         //less
282         if (a.tv_sec < b.tv_sec)
283             return (-1);
284         //greater
285         else if (a.tv_sec > b.tv_sec)
286             return (1);
287         //less
288         else if (a.tv_nsec < b.tv_nsec)
289             return (-1);
290         //greater
291         else if (a.tv_nsec > b.tv_nsec)
292             return (1);
293         //equal
294         else
295             return (0);
296     }
297
298     /**
299      * functor to return all fired events
300      * @param a
301      * @return
302      */
303     inline static bool eventFired(const pollfd& a)
304     {
305         return (a.revents == 0 ? false : true);
306     }
307
308     /**
309      * functor to help find the items that do not need dispatching
310      * @param a
311      * @return
312      */
313     inline static bool noDispatching(const sh_poll_s& a)
314     {
315         //remove from list of there is no checkCB
316         if (!a.checkCB)
317             return (true);
318         return (!a.checkCB->Call(a.handle, a.userData));
319     }
320
321     /**
322      * checks if dispatching is already finished
323      * @param a
324      * @return
325      */
326     inline static bool dispatchingFinished(const sh_poll_s& a)
327     {
328         //remove from list of there is no dispatchCB
329         if (!a.dispatchCB)
330             return (true);
331         return (!a.dispatchCB->Call(a.handle, a.userData));
332     }
333
334     class CAmShCopyPollfd //!< functor to copy filedescriptors into the poll array
335     {
336     private:
337         mListPollfd_t& mArray;
338     public:
339         CAmShCopyPollfd(mListPollfd_t& dest) :
340                 mArray(dest)
341         {
342         }
343         void operator()(const sh_poll_s& row)
344         {
345             pollfd temp = row.pollfdValue;
346             temp.revents = 0;
347             mArray.push_back(temp);
348         }
349     };
350
351     class CAmShCallFire //!< functor to call the firecallbacks
352     {
353     public:
354         CAmShCallFire()
355         {
356         }
357         ;
358         void operator()(sh_poll_s& row)
359         {
360             row.firedCB->Call(row.pollfdValue, row.handle, row.userData);
361         }
362     };
363
364     class CAmShCallPrep //!< functor to call the preparation callbacks
365     {
366     public:
367         CAmShCallPrep()
368         {
369         }
370         ;
371         void operator()(sh_poll_s& row)
372         {
373             if (row.prepareCB)
374                 row.prepareCB->Call(row.handle, row.userData);
375         }
376     };
377
378     class CAmShCallTimer //!<functor to call a timer
379     {
380     public:
381         CAmShCallTimer()
382         {
383         }
384         ;
385         void operator()(sh_timer_s& row)
386         {
387             row.callback->Call(row.handle, row.userData);
388         }
389     };
390
391     class CAmShCountdownUp //!<functor that checks if a timer is up
392     {
393     private:
394         timespec mDiffTime;
395     public:
396         CAmShCountdownUp(const timespec& differenceTime) :
397                 mDiffTime(differenceTime)
398         {
399         }
400         ;
401         bool operator()(const sh_timer_s& row)
402         {
403             timespec sub = timespecSub(row.countdown, mDiffTime);
404             if (sub.tv_nsec == 0 && sub.tv_sec == 0)
405                 return (true);
406             return (false);
407         }
408     };
409
410     class CAmShCountdownZero //!<functor that checks if a timer is zero
411     {
412     public:
413         CAmShCountdownZero()
414         {
415         }
416         ;
417         bool operator()(const sh_timer_s& row)
418         {
419             if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
420                 return (true);
421             return (false);
422         }
423     };
424
425     class CAmShSubstractTime //!<functor to easy substract from each countdown value
426     {
427     private:
428         timespec param;
429     public:
430         CAmShSubstractTime(timespec param) :
431                 param(param)
432         {
433         }
434         inline void operator()(sh_timer_s& t)
435         {
436             t.countdown = timespecSub(t.countdown, param);
437         }
438     };
439
440     mListPollfd_t mfdPollingArray; //!<the polling array for ppoll
441     mListPoll_t mListPoll; //!<list that holds all information for the ppoll
442     std::list<sh_timer_s> mListTimer; //!<list of all timers
443     std::list<sh_timer_s> mListActiveTimer; //!<list of all currently active timers
444     sh_timerHandle_t mLastInsertedHandle; //!<keeps track of the last inserted timer handle
445     sh_pollHandle_t mLastInsertedPollHandle; //!<keeps track of the last inserted poll handle
446     bool mRecreatePollfds; //!<when this is true, the poll list needs to be recreated
447     timespec mStartTime; //!<here the actual time is saved for timecorrection
448
449 //    void debugPrintTimerList ()
450 //    {
451 //        std::list<sh_timer_s>::iterator it(mListActiveTimer.begin());
452 //        for(;it!=mListActiveTimer.end();++it)
453 //        {
454 //            std::cout<< "Handle " << it->handle << "sec " << it->countdown.tv_sec << "nsec " << it->countdown.tv_nsec<<std::endl;
455 //        }
456 //    }
457 }
458 ;
459
460 /**
461  * template to create the functor for a class
462  */
463 template<class TClass> class TAmShTimerCallBack: public IAmShTimerCallBack
464 {
465 private:
466     TClass* mInstance;
467     void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData);
468
469 public:
470     TAmShTimerCallBack(TClass* instance, void (TClass::*function)(sh_timerHandle_t handle, void* userData)) :
471             mInstance(instance), //
472             mFunction(function)
473     {
474     }
475     ;
476
477     virtual void Call(sh_timerHandle_t handle, void* userData)
478     {
479         (*mInstance.*mFunction)(handle, userData);
480     }
481 };
482
483 /**
484  * template for a callback
485  */
486 template<class TClass> class TAmShPollPrepare: public IAmShPollPrepare
487 {
488 private:
489     TClass* mInstance;
490     void (TClass::*mFunction)(const sh_timerHandle_t handle, void* userData);
491
492 public:
493     TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_timerHandle_t handle, void* userData)) :
494             mInstance(instance), //
495             mFunction(function)
496     {
497     }
498     ;
499
500     virtual void Call(const sh_timerHandle_t handle, void* userData)
501     {
502         (*mInstance.*mFunction)(handle, userData);
503     }
504     ;
505 };
506
507 /**make private, not public
508  * template for a callback
509  */
510 template<class TClass> class TAmShPollFired: public IAmShPollFired
511 {
512 private:
513     TClass* mInstance;
514     void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
515
516 public:
517     TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) :
518             mInstance(instance), //
519             mFunction(function)
520     {
521     }
522     ;
523
524     virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
525     {
526         (*mInstance.*mFunction)(pollfd, handle, userData);
527     }
528     ;
529 };
530
531 /**
532  * template for a callback
533  */
534 template<class TClass> class TAmShPollCheck: public IAmShPollCheck
535 {
536 private:
537     TClass* mInstance;
538     bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
539
540 public:
541     TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
542             mInstance(instance), //
543             mFunction(function)
544     {
545     }
546     ;
547
548     virtual bool Call(const sh_pollHandle_t handle, void* userData)
549     {
550         return ((*mInstance.*mFunction)(handle, userData));
551     }
552     ;
553 };
554
555 /**
556  * template for a callback
557  */
558 template<class TClass> class TAmShPollDispatch: public IAmShPollDispatch
559 {
560 private:
561     TClass* mInstance;
562     bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
563
564 public:
565     TAmShPollDispatch(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
566             mInstance(instance), //
567             mFunction(function)
568     {
569     }
570     ;
571
572     virtual bool Call(const sh_pollHandle_t handle, void* userData)
573     {
574         return ((*mInstance.*mFunction)(handle, userData));
575     }
576     ;
577 };
578 } /* namespace am */
579 #endif /* SOCKETHANDLER_H_ */