c678537eb5520c353354ecfd6b8f72e6cee99bd7
[profile/ivi/pulseaudio.git] / polyp / mainloop.c
1 /* $Id$ */
2
3 /***
4   This file is part of polypaudio.
5  
6   polypaudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published
8   by the Free Software Foundation; either version 2 of the License,
9   or (at your option) any later version.
10  
11   polypaudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15  
16   You should have received a copy of the GNU General Public License
17   along with polypaudio; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <signal.h>
28 #include <unistd.h>
29 #include <sys/poll.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <assert.h>
33 #include <fcntl.h>
34 #include <errno.h>
35
36 #include "mainloop.h"
37 #include "util.h"
38 #include "idxset.h"
39 #include "xmalloc.h"
40
41 struct pa_base_event {
42 };
43
44 struct pa_io_event {
45     struct pa_mainloop *mainloop;
46     int dead;
47     int fd;
48     enum pa_io_event_flags events;
49     void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata);
50     struct pollfd *pollfd;
51     void *userdata;
52     void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata);
53 };
54
55 struct pa_time_event {
56     struct pa_mainloop *mainloop;
57     int dead;
58     int enabled;
59     struct timeval timeval;
60     void (*callback)(struct pa_mainloop_api*a, struct pa_time_event *e, const struct timeval*tv, void *userdata);
61     void *userdata;
62     void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata);
63 };
64
65 struct pa_defer_event {
66     struct pa_mainloop *mainloop;
67     int dead;
68     int enabled;
69     void (*callback)(struct pa_mainloop_api*a, struct pa_defer_event*e, void *userdata);
70     void *userdata;
71     void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata);
72 };
73
74 struct pa_mainloop {
75     struct pa_idxset *io_events, *time_events, *defer_events;
76     int io_events_scan_dead, defer_events_scan_dead, time_events_scan_dead;
77
78     struct pollfd *pollfds;
79     unsigned max_pollfds, n_pollfds;
80     int rebuild_pollfds;
81
82     int quit, running, retval;
83     struct pa_mainloop_api api;
84 };
85
86 /* IO events */
87 static struct pa_io_event* mainloop_io_new(struct pa_mainloop_api*a, int fd, enum pa_io_event_flags events, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata) {
88     struct pa_mainloop *m;
89     struct pa_io_event *e;
90
91     assert(a && a->userdata && fd >= 0 && callback);
92     m = a->userdata;
93     assert(a == &m->api);
94
95     e = pa_xmalloc(sizeof(struct pa_io_event));
96     e->mainloop = m;
97     e->dead = 0;
98
99     e->fd = fd;
100     e->events = events;
101     e->callback = callback;
102     e->userdata = userdata;
103     e->destroy_callback = NULL;
104     e->pollfd = NULL;
105
106     pa_idxset_put(m->io_events, e, NULL);
107     m->rebuild_pollfds = 1;
108     return e;
109 }
110
111 static void mainloop_io_enable(struct pa_io_event *e, enum pa_io_event_flags events) {
112     assert(e && e->mainloop);
113
114     e->events = events;
115     if (e->pollfd)
116         e->pollfd->events =
117             (events & PA_IO_EVENT_INPUT ? POLLIN : 0) |
118             (events & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) |
119             POLLHUP |
120             POLLERR;
121 }
122
123 static void mainloop_io_free(struct pa_io_event *e) {
124     assert(e && e->mainloop);
125     e->dead = e->mainloop->io_events_scan_dead = e->mainloop->rebuild_pollfds = 1;
126 }
127
128 static void mainloop_io_set_destroy(struct pa_io_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata)) {
129     assert(e);
130     e->destroy_callback = callback;
131 }
132
133 /* Defer events */
134 struct pa_defer_event* mainloop_defer_new(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata), void *userdata) {
135     struct pa_mainloop *m;
136     struct pa_defer_event *e;
137
138     assert(a && a->userdata && callback);
139     m = a->userdata;
140     assert(a == &m->api);
141
142     e = pa_xmalloc(sizeof(struct pa_defer_event));
143     e->mainloop = m;
144     e->dead = 0;
145
146     e->enabled = 1;
147     e->callback = callback;
148     e->userdata = userdata;
149     e->destroy_callback = NULL;
150
151     pa_idxset_put(m->defer_events, e, NULL);
152     return e;
153 }
154
155 static void mainloop_defer_enable(struct pa_defer_event *e, int b) {
156     assert(e);
157     e->enabled = b;
158 }
159
160 static void mainloop_defer_free(struct pa_defer_event *e) {
161     assert(e);
162     e->dead = e->mainloop->defer_events_scan_dead = 1;
163 }
164
165 static void mainloop_defer_set_destroy(struct pa_defer_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata)) {
166     assert(e);
167     e->destroy_callback = callback;
168 }
169
170 /* Time events */
171 static struct pa_time_event* mainloop_time_new(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) {
172     struct pa_mainloop *m;
173     struct pa_time_event *e;
174
175     assert(a && a->userdata && callback);
176     m = a->userdata;
177     assert(a == &m->api);
178
179     e = pa_xmalloc(sizeof(struct pa_time_event));
180     e->mainloop = m;
181     e->dead = 0;
182
183     e->enabled = !!tv;
184     if (tv)
185         e->timeval = *tv;
186
187     e->callback = callback;
188     e->userdata = userdata;
189     e->destroy_callback = NULL;
190
191     pa_idxset_put(m->time_events, e, NULL);
192     return e;
193 }
194
195 static void mainloop_time_restart(struct pa_time_event *e, const struct timeval *tv) {
196     assert(e);
197
198     if (tv) {
199         e->enabled = 1;
200         e->timeval = *tv;
201     } else
202         e->enabled = 0;
203 }
204
205 static void mainloop_time_free(struct pa_time_event *e) {
206     assert(e);
207     e->dead = e->mainloop->time_events_scan_dead = 1;
208 }
209
210 static void mainloop_time_set_destroy(struct pa_time_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata)) {
211     assert(e);
212     e->destroy_callback = callback;
213 }
214
215 /* quit() */
216
217 static void mainloop_quit(struct pa_mainloop_api*a, int retval) {
218     struct pa_mainloop *m;
219     assert(a && a->userdata);
220     m = a->userdata;
221     assert(a == &m->api);
222
223     m->quit = 1;
224     m->retval = retval;
225 }
226     
227 static const struct pa_mainloop_api vtable = {
228     userdata: NULL,
229
230     io_new: mainloop_io_new,
231     io_enable: mainloop_io_enable,
232     io_free: mainloop_io_free,
233     io_set_destroy: mainloop_io_set_destroy,
234
235     time_new : mainloop_time_new,
236     time_restart : mainloop_time_restart,
237     time_free : mainloop_time_free,
238     time_set_destroy : mainloop_time_set_destroy,
239     
240     defer_new : mainloop_defer_new,
241     defer_enable : mainloop_defer_enable,
242     defer_free : mainloop_defer_free,
243     defer_set_destroy : mainloop_defer_set_destroy,
244     
245     quit : mainloop_quit,
246 };
247
248 struct pa_mainloop *pa_mainloop_new(void) {
249     struct pa_mainloop *m;
250
251     m = pa_xmalloc(sizeof(struct pa_mainloop));
252
253     m->io_events = pa_idxset_new(NULL, NULL);
254     m->defer_events = pa_idxset_new(NULL, NULL);
255     m->time_events = pa_idxset_new(NULL, NULL);
256
257     assert(m->io_events && m->defer_events && m->time_events);
258
259     m->io_events_scan_dead = m->defer_events_scan_dead = m->time_events_scan_dead = 0;
260     
261     m->pollfds = NULL;
262     m->max_pollfds = m->n_pollfds = m->rebuild_pollfds = 0;
263
264     m->quit = m->running = m->retval = 0;
265
266     m->api = vtable;
267     m->api.userdata = m;
268     
269     return m;
270 }
271
272 static int io_foreach(void *p, uint32_t index, int *del, void*userdata) {
273     struct pa_io_event *e = p;
274     int *all = userdata;
275     assert(e && del && all);
276
277     if (!*all || !e->dead)
278         return 0;
279     
280     if (e->destroy_callback)
281         e->destroy_callback(&e->mainloop->api, e, e->userdata);
282     pa_xfree(e);
283     *del = 1;
284     return 0;
285 };
286
287 static int time_foreach(void *p, uint32_t index, int *del, void*userdata) {
288     struct pa_time_event *e = p;
289     int *all = userdata;
290     assert(e && del && all);
291
292     if (!*all || !e->dead)
293         return 0;
294     
295     if (e->destroy_callback)
296         e->destroy_callback(&e->mainloop->api, e, e->userdata);
297     pa_xfree(e);
298     *del = 1;
299     return 0;
300 };
301
302 static int defer_foreach(void *p, uint32_t index, int *del, void*userdata) {
303     struct pa_defer_event *e = p;
304     int *all = userdata;
305     assert(e && del && all);
306
307     if (!*all || !e->dead)
308         return 0;
309     
310     if (e->destroy_callback)
311         e->destroy_callback(&e->mainloop->api, e, e->userdata);
312     pa_xfree(e);
313     *del = 1;
314     return 0;
315 };
316
317 void pa_mainloop_free(struct pa_mainloop* m) {
318     int all = 1;
319     assert(m);
320
321     pa_idxset_foreach(m->io_events, io_foreach, &all);
322     pa_idxset_foreach(m->time_events, time_foreach, &all);
323     pa_idxset_foreach(m->defer_events, defer_foreach, &all);
324
325     pa_idxset_free(m->io_events, NULL, NULL);
326     pa_idxset_free(m->time_events, NULL, NULL);
327     pa_idxset_free(m->defer_events, NULL, NULL);
328
329     pa_xfree(m->pollfds);
330     pa_xfree(m);
331 }
332
333 static void scan_dead(struct pa_mainloop *m) {
334     int all = 0;
335     assert(m);
336     if (m->io_events_scan_dead)
337         pa_idxset_foreach(m->io_events, io_foreach, &all);
338     if (m->time_events_scan_dead)
339         pa_idxset_foreach(m->time_events, time_foreach, &all);
340     if (m->defer_events_scan_dead)
341         pa_idxset_foreach(m->defer_events, defer_foreach, &all);
342 }
343
344 static void rebuild_pollfds(struct pa_mainloop *m) {
345     struct pa_io_event*e;
346     struct pollfd *p;
347     uint32_t index = PA_IDXSET_INVALID;
348     unsigned l;
349
350     l = pa_idxset_ncontents(m->io_events);
351     if (m->max_pollfds < l) {
352         m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l);
353         m->max_pollfds = l;
354     }
355
356     m->n_pollfds = 0;
357     p = m->pollfds;
358     for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) {
359         if (e->dead) {
360             e->pollfd = NULL;
361             continue;
362         }
363
364         e->pollfd = p;
365         p->fd = e->fd;
366         p->events =
367             ((e->events & PA_IO_EVENT_INPUT) ? POLLIN : 0) |
368             ((e->events & PA_IO_EVENT_OUTPUT) ? POLLOUT : 0) |
369             POLLHUP |
370             POLLERR;
371         p->revents = 0;
372
373         p++;
374         m->n_pollfds++;
375     }
376 }
377
378 static void dispatch_pollfds(struct pa_mainloop *m) {
379     uint32_t index = PA_IDXSET_INVALID;
380     struct pa_io_event *e;
381
382     for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) {
383         if (e->dead || !e->pollfd || !e->pollfd->revents)
384             continue;
385         
386         assert(e->pollfd->fd == e->fd && e->callback);
387         e->callback(&m->api, e, e->fd,
388                     (e->pollfd->revents & POLLHUP ? PA_IO_EVENT_HANGUP : 0) |
389                     (e->pollfd->revents & POLLIN ? PA_IO_EVENT_INPUT : 0) |
390                     (e->pollfd->revents & POLLOUT ? PA_IO_EVENT_OUTPUT : 0) |
391                     (e->pollfd->revents & POLLERR ? PA_IO_EVENT_ERROR : 0),
392                     e->userdata);
393         e->pollfd->revents = 0;
394     }
395 }
396
397 static void dispatch_defer(struct pa_mainloop *m) {
398     uint32_t index;
399     struct pa_defer_event *e;
400
401     for (e = pa_idxset_first(m->defer_events, &index); e; e = pa_idxset_next(m->defer_events, &index)) {
402         if (e->dead || !e->enabled)
403             continue;
404
405         assert(e->callback);
406         e->callback(&m->api, e, e->userdata);
407     }
408 }
409
410 static int calc_next_timeout(struct pa_mainloop *m) {
411     uint32_t index;
412     struct pa_time_event *e;
413     struct timeval now;
414     int t = -1;
415
416     if (pa_idxset_isempty(m->time_events))
417         return -1;
418
419     gettimeofday(&now, NULL);
420     
421     for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) {
422         int tmp;
423         
424         if (e->dead || !e->enabled)
425             continue;
426
427         if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec)) 
428             return 0;
429
430         tmp = (e->timeval.tv_sec - now.tv_sec)*1000;
431             
432         if (e->timeval.tv_usec > now.tv_usec)
433             tmp += (e->timeval.tv_usec - now.tv_usec)/1000;
434         else
435             tmp -= (now.tv_usec - e->timeval.tv_usec)/1000;
436
437         if (tmp == 0)
438             return 0;
439         else if (t == -1 || tmp < t)
440             t = tmp;
441     }
442
443     return t;
444 }
445
446 static void dispatch_timeout(struct pa_mainloop *m) {
447     uint32_t index;
448     struct pa_time_event *e;
449     struct timeval now;
450     assert(m);
451
452     if (pa_idxset_isempty(m->time_events))
453         return;
454
455     gettimeofday(&now, NULL);
456     for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) {
457         
458         if (e->dead || !e->enabled)
459             continue;
460
461         if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec)) {
462             assert(e->callback);
463
464             e->enabled = 0;
465             e->callback(&m->api, e, &e->timeval, e->userdata);
466         }
467     }
468 }
469
470 int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) {
471     int r;
472     assert(m && !m->running);
473     
474     if(m->quit) {
475         if (retval)
476             *retval = m->retval;
477         return 1;
478     }
479
480     m->running = 1;
481
482     scan_dead(m);
483     dispatch_defer(m);
484
485     if (m->rebuild_pollfds) {
486         rebuild_pollfds(m);
487         m->rebuild_pollfds = 0;
488     }
489
490     do {
491         int t = block ? calc_next_timeout(m) : 0;
492         /*fprintf(stderr, "%u\n", t);*/
493         r = poll(m->pollfds, m->n_pollfds, t);
494     } while (r < 0 && errno == EINTR);
495
496     dispatch_timeout(m);
497     
498     if (r > 0)
499         dispatch_pollfds(m);
500     else if (r < 0)
501         fprintf(stderr, "select(): %s\n", strerror(errno));
502     
503     m->running = 0;
504     return r < 0 ? -1 : 0;
505 }
506
507 int pa_mainloop_run(struct pa_mainloop *m, int *retval) {
508     int r;
509     while ((r = pa_mainloop_iterate(m, 1, retval)) == 0);
510     return r;
511 }
512
513 void pa_mainloop_quit(struct pa_mainloop *m, int r) {
514     assert(m);
515     m->quit = r;
516 }
517
518 struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m) {
519     assert(m);
520     return &m->api;
521 }