- add more python stuff
[enigma2.git] / lib / base / ebase.cpp
1 #include <lib/base/ebase.h>
2
3 #include <fcntl.h>
4 #include <unistd.h>
5
6 #include <lib/base/eerror.h>
7
8 eSocketNotifier::eSocketNotifier(eMainloop *context, int fd, int requested, bool startnow): context(*context), fd(fd), state(0), requested(requested)
9 {
10         if (startnow)   
11                 start();
12 }
13
14 eSocketNotifier::~eSocketNotifier()
15 {
16         stop();
17 }
18
19 void eSocketNotifier::start()
20 {
21         if (state)
22                 stop();
23
24         context.addSocketNotifier(this);
25         state=1;
26 }
27
28 void eSocketNotifier::stop()
29 {
30         if (state)
31                 context.removeSocketNotifier(this);
32
33         state=0;
34 }
35
36                                         // timer
37 void eTimer::start(long msek, bool singleShot)
38 {
39         if (bActive)
40                 stop();
41
42         bActive = true;
43         bSingleShot = singleShot;
44         interval = msek;
45         gettimeofday(&nextActivation, 0);               
46 //      eDebug("this = %p\nnow sec = %d, usec = %d\nadd %d msec", this, nextActivation.tv_sec, nextActivation.tv_usec, msek);
47         nextActivation += (msek<0 ? 0 : msek);
48 //      eDebug("next Activation sec = %d, usec = %d", nextActivation.tv_sec, nextActivation.tv_usec );
49         context.addTimer(this);
50 }
51
52 void eTimer::stop()
53 {
54         if (bActive)
55         {
56                 bActive=false;
57                 context.removeTimer(this);
58         }
59 }
60
61 void eTimer::changeInterval(long msek)
62 {
63         if (bActive)  // Timer is running?
64         {
65                 context.removeTimer(this);       // then stop
66                 nextActivation -= interval;  // sub old interval
67         }
68         else
69                 bActive=true;   // then activate Timer
70
71         interval = msek;                                                // set new Interval
72         nextActivation += interval;             // calc nextActivation
73
74         context.addTimer(this);                         // add Timer to context TimerList
75 }
76
77 void eTimer::activate()   // Internal Funktion... called from eApplication
78 {
79         timeval now;
80         gettimeofday(&now, 0);
81 //      eDebug("this = %p\nnow sec = %d, usec = %d\nnextActivation sec = %d, usec = %d", this, now.tv_sec, now.tv_usec, nextActivation.tv_sec, nextActivation.tv_usec );
82 //      eDebug("Timer emitted");
83         context.removeTimer(this);
84
85         if (!bSingleShot)
86         {
87                 nextActivation += interval;
88                 context.addTimer(this);
89         }
90         else
91                 bActive=false;
92
93         /*emit*/ timeout();
94 }
95
96 // mainloop
97
98 void eMainloop::addSocketNotifier(eSocketNotifier *sn)
99 {
100         notifiers.insert(std::pair<int,eSocketNotifier*> (sn->getFD(), sn));
101 }
102
103 void eMainloop::removeSocketNotifier(eSocketNotifier *sn)
104 {
105         notifiers.erase(sn->getFD());
106 }
107
108 void eMainloop::processOneEvent()
109 {
110 // process pending timers...
111         long usec=0;
112
113         while (TimerList && (usec = timeout_usec( TimerList.begin()->getNextActivation() ) ) <= 0 )
114                 TimerList.begin()->activate();
115
116         int fdAnz = notifiers.size();
117         pollfd* pfd = new pollfd[fdAnz];  // make new pollfd array
118
119 // fill pfd array
120         std::map<int,eSocketNotifier*>::iterator it(notifiers.begin());
121         for (int i=0; i < fdAnz; i++, it++)
122         {
123                 pfd[i].fd = it->first;
124                 pfd[i].events = it->second->getRequested();
125         }
126
127         int ret=poll(pfd, fdAnz, TimerList ? usec / 1000 : -1);  // milli .. not micro seks
128
129         if (ret>0)
130         {
131 //              eDebug("bin aussem poll raus und da war was");
132                 for (int i=0; i < fdAnz ; i++)
133                 {
134                         if( notifiers.find(pfd[i].fd) == notifiers.end())
135                                 continue;
136
137                         int req = notifiers[pfd[i].fd]->getRequested();
138
139                         if ( pfd[i].revents & req )
140                         {
141                                 notifiers[pfd[i].fd]->activate(pfd[i].revents);
142
143                                 if (!--ret)
144                                         break;
145                         } else if (pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL))
146                                 eDebug("poll: unhandled POLLERR/HUP/NVAL for fd %d(%d)", pfd[i].fd,pfd[i].revents);
147                 }
148         }
149         else if (ret<0)
150                 eDebug("poll made error");
151
152                 // check Timers...
153         while ( TimerList && timeout_usec( TimerList.begin()->getNextActivation() ) <= 0 )
154                 TimerList.begin()->activate();
155
156         delete [] pfd;
157 }
158
159
160 int eMainloop::exec()
161 {
162         if (!loop_level)
163         {
164                 app_quit_now = false;
165                 enter_loop();
166         }
167         return retval;
168 }
169
170 void eMainloop::enter_loop()
171 {
172         loop_level++;
173
174         // Status der vorhandenen Loop merken
175         bool old_exit_loop = app_exit_loop;
176         
177         app_exit_loop = false;
178
179         while (!app_exit_loop && !app_quit_now)
180         {
181                 processOneEvent();
182         }
183
184         // wiederherstellen der vorherigen app_exit_loop
185         app_exit_loop = old_exit_loop;
186
187         loop_level--;
188
189         if (!loop_level)
190         {
191                         // do something here on exit the last loop
192         }
193 }
194
195 void eMainloop::exit_loop()  // call this to leave the current loop
196 {
197         app_exit_loop = true;   
198 }
199
200 void eMainloop::quit( int ret )   // call this to leave all loops
201 {
202         retval=ret;
203         app_quit_now = true;
204 }
205
206 eApplication* eApp = 0;