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 Lesser 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 Lesser 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
43 struct pa_mainloop
*mainloop
;
46 enum pa_io_event_flags events
;
47 void (*callback
) (struct pa_mainloop_api
*a
, struct pa_io_event
*e
, int fd
, enum pa_io_event_flags f
, void *userdata
);
48 struct pollfd
*pollfd
;
50 void (*destroy_callback
) (struct pa_mainloop_api
*a
, struct pa_io_event
*e
, void *userdata
);
53 struct pa_time_event
{
54 struct pa_mainloop
*mainloop
;
57 struct timeval timeval
;
58 void (*callback
)(struct pa_mainloop_api
*a
, struct pa_time_event
*e
, const struct timeval
*tv
, void *userdata
);
60 void (*destroy_callback
) (struct pa_mainloop_api
*a
, struct pa_time_event
*e
, void *userdata
);
63 struct pa_defer_event
{
64 struct pa_mainloop
*mainloop
;
67 void (*callback
)(struct pa_mainloop_api
*a
, struct pa_defer_event
*e
, void *userdata
);
69 void (*destroy_callback
) (struct pa_mainloop_api
*a
, struct pa_defer_event
*e
, void *userdata
);
73 struct pa_idxset
*io_events
, *time_events
, *defer_events
;
74 int io_events_scan_dead
, defer_events_scan_dead
, time_events_scan_dead
;
76 struct pollfd
*pollfds
;
77 unsigned max_pollfds
, n_pollfds
;
80 int quit
, running
, retval
;
81 struct pa_mainloop_api api
;
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
;
91 assert(a
&& a
->userdata
&& fd
>= 0 && callback
);
95 e
= pa_xmalloc(sizeof(struct pa_io_event
));
101 e
->callback
= callback
;
102 e
->userdata
= userdata
;
103 e
->destroy_callback
= NULL
;
106 pa_idxset_put(m
->io_events
, e
, NULL
);
107 m
->rebuild_pollfds
= 1;
111 static void mainloop_io_enable(struct pa_io_event
*e
, enum pa_io_event_flags events
) {
112 assert(e
&& e
->mainloop
);
117 (events
& PA_IO_EVENT_INPUT
? POLLIN
: 0) |
118 (events
& PA_IO_EVENT_OUTPUT
? POLLOUT
: 0) |
122 static void mainloop_io_free(struct pa_io_event
*e
) {
123 assert(e
&& e
->mainloop
);
124 e
->dead
= e
->mainloop
->io_events_scan_dead
= e
->mainloop
->rebuild_pollfds
= 1;
127 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 e
->destroy_callback
= callback
;
133 static 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
) {
134 struct pa_mainloop
*m
;
135 struct pa_defer_event
*e
;
137 assert(a
&& a
->userdata
&& callback
);
139 assert(a
== &m
->api
);
141 e
= pa_xmalloc(sizeof(struct pa_defer_event
));
146 e
->callback
= callback
;
147 e
->userdata
= userdata
;
148 e
->destroy_callback
= NULL
;
150 pa_idxset_put(m
->defer_events
, e
, NULL
);
152 m
->deferred_pending
++;
156 static void mainloop_defer_enable(struct pa_defer_event
*e
, int b
) {
159 if (e
->enabled
&& !b
) {
160 assert(e
->mainloop
->deferred_pending
> 0);
161 e
->mainloop
->deferred_pending
--;
162 } else if (!e
->enabled
&& b
)
163 e
->mainloop
->deferred_pending
++;
168 static void mainloop_defer_free(struct pa_defer_event
*e
) {
170 e
->dead
= e
->mainloop
->defer_events_scan_dead
= 1;
174 assert(e
->mainloop
->deferred_pending
> 0);
175 e
->mainloop
->deferred_pending
--;
179 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
)) {
181 e
->destroy_callback
= callback
;
185 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
) {
186 struct pa_mainloop
*m
;
187 struct pa_time_event
*e
;
189 assert(a
&& a
->userdata
&& callback
);
191 assert(a
== &m
->api
);
193 e
= pa_xmalloc(sizeof(struct pa_time_event
));
201 e
->callback
= callback
;
202 e
->userdata
= userdata
;
203 e
->destroy_callback
= NULL
;
205 pa_idxset_put(m
->time_events
, e
, NULL
);
210 static void mainloop_time_restart(struct pa_time_event
*e
, const struct timeval
*tv
) {
220 static void mainloop_time_free(struct pa_time_event
*e
) {
223 e
->dead
= e
->mainloop
->time_events_scan_dead
= 1;
226 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
)) {
228 e
->destroy_callback
= callback
;
233 static void mainloop_quit(struct pa_mainloop_api
*a
, int retval
) {
234 struct pa_mainloop
*m
;
235 assert(a
&& a
->userdata
);
237 assert(a
== &m
->api
);
243 static const struct pa_mainloop_api vtable
= {
246 .io_new
= mainloop_io_new
,
247 .io_enable
= mainloop_io_enable
,
248 .io_free
= mainloop_io_free
,
249 .io_set_destroy
= mainloop_io_set_destroy
,
251 .time_new
= mainloop_time_new
,
252 .time_restart
= mainloop_time_restart
,
253 .time_free
= mainloop_time_free
,
254 .time_set_destroy
= mainloop_time_set_destroy
,
256 .defer_new
= mainloop_defer_new
,
257 .defer_enable
= mainloop_defer_enable
,
258 .defer_free
= mainloop_defer_free
,
259 .defer_set_destroy
= mainloop_defer_set_destroy
,
261 .quit
= mainloop_quit
,
264 struct pa_mainloop
*pa_mainloop_new(void) {
265 struct pa_mainloop
*m
;
267 m
= pa_xmalloc(sizeof(struct pa_mainloop
));
269 m
->io_events
= pa_idxset_new(NULL
, NULL
);
270 m
->defer_events
= pa_idxset_new(NULL
, NULL
);
271 m
->time_events
= pa_idxset_new(NULL
, NULL
);
273 assert(m
->io_events
&& m
->defer_events
&& m
->time_events
);
275 m
->io_events_scan_dead
= m
->defer_events_scan_dead
= m
->time_events_scan_dead
= 0;
278 m
->max_pollfds
= m
->n_pollfds
= m
->rebuild_pollfds
= 0;
280 m
->quit
= m
->running
= m
->retval
= 0;
285 m
->deferred_pending
= 0;
290 static int io_foreach(void *p
, uint32_t index
, int *del
, void*userdata
) {
291 struct pa_io_event
*e
= p
;
293 assert(e
&& del
&& all
);
295 if (!*all
&& !e
->dead
)
298 if (e
->destroy_callback
)
299 e
->destroy_callback(&e
->mainloop
->api
, e
, e
->userdata
);
305 static int time_foreach(void *p
, uint32_t index
, int *del
, void*userdata
) {
306 struct pa_time_event
*e
= p
;
308 assert(e
&& del
&& all
);
310 if (!*all
&& !e
->dead
)
313 if (e
->destroy_callback
)
314 e
->destroy_callback(&e
->mainloop
->api
, e
, e
->userdata
);
320 static int defer_foreach(void *p
, uint32_t index
, int *del
, void*userdata
) {
321 struct pa_defer_event
*e
= p
;
323 assert(e
&& del
&& all
);
325 if (!*all
&& !e
->dead
)
328 if (e
->destroy_callback
)
329 e
->destroy_callback(&e
->mainloop
->api
, e
, e
->userdata
);
335 void pa_mainloop_free(struct pa_mainloop
* m
) {
339 pa_idxset_foreach(m
->io_events
, io_foreach
, &all
);
340 pa_idxset_foreach(m
->time_events
, time_foreach
, &all
);
341 pa_idxset_foreach(m
->defer_events
, defer_foreach
, &all
);
343 pa_idxset_free(m
->io_events
, NULL
, NULL
);
344 pa_idxset_free(m
->time_events
, NULL
, NULL
);
345 pa_idxset_free(m
->defer_events
, NULL
, NULL
);
347 pa_xfree(m
->pollfds
);
351 static void scan_dead(struct pa_mainloop
*m
) {
355 if (m
->io_events_scan_dead
)
356 pa_idxset_foreach(m
->io_events
, io_foreach
, &all
);
357 if (m
->time_events_scan_dead
)
358 pa_idxset_foreach(m
->time_events
, time_foreach
, &all
);
359 if (m
->defer_events_scan_dead
)
360 pa_idxset_foreach(m
->defer_events
, defer_foreach
, &all
);
362 m
->io_events_scan_dead
= m
->time_events_scan_dead
= m
->defer_events_scan_dead
= 0;
365 static void rebuild_pollfds(struct pa_mainloop
*m
) {
366 struct pa_io_event
*e
;
368 uint32_t index
= PA_IDXSET_INVALID
;
371 l
= pa_idxset_ncontents(m
->io_events
);
372 if (m
->max_pollfds
< l
) {
373 m
->pollfds
= pa_xrealloc(m
->pollfds
, sizeof(struct pollfd
)*l
);
379 for (e
= pa_idxset_first(m
->io_events
, &index
); e
; e
= pa_idxset_next(m
->io_events
, &index
)) {
388 ((e
->events
& PA_IO_EVENT_INPUT
) ? POLLIN
: 0) |
389 ((e
->events
& PA_IO_EVENT_OUTPUT
) ? POLLOUT
: 0) |
399 static int dispatch_pollfds(struct pa_mainloop
*m
) {
400 uint32_t index
= PA_IDXSET_INVALID
;
401 struct pa_io_event
*e
;
404 for (e
= pa_idxset_first(m
->io_events
, &index
); e
&& !m
->quit
; e
= pa_idxset_next(m
->io_events
, &index
)) {
405 if (e
->dead
|| !e
->pollfd
|| !e
->pollfd
->revents
)
408 assert(e
->pollfd
->fd
== e
->fd
&& e
->callback
);
409 e
->callback(&m
->api
, e
, e
->fd
,
410 (e
->pollfd
->revents
& POLLHUP
? PA_IO_EVENT_HANGUP
: 0) |
411 (e
->pollfd
->revents
& POLLIN
? PA_IO_EVENT_INPUT
: 0) |
412 (e
->pollfd
->revents
& POLLOUT
? PA_IO_EVENT_OUTPUT
: 0) |
413 (e
->pollfd
->revents
& POLLERR
? PA_IO_EVENT_ERROR
: 0),
415 e
->pollfd
->revents
= 0;
422 static int dispatch_defer(struct pa_mainloop
*m
) {
424 struct pa_defer_event
*e
;
427 if (!m
->deferred_pending
)
430 for (e
= pa_idxset_first(m
->defer_events
, &index
); e
&& !m
->quit
; e
= pa_idxset_next(m
->defer_events
, &index
)) {
431 if (e
->dead
|| !e
->enabled
)
435 e
->callback(&m
->api
, e
, e
->userdata
);
442 static int calc_next_timeout(struct pa_mainloop
*m
) {
444 struct pa_time_event
*e
;
449 if (pa_idxset_isempty(m
->time_events
))
452 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 /* Let's save a system call */
460 gettimeofday(&now
, NULL
);
464 if (e
->timeval
.tv_sec
< now
.tv_sec
|| (e
->timeval
.tv_sec
== now
.tv_sec
&& e
->timeval
.tv_usec
<= now
.tv_usec
))
467 tmp
= (e
->timeval
.tv_sec
- now
.tv_sec
)*1000;
469 if (e
->timeval
.tv_usec
> now
.tv_usec
)
470 tmp
+= (e
->timeval
.tv_usec
- now
.tv_usec
)/1000;
472 tmp
-= (now
.tv_usec
- e
->timeval
.tv_usec
)/1000;
476 else if (t
== -1 || tmp
< t
)
483 static int dispatch_timeout(struct pa_mainloop
*m
) {
485 struct pa_time_event
*e
;
491 if (pa_idxset_isempty(m
->time_events
))
494 for (e
= pa_idxset_first(m
->time_events
, &index
); e
&& !m
->quit
; e
= pa_idxset_next(m
->time_events
, &index
)) {
496 if (e
->dead
|| !e
->enabled
)
499 /* Let's save a system call */
501 gettimeofday(&now
, NULL
);
505 if (e
->timeval
.tv_sec
< now
.tv_sec
|| (e
->timeval
.tv_sec
== now
.tv_sec
&& e
->timeval
.tv_usec
<= now
.tv_usec
)) {
509 e
->callback(&m
->api
, e
, &e
->timeval
, e
->userdata
);
518 int pa_mainloop_iterate(struct pa_mainloop
*m
, int block
, int *retval
) {
519 int r
, t
, dispatched
= 0;
520 assert(m
&& !m
->running
);
528 dispatched
+= dispatch_defer(m
);
533 if (m
->rebuild_pollfds
) {
535 m
->rebuild_pollfds
= 0;
538 t
= block
? calc_next_timeout(m
) : 0;
540 r
= poll(m
->pollfds
, m
->n_pollfds
, t
);
546 pa_log(__FILE__
": select(): %s\n", strerror(errno
));
548 dispatched
+= dispatch_timeout(m
);
554 dispatched
+= dispatch_pollfds(m
);
563 /* pa_log("dispatched: %i\n", dispatched); */
565 return r
< 0 ? -1 : dispatched
;
577 int pa_mainloop_run(struct pa_mainloop
*m
, int *retval
) {
579 while ((r
= pa_mainloop_iterate(m
, 1, retval
)) >= 0);
589 void pa_mainloop_quit(struct pa_mainloop
*m
, int r
) {
594 struct pa_mainloop_api
* pa_mainloop_get_api(struct pa_mainloop
*m
) {
599 int pa_mainloop_deferred_pending(struct pa_mainloop
*m
) {
601 return m
->deferred_pending
> 0;
605 void pa_mainloop_dump(struct pa_mainloop
*m
) {
608 pa_log(__FILE__
": Dumping mainloop sources START\n");
611 uint32_t index
= PA_IDXSET_INVALID
;
612 struct pa_io_event
*e
;
613 for (e
= pa_idxset_first(m
->io_events
, &index
); e
; e
= pa_idxset_next(m
->io_events
, &index
)) {
617 pa_log(__FILE__
": kind=io fd=%i events=%i callback=%p userdata=%p\n", e
->fd
, (int) e
->events
, (void*) e
->callback
, (void*) e
->userdata
);
621 uint32_t index
= PA_IDXSET_INVALID
;
622 struct pa_defer_event
*e
;
623 for (e
= pa_idxset_first(m
->defer_events
, &index
); e
; e
= pa_idxset_next(m
->defer_events
, &index
)) {
627 pa_log(__FILE__
": kind=defer enabled=%i callback=%p userdata=%p\n", e
->enabled
, (void*) e
->callback
, (void*) e
->userdata
);
631 uint32_t index
= PA_IDXSET_INVALID
;
632 struct pa_time_event
*e
;
633 for (e
= pa_idxset_first(m
->time_events
, &index
); e
; e
= pa_idxset_next(m
->time_events
, &index
)) {
637 pa_log(__FILE__
": kind=time enabled=%i time=%lu.%lu callback=%p userdata=%p\n", e
->enabled
, (unsigned long) e
->timeval
.tv_sec
, (unsigned long) e
->timeval
.tv_usec
, (void*) e
->callback
, (void*) e
->userdata
);
641 pa_log(__FILE__
": Dumping mainloop sources STOP\n");