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
35 #ifdef HAVE_SYS_POLL_H
41 #include "../polypcore/winsock.h"
43 #include <polypcore/util.h>
44 #include <polypcore/idxset.h>
45 #include <polypcore/xmalloc.h>
46 #include <polypcore/log.h>
51 pa_mainloop
*mainloop
;
54 pa_io_event_flags_t events
;
55 void (*callback
) (pa_mainloop_api
*a
, pa_io_event
*e
, int fd
, pa_io_event_flags_t f
, void *userdata
);
56 struct pollfd
*pollfd
;
58 void (*destroy_callback
) (pa_mainloop_api
*a
, pa_io_event
*e
, void *userdata
);
61 struct pa_time_event
{
62 pa_mainloop
*mainloop
;
65 struct timeval timeval
;
66 void (*callback
)(pa_mainloop_api
*a
, pa_time_event
*e
, const struct timeval
*tv
, void *userdata
);
68 void (*destroy_callback
) (pa_mainloop_api
*a
, pa_time_event
*e
, void *userdata
);
71 struct pa_defer_event
{
72 pa_mainloop
*mainloop
;
75 void (*callback
)(pa_mainloop_api
*a
, pa_defer_event
*e
, void *userdata
);
77 void (*destroy_callback
) (pa_mainloop_api
*a
, pa_defer_event
*e
, void *userdata
);
81 pa_idxset
*io_events
, *time_events
, *defer_events
;
82 int io_events_scan_dead
, defer_events_scan_dead
, time_events_scan_dead
;
84 struct pollfd
*pollfds
;
85 unsigned max_pollfds
, n_pollfds
;
107 static pa_io_event
* mainloop_io_new(
110 pa_io_event_flags_t events
,
111 void (*callback
) (pa_mainloop_api
*a
, pa_io_event
*e
, int fd
, pa_io_event_flags_t events
, void *userdata
),
117 assert(a
&& a
->userdata
&& fd
>= 0 && callback
);
119 assert(a
== &m
->api
);
121 pa_mainloop_wakeup(m
);
123 e
= pa_xmalloc(sizeof(pa_io_event
));
129 e
->callback
= callback
;
130 e
->userdata
= userdata
;
131 e
->destroy_callback
= NULL
;
145 if ((select((SELECT_TYPE_ARG1
) fd
, NULL
, NULL
, SELECT_TYPE_ARG234
&xset
,
146 SELECT_TYPE_ARG5
&tv
) == -1) &&
147 (WSAGetLastError() == WSAENOTSOCK
)) {
148 pa_log_warn(__FILE__
": WARNING: cannot monitor non-socket file descriptors.\n");
154 pa_idxset_put(m
->io_events
, e
, NULL
);
155 m
->rebuild_pollfds
= 1;
159 static void mainloop_io_enable(pa_io_event
*e
, pa_io_event_flags_t events
) {
160 assert(e
&& e
->mainloop
);
162 pa_mainloop_wakeup(e
->mainloop
);
165 e
->mainloop
->rebuild_pollfds
= 1;
168 static void mainloop_io_free(pa_io_event
*e
) {
169 assert(e
&& e
->mainloop
);
171 pa_mainloop_wakeup(e
->mainloop
);
173 e
->dead
= e
->mainloop
->io_events_scan_dead
= e
->mainloop
->rebuild_pollfds
= 1;
176 static void mainloop_io_set_destroy(pa_io_event
*e
, void (*callback
)(pa_mainloop_api
*a
, pa_io_event
*e
, void *userdata
)) {
178 e
->destroy_callback
= callback
;
182 static pa_defer_event
* mainloop_defer_new(pa_mainloop_api
*a
, void (*callback
) (pa_mainloop_api
*a
, pa_defer_event
*e
, void *userdata
), void *userdata
) {
186 assert(a
&& a
->userdata
&& callback
);
188 assert(a
== &m
->api
);
190 e
= pa_xmalloc(sizeof(pa_defer_event
));
195 e
->callback
= callback
;
196 e
->userdata
= userdata
;
197 e
->destroy_callback
= NULL
;
199 pa_idxset_put(m
->defer_events
, e
, NULL
);
201 m
->deferred_pending
++;
205 static void mainloop_defer_enable(pa_defer_event
*e
, int b
) {
208 if (e
->enabled
&& !b
) {
209 assert(e
->mainloop
->deferred_pending
> 0);
210 e
->mainloop
->deferred_pending
--;
211 } else if (!e
->enabled
&& b
)
212 e
->mainloop
->deferred_pending
++;
217 static void mainloop_defer_free(pa_defer_event
*e
) {
219 e
->dead
= e
->mainloop
->defer_events_scan_dead
= 1;
223 assert(e
->mainloop
->deferred_pending
> 0);
224 e
->mainloop
->deferred_pending
--;
228 static void mainloop_defer_set_destroy(pa_defer_event
*e
, void (*callback
)(pa_mainloop_api
*a
, pa_defer_event
*e
, void *userdata
)) {
230 e
->destroy_callback
= callback
;
234 static pa_time_event
* mainloop_time_new(pa_mainloop_api
*a
, const struct timeval
*tv
, void (*callback
) (pa_mainloop_api
*a
, pa_time_event
*e
, const struct timeval
*tv
, void *userdata
), void *userdata
) {
238 assert(a
&& a
->userdata
&& callback
);
240 assert(a
== &m
->api
);
242 pa_mainloop_wakeup(m
);
244 e
= pa_xmalloc(sizeof(pa_time_event
));
252 e
->callback
= callback
;
253 e
->userdata
= userdata
;
254 e
->destroy_callback
= NULL
;
256 pa_idxset_put(m
->time_events
, e
, NULL
);
261 static void mainloop_time_restart(pa_time_event
*e
, const struct timeval
*tv
) {
264 pa_mainloop_wakeup(e
->mainloop
);
273 static void mainloop_time_free(pa_time_event
*e
) {
276 pa_mainloop_wakeup(e
->mainloop
);
278 e
->dead
= e
->mainloop
->time_events_scan_dead
= 1;
281 static void mainloop_time_set_destroy(pa_time_event
*e
, void (*callback
)(pa_mainloop_api
*a
, pa_time_event
*e
, void *userdata
)) {
283 e
->destroy_callback
= callback
;
288 static void mainloop_quit(pa_mainloop_api
*a
, int retval
) {
290 assert(a
&& a
->userdata
);
292 assert(a
== &m
->api
);
294 pa_mainloop_wakeup(m
);
300 static const pa_mainloop_api vtable
= {
303 .io_new
= mainloop_io_new
,
304 .io_enable
= mainloop_io_enable
,
305 .io_free
= mainloop_io_free
,
306 .io_set_destroy
= mainloop_io_set_destroy
,
308 .time_new
= mainloop_time_new
,
309 .time_restart
= mainloop_time_restart
,
310 .time_free
= mainloop_time_free
,
311 .time_set_destroy
= mainloop_time_set_destroy
,
313 .defer_new
= mainloop_defer_new
,
314 .defer_enable
= mainloop_defer_enable
,
315 .defer_free
= mainloop_defer_free
,
316 .defer_set_destroy
= mainloop_defer_set_destroy
,
318 .quit
= mainloop_quit
,
321 pa_mainloop
*pa_mainloop_new(void) {
324 m
= pa_xmalloc(sizeof(pa_mainloop
));
327 if (pipe(m
->wakeup_pipe
) < 0) {
332 pa_make_nonblock_fd(m
->wakeup_pipe
[0]);
333 pa_make_nonblock_fd(m
->wakeup_pipe
[1]);
335 m
->wakeup_pipe
[0] = -1;
336 m
->wakeup_pipe
[1] = -1;
339 m
->io_events
= pa_idxset_new(NULL
, NULL
);
340 m
->defer_events
= pa_idxset_new(NULL
, NULL
);
341 m
->time_events
= pa_idxset_new(NULL
, NULL
);
343 assert(m
->io_events
&& m
->defer_events
&& m
->time_events
);
345 m
->io_events_scan_dead
= m
->defer_events_scan_dead
= m
->time_events_scan_dead
= 0;
348 m
->max_pollfds
= m
->n_pollfds
= m
->rebuild_pollfds
= 0;
350 m
->quit
= m
->retval
= 0;
355 m
->deferred_pending
= 0;
357 m
->state
= STATE_PASSIVE
;
362 static int io_foreach(void *p
, uint32_t PA_GCC_UNUSED idx
, int *del
, void*userdata
) {
365 assert(e
&& del
&& all
);
367 if (!*all
&& !e
->dead
)
370 if (e
->destroy_callback
)
371 e
->destroy_callback(&e
->mainloop
->api
, e
, e
->userdata
);
377 static int time_foreach(void *p
, uint32_t PA_GCC_UNUSED idx
, int *del
, void*userdata
) {
378 pa_time_event
*e
= p
;
380 assert(e
&& del
&& all
);
382 if (!*all
&& !e
->dead
)
385 if (e
->destroy_callback
)
386 e
->destroy_callback(&e
->mainloop
->api
, e
, e
->userdata
);
392 static int defer_foreach(void *p
, PA_GCC_UNUSED
uint32_t idx
, int *del
, void*userdata
) {
393 pa_defer_event
*e
= p
;
395 assert(e
&& del
&& all
);
397 if (!*all
&& !e
->dead
)
400 if (e
->destroy_callback
)
401 e
->destroy_callback(&e
->mainloop
->api
, e
, e
->userdata
);
407 void pa_mainloop_free(pa_mainloop
* m
) {
409 assert(m
&& (m
->state
!= STATE_POLLING
));
411 pa_idxset_foreach(m
->io_events
, io_foreach
, &all
);
412 pa_idxset_foreach(m
->time_events
, time_foreach
, &all
);
413 pa_idxset_foreach(m
->defer_events
, defer_foreach
, &all
);
415 pa_idxset_free(m
->io_events
, NULL
, NULL
);
416 pa_idxset_free(m
->time_events
, NULL
, NULL
);
417 pa_idxset_free(m
->defer_events
, NULL
, NULL
);
419 pa_xfree(m
->pollfds
);
421 if (m
->wakeup_pipe
[0] >= 0)
422 close(m
->wakeup_pipe
[0]);
423 if (m
->wakeup_pipe
[1] >= 0)
424 close(m
->wakeup_pipe
[1]);
429 static void scan_dead(pa_mainloop
*m
) {
433 if (m
->io_events_scan_dead
)
434 pa_idxset_foreach(m
->io_events
, io_foreach
, &all
);
435 if (m
->time_events_scan_dead
)
436 pa_idxset_foreach(m
->time_events
, time_foreach
, &all
);
437 if (m
->defer_events_scan_dead
)
438 pa_idxset_foreach(m
->defer_events
, defer_foreach
, &all
);
440 m
->io_events_scan_dead
= m
->time_events_scan_dead
= m
->defer_events_scan_dead
= 0;
443 static void rebuild_pollfds(pa_mainloop
*m
) {
446 uint32_t idx
= PA_IDXSET_INVALID
;
449 l
= pa_idxset_size(m
->io_events
) + 1;
450 if (m
->max_pollfds
< l
) {
451 m
->pollfds
= pa_xrealloc(m
->pollfds
, sizeof(struct pollfd
)*l
);
458 if (m
->wakeup_pipe
[0] >= 0) {
459 m
->pollfds
[0].fd
= m
->wakeup_pipe
[0];
460 m
->pollfds
[0].events
= POLLIN
;
461 m
->pollfds
[0].revents
= 0;
466 for (e
= pa_idxset_first(m
->io_events
, &idx
); e
; e
= pa_idxset_next(m
->io_events
, &idx
)) {
475 ((e
->events
& PA_IO_EVENT_INPUT
) ? POLLIN
: 0) |
476 ((e
->events
& PA_IO_EVENT_OUTPUT
) ? POLLOUT
: 0) |
485 m
->rebuild_pollfds
= 0;
488 static int dispatch_pollfds(pa_mainloop
*m
) {
489 uint32_t idx
= PA_IDXSET_INVALID
;
493 for (e
= pa_idxset_first(m
->io_events
, &idx
); e
&& !m
->quit
; e
= pa_idxset_next(m
->io_events
, &idx
)) {
494 if (e
->dead
|| !e
->pollfd
|| !e
->pollfd
->revents
)
497 assert(e
->pollfd
->fd
== e
->fd
&& e
->callback
);
498 e
->callback(&m
->api
, e
, e
->fd
,
499 (e
->pollfd
->revents
& POLLHUP
? PA_IO_EVENT_HANGUP
: 0) |
500 (e
->pollfd
->revents
& POLLIN
? PA_IO_EVENT_INPUT
: 0) |
501 (e
->pollfd
->revents
& POLLOUT
? PA_IO_EVENT_OUTPUT
: 0) |
502 (e
->pollfd
->revents
& POLLERR
? PA_IO_EVENT_ERROR
: 0),
504 e
->pollfd
->revents
= 0;
511 static int dispatch_defer(pa_mainloop
*m
) {
516 if (!m
->deferred_pending
)
519 for (e
= pa_idxset_first(m
->defer_events
, &idx
); e
&& !m
->quit
; e
= pa_idxset_next(m
->defer_events
, &idx
)) {
520 if (e
->dead
|| !e
->enabled
)
524 e
->callback(&m
->api
, e
, e
->userdata
);
531 static int calc_next_timeout(pa_mainloop
*m
) {
538 if (pa_idxset_isempty(m
->time_events
))
541 for (e
= pa_idxset_first(m
->time_events
, &idx
); e
; e
= pa_idxset_next(m
->time_events
, &idx
)) {
544 if (e
->dead
|| !e
->enabled
)
547 /* Let's save a system call */
549 pa_gettimeofday(&now
);
553 if (e
->timeval
.tv_sec
< now
.tv_sec
|| (e
->timeval
.tv_sec
== now
.tv_sec
&& e
->timeval
.tv_usec
<= now
.tv_usec
))
556 tmp
= (e
->timeval
.tv_sec
- now
.tv_sec
)*1000;
558 if (e
->timeval
.tv_usec
> now
.tv_usec
)
559 tmp
+= (e
->timeval
.tv_usec
- now
.tv_usec
)/1000;
561 tmp
-= (now
.tv_usec
- e
->timeval
.tv_usec
)/1000;
565 else if (t
== -1 || tmp
< t
)
572 static int dispatch_timeout(pa_mainloop
*m
) {
580 if (pa_idxset_isempty(m
->time_events
))
583 for (e
= pa_idxset_first(m
->time_events
, &idx
); e
&& !m
->quit
; e
= pa_idxset_next(m
->time_events
, &idx
)) {
585 if (e
->dead
|| !e
->enabled
)
588 /* Let's save a system call */
590 pa_gettimeofday(&now
);
594 if (e
->timeval
.tv_sec
< now
.tv_sec
|| (e
->timeval
.tv_sec
== now
.tv_sec
&& e
->timeval
.tv_usec
<= now
.tv_usec
)) {
598 e
->callback(&m
->api
, e
, &e
->timeval
, e
->userdata
);
607 void pa_mainloop_wakeup(pa_mainloop
*m
) {
611 if (m
->wakeup_pipe
[1] >= 0)
612 write(m
->wakeup_pipe
[1], &c
, sizeof(c
));
615 static void clear_wakeup(pa_mainloop
*m
) {
620 if (m
->wakeup_pipe
[0] < 0)
623 while (read(m
->wakeup_pipe
[0], &c
, sizeof(c
)) == sizeof(c
));
626 int pa_mainloop_prepare(pa_mainloop
*m
, int timeout
) {
629 assert(m
&& (m
->state
== STATE_PASSIVE
));
638 dispatched
+= dispatch_defer(m
);
643 if (m
->rebuild_pollfds
)
646 m
->prepared_timeout
= calc_next_timeout(m
);
647 if ((timeout
>= 0) && (m
->prepared_timeout
> timeout
))
648 m
->prepared_timeout
= timeout
;
650 m
->state
= STATE_PREPARED
;
656 m
->state
= STATE_QUIT
;
661 int pa_mainloop_poll(pa_mainloop
*m
) {
664 assert(m
&& (m
->state
== STATE_PREPARED
));
666 m
->state
= STATE_POLLING
;
668 r
= poll(m
->pollfds
, m
->n_pollfds
, m
->prepared_timeout
);
670 if ((r
< 0) && (errno
== EINTR
))
674 m
->state
= STATE_PASSIVE
;
676 m
->state
= STATE_POLLED
;
681 int pa_mainloop_dispatch(pa_mainloop
*m
) {
684 assert(m
&& (m
->state
== STATE_POLLED
));
686 dispatched
+= dispatch_timeout(m
);
691 dispatched
+= dispatch_pollfds(m
);
696 m
->state
= STATE_PASSIVE
;
702 m
->state
= STATE_QUIT
;
707 int pa_mainloop_get_retval(pa_mainloop
*m
) {
712 int pa_mainloop_iterate(pa_mainloop
*m
, int block
, int *retval
) {
713 int r
, dispatched
= 0;
717 r
= pa_mainloop_prepare(m
, block
? -1 : 0);
719 if ((r
== -2) && retval
)
720 *retval
= pa_mainloop_get_retval(m
);
726 r
= pa_mainloop_poll(m
);
728 pa_log(__FILE__
": poll(): %s\n", strerror(errno
));
732 r
= pa_mainloop_dispatch(m
);
734 if ((r
== -2) && retval
)
735 *retval
= pa_mainloop_get_retval(m
);
744 int pa_mainloop_run(pa_mainloop
*m
, int *retval
) {
746 while ((r
= pa_mainloop_iterate(m
, 1, retval
)) >= 0);
756 void pa_mainloop_quit(pa_mainloop
*m
, int r
) {
758 pa_mainloop_wakeup(m
);
762 pa_mainloop_api
* pa_mainloop_get_api(pa_mainloop
*m
) {
767 int pa_mainloop_deferred_pending(pa_mainloop
*m
) {
769 return m
->deferred_pending
> 0;
774 void pa_mainloop_dump(pa_mainloop
*m
) {
777 pa_log(__FILE__
": Dumping mainloop sources START\n");
780 uint32_t idx
= PA_IDXSET_INVALID
;
782 for (e
= pa_idxset_first(m
->io_events
, &idx
); e
; e
= pa_idxset_next(m
->io_events
, &idx
)) {
786 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
);
790 uint32_t idx
= PA_IDXSET_INVALID
;
792 for (e
= pa_idxset_first(m
->defer_events
, &idx
); e
; e
= pa_idxset_next(m
->defer_events
, &idx
)) {
796 pa_log(__FILE__
": kind=defer enabled=%i callback=%p userdata=%p\n", e
->enabled
, (void*) e
->callback
, (void*) e
->userdata
);
800 uint32_t idx
= PA_IDXSET_INVALID
;
802 for (e
= pa_idxset_first(m
->time_events
, &idx
); e
; e
= pa_idxset_next(m
->time_events
, &idx
)) {
806 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
);
810 pa_log(__FILE__
": Dumping mainloop sources STOP\n");