4 This file is part of polypaudio.
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.
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.
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
42 struct pa_mainloop
*mainloop
;
45 enum pa_io_event_flags events
;
46 void (*callback
) (struct pa_mainloop_api
*a
, struct pa_io_event
*e
, int fd
, enum pa_io_event_flags f
, void *userdata
);
47 struct pollfd
*pollfd
;
49 void (*destroy_callback
) (struct pa_mainloop_api
*a
, struct pa_io_event
*e
, void *userdata
);
52 struct pa_time_event
{
53 struct pa_mainloop
*mainloop
;
56 struct timeval timeval
;
57 void (*callback
)(struct pa_mainloop_api
*a
, struct pa_time_event
*e
, const struct timeval
*tv
, void *userdata
);
59 void (*destroy_callback
) (struct pa_mainloop_api
*a
, struct pa_time_event
*e
, void *userdata
);
62 struct pa_defer_event
{
63 struct pa_mainloop
*mainloop
;
66 void (*callback
)(struct pa_mainloop_api
*a
, struct pa_defer_event
*e
, void *userdata
);
68 void (*destroy_callback
) (struct pa_mainloop_api
*a
, struct pa_defer_event
*e
, void *userdata
);
72 struct pa_idxset
*io_events
, *time_events
, *defer_events
;
73 int io_events_scan_dead
, defer_events_scan_dead
, time_events_scan_dead
;
75 struct pollfd
*pollfds
;
76 unsigned max_pollfds
, n_pollfds
;
79 int quit
, running
, retval
;
80 struct pa_mainloop_api api
;
84 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
) {
85 struct pa_mainloop
*m
;
86 struct pa_io_event
*e
;
88 assert(a
&& a
->userdata
&& fd
>= 0 && callback
);
92 e
= pa_xmalloc(sizeof(struct pa_io_event
));
98 e
->callback
= callback
;
99 e
->userdata
= userdata
;
100 e
->destroy_callback
= NULL
;
103 pa_idxset_put(m
->io_events
, e
, NULL
);
104 m
->rebuild_pollfds
= 1;
108 static void mainloop_io_enable(struct pa_io_event
*e
, enum pa_io_event_flags events
) {
109 assert(e
&& e
->mainloop
);
114 (events
& PA_IO_EVENT_INPUT
? POLLIN
: 0) |
115 (events
& PA_IO_EVENT_OUTPUT
? POLLOUT
: 0) |
120 static void mainloop_io_free(struct pa_io_event
*e
) {
121 assert(e
&& e
->mainloop
);
122 e
->dead
= e
->mainloop
->io_events_scan_dead
= e
->mainloop
->rebuild_pollfds
= 1;
125 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
)) {
127 e
->destroy_callback
= callback
;
131 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
) {
132 struct pa_mainloop
*m
;
133 struct pa_defer_event
*e
;
135 assert(a
&& a
->userdata
&& callback
);
137 assert(a
== &m
->api
);
139 e
= pa_xmalloc(sizeof(struct pa_defer_event
));
144 e
->callback
= callback
;
145 e
->userdata
= userdata
;
146 e
->destroy_callback
= NULL
;
148 pa_idxset_put(m
->defer_events
, e
, NULL
);
152 static void mainloop_defer_enable(struct pa_defer_event
*e
, int b
) {
157 static void mainloop_defer_free(struct pa_defer_event
*e
) {
159 e
->dead
= e
->mainloop
->defer_events_scan_dead
= 1;
162 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
)) {
164 e
->destroy_callback
= callback
;
168 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
) {
169 struct pa_mainloop
*m
;
170 struct pa_time_event
*e
;
172 assert(a
&& a
->userdata
&& callback
);
174 assert(a
== &m
->api
);
176 e
= pa_xmalloc(sizeof(struct pa_time_event
));
184 e
->callback
= callback
;
185 e
->userdata
= userdata
;
186 e
->destroy_callback
= NULL
;
188 pa_idxset_put(m
->time_events
, e
, NULL
);
192 static void mainloop_time_restart(struct pa_time_event
*e
, const struct timeval
*tv
) {
202 static void mainloop_time_free(struct pa_time_event
*e
) {
204 e
->dead
= e
->mainloop
->time_events_scan_dead
= 1;
207 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
)) {
209 e
->destroy_callback
= callback
;
214 static void mainloop_quit(struct pa_mainloop_api
*a
, int retval
) {
215 struct pa_mainloop
*m
;
216 assert(a
&& a
->userdata
);
218 assert(a
== &m
->api
);
224 static const struct pa_mainloop_api vtable
= {
227 .io_new
= mainloop_io_new
,
228 .io_enable
= mainloop_io_enable
,
229 .io_free
= mainloop_io_free
,
230 .io_set_destroy
= mainloop_io_set_destroy
,
232 .time_new
= mainloop_time_new
,
233 .time_restart
= mainloop_time_restart
,
234 .time_free
= mainloop_time_free
,
235 .time_set_destroy
= mainloop_time_set_destroy
,
237 .defer_new
= mainloop_defer_new
,
238 .defer_enable
= mainloop_defer_enable
,
239 .defer_free
= mainloop_defer_free
,
240 .defer_set_destroy
= mainloop_defer_set_destroy
,
242 .quit
= mainloop_quit
,
245 struct pa_mainloop
*pa_mainloop_new(void) {
246 struct pa_mainloop
*m
;
248 m
= pa_xmalloc(sizeof(struct pa_mainloop
));
250 m
->io_events
= pa_idxset_new(NULL
, NULL
);
251 m
->defer_events
= pa_idxset_new(NULL
, NULL
);
252 m
->time_events
= pa_idxset_new(NULL
, NULL
);
254 assert(m
->io_events
&& m
->defer_events
&& m
->time_events
);
256 m
->io_events_scan_dead
= m
->defer_events_scan_dead
= m
->time_events_scan_dead
= 0;
259 m
->max_pollfds
= m
->n_pollfds
= m
->rebuild_pollfds
= 0;
261 m
->quit
= m
->running
= m
->retval
= 0;
269 static int io_foreach(void *p
, uint32_t index
, int *del
, void*userdata
) {
270 struct pa_io_event
*e
= p
;
272 assert(e
&& del
&& all
);
274 if (!*all
|| !e
->dead
)
277 if (e
->destroy_callback
)
278 e
->destroy_callback(&e
->mainloop
->api
, e
, e
->userdata
);
284 static int time_foreach(void *p
, uint32_t index
, int *del
, void*userdata
) {
285 struct pa_time_event
*e
= p
;
287 assert(e
&& del
&& all
);
289 if (!*all
|| !e
->dead
)
292 if (e
->destroy_callback
)
293 e
->destroy_callback(&e
->mainloop
->api
, e
, e
->userdata
);
299 static int defer_foreach(void *p
, uint32_t index
, int *del
, void*userdata
) {
300 struct pa_defer_event
*e
= p
;
302 assert(e
&& del
&& all
);
304 if (!*all
|| !e
->dead
)
307 if (e
->destroy_callback
)
308 e
->destroy_callback(&e
->mainloop
->api
, e
, e
->userdata
);
314 void pa_mainloop_free(struct pa_mainloop
* m
) {
318 pa_idxset_foreach(m
->io_events
, io_foreach
, &all
);
319 pa_idxset_foreach(m
->time_events
, time_foreach
, &all
);
320 pa_idxset_foreach(m
->defer_events
, defer_foreach
, &all
);
322 pa_idxset_free(m
->io_events
, NULL
, NULL
);
323 pa_idxset_free(m
->time_events
, NULL
, NULL
);
324 pa_idxset_free(m
->defer_events
, NULL
, NULL
);
326 pa_xfree(m
->pollfds
);
330 static void scan_dead(struct pa_mainloop
*m
) {
333 if (m
->io_events_scan_dead
)
334 pa_idxset_foreach(m
->io_events
, io_foreach
, &all
);
335 if (m
->time_events_scan_dead
)
336 pa_idxset_foreach(m
->time_events
, time_foreach
, &all
);
337 if (m
->defer_events_scan_dead
)
338 pa_idxset_foreach(m
->defer_events
, defer_foreach
, &all
);
341 static void rebuild_pollfds(struct pa_mainloop
*m
) {
342 struct pa_io_event
*e
;
344 uint32_t index
= PA_IDXSET_INVALID
;
347 l
= pa_idxset_ncontents(m
->io_events
);
348 if (m
->max_pollfds
< l
) {
349 m
->pollfds
= pa_xrealloc(m
->pollfds
, sizeof(struct pollfd
)*l
);
355 for (e
= pa_idxset_first(m
->io_events
, &index
); e
; e
= pa_idxset_next(m
->io_events
, &index
)) {
364 ((e
->events
& PA_IO_EVENT_INPUT
) ? POLLIN
: 0) |
365 ((e
->events
& PA_IO_EVENT_OUTPUT
) ? POLLOUT
: 0) |
375 static void dispatch_pollfds(struct pa_mainloop
*m
) {
376 uint32_t index
= PA_IDXSET_INVALID
;
377 struct pa_io_event
*e
;
379 for (e
= pa_idxset_first(m
->io_events
, &index
); e
; e
= pa_idxset_next(m
->io_events
, &index
)) {
380 if (e
->dead
|| !e
->pollfd
|| !e
->pollfd
->revents
)
383 assert(e
->pollfd
->fd
== e
->fd
&& e
->callback
);
384 e
->callback(&m
->api
, e
, e
->fd
,
385 (e
->pollfd
->revents
& POLLHUP
? PA_IO_EVENT_HANGUP
: 0) |
386 (e
->pollfd
->revents
& POLLIN
? PA_IO_EVENT_INPUT
: 0) |
387 (e
->pollfd
->revents
& POLLOUT
? PA_IO_EVENT_OUTPUT
: 0) |
388 (e
->pollfd
->revents
& POLLERR
? PA_IO_EVENT_ERROR
: 0),
390 e
->pollfd
->revents
= 0;
394 static void dispatch_defer(struct pa_mainloop
*m
) {
396 struct pa_defer_event
*e
;
398 for (e
= pa_idxset_first(m
->defer_events
, &index
); e
; e
= pa_idxset_next(m
->defer_events
, &index
)) {
399 if (e
->dead
|| !e
->enabled
)
403 e
->callback(&m
->api
, e
, e
->userdata
);
407 static int calc_next_timeout(struct pa_mainloop
*m
) {
409 struct pa_time_event
*e
;
413 if (pa_idxset_isempty(m
->time_events
))
416 gettimeofday(&now
, NULL
);
418 for (e
= pa_idxset_first(m
->time_events
, &index
); e
; e
= pa_idxset_next(m
->time_events
, &index
)) {
421 if (e
->dead
|| !e
->enabled
)
424 if (e
->timeval
.tv_sec
< now
.tv_sec
|| (e
->timeval
.tv_sec
== now
.tv_sec
&& e
->timeval
.tv_usec
<= now
.tv_usec
))
427 tmp
= (e
->timeval
.tv_sec
- now
.tv_sec
)*1000;
429 if (e
->timeval
.tv_usec
> now
.tv_usec
)
430 tmp
+= (e
->timeval
.tv_usec
- now
.tv_usec
)/1000;
432 tmp
-= (now
.tv_usec
- e
->timeval
.tv_usec
)/1000;
436 else if (t
== -1 || tmp
< t
)
443 static void dispatch_timeout(struct pa_mainloop
*m
) {
445 struct pa_time_event
*e
;
449 if (pa_idxset_isempty(m
->time_events
))
452 gettimeofday(&now
, NULL
);
453 for (e
= pa_idxset_first(m
->time_events
, &index
); e
; e
= pa_idxset_next(m
->time_events
, &index
)) {
455 if (e
->dead
|| !e
->enabled
)
458 if (e
->timeval
.tv_sec
< now
.tv_sec
|| (e
->timeval
.tv_sec
== now
.tv_sec
&& e
->timeval
.tv_usec
<= now
.tv_usec
)) {
462 e
->callback(&m
->api
, e
, &e
->timeval
, e
->userdata
);
467 int pa_mainloop_iterate(struct pa_mainloop
*m
, int block
, int *retval
) {
469 assert(m
&& !m
->running
);
482 if (m
->rebuild_pollfds
) {
484 m
->rebuild_pollfds
= 0;
488 int t
= block
? calc_next_timeout(m
) : 0;
489 /*fprintf(stderr, "%u\n", t);*/
490 r
= poll(m
->pollfds
, m
->n_pollfds
, t
);
491 } while (r
< 0 && errno
== EINTR
);
498 fprintf(stderr
, "select(): %s\n", strerror(errno
));
501 return r
< 0 ? -1 : 0;
504 int pa_mainloop_run(struct pa_mainloop
*m
, int *retval
) {
506 while ((r
= pa_mainloop_iterate(m
, 1, retval
)) == 0);
510 void pa_mainloop_quit(struct pa_mainloop
*m
, int r
) {
515 struct pa_mainloop_api
* pa_mainloop_get_api(struct pa_mainloop
*m
) {