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
38 #include "../polypcore/poll.h"
41 #include "../polypcore/winsock.h"
44 #include "../polypcore/pipe.h"
47 #include <polyp/xmalloc.h>
49 #include <polypcore/core-util.h>
50 #include <polypcore/idxset.h>
51 #include <polypcore/log.h>
56 pa_mainloop
*mainloop
;
59 pa_io_event_flags_t events
;
60 void (*callback
) (pa_mainloop_api
*a
, pa_io_event
*e
, int fd
, pa_io_event_flags_t f
, void *userdata
);
61 struct pollfd
*pollfd
;
63 void (*destroy_callback
) (pa_mainloop_api
*a
, pa_io_event
*e
, void *userdata
);
66 struct pa_time_event
{
67 pa_mainloop
*mainloop
;
70 struct timeval timeval
;
71 void (*callback
)(pa_mainloop_api
*a
, pa_time_event
*e
, const struct timeval
*tv
, void *userdata
);
73 void (*destroy_callback
) (pa_mainloop_api
*a
, pa_time_event
*e
, void *userdata
);
76 struct pa_defer_event
{
77 pa_mainloop
*mainloop
;
80 void (*callback
)(pa_mainloop_api
*a
, pa_defer_event
*e
, void *userdata
);
82 void (*destroy_callback
) (pa_mainloop_api
*a
, pa_defer_event
*e
, void *userdata
);
86 pa_idxset
*io_events
, *time_events
, *defer_events
;
87 int io_events_scan_dead
, defer_events_scan_dead
, time_events_scan_dead
;
89 struct pollfd
*pollfds
;
90 unsigned max_pollfds
, n_pollfds
;
110 pa_poll_func poll_func
;
111 void *poll_func_userdata
;
115 static pa_io_event
* mainloop_io_new(
118 pa_io_event_flags_t events
,
119 void (*callback
) (pa_mainloop_api
*a
, pa_io_event
*e
, int fd
, pa_io_event_flags_t events
, void *userdata
),
125 assert(a
&& a
->userdata
&& fd
>= 0 && callback
);
127 assert(a
== &m
->api
);
129 e
= pa_xmalloc(sizeof(pa_io_event
));
135 e
->callback
= callback
;
136 e
->userdata
= userdata
;
137 e
->destroy_callback
= NULL
;
151 if ((select((SELECT_TYPE_ARG1
) fd
, NULL
, NULL
, SELECT_TYPE_ARG234
&xset
,
152 SELECT_TYPE_ARG5
&tv
) == -1) &&
153 (WSAGetLastError() == WSAENOTSOCK
)) {
154 pa_log_warn(__FILE__
": WARNING: cannot monitor non-socket file descriptors.");
160 pa_idxset_put(m
->io_events
, e
, NULL
);
161 m
->rebuild_pollfds
= 1;
163 pa_mainloop_wakeup(m
);
168 static void mainloop_io_enable(pa_io_event
*e
, pa_io_event_flags_t events
) {
169 assert(e
&& e
->mainloop
);
172 e
->mainloop
->rebuild_pollfds
= 1;
174 pa_mainloop_wakeup(e
->mainloop
);
177 static void mainloop_io_free(pa_io_event
*e
) {
178 assert(e
&& e
->mainloop
);
180 e
->dead
= e
->mainloop
->io_events_scan_dead
= e
->mainloop
->rebuild_pollfds
= 1;
182 pa_mainloop_wakeup(e
->mainloop
);
185 static void mainloop_io_set_destroy(pa_io_event
*e
, void (*callback
)(pa_mainloop_api
*a
, pa_io_event
*e
, void *userdata
)) {
187 e
->destroy_callback
= callback
;
191 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
) {
195 assert(a
&& a
->userdata
&& callback
);
197 assert(a
== &m
->api
);
199 e
= pa_xmalloc(sizeof(pa_defer_event
));
204 e
->callback
= callback
;
205 e
->userdata
= userdata
;
206 e
->destroy_callback
= NULL
;
208 pa_idxset_put(m
->defer_events
, e
, NULL
);
210 m
->deferred_pending
++;
212 pa_mainloop_wakeup(e
->mainloop
);
217 static void mainloop_defer_enable(pa_defer_event
*e
, int b
) {
220 if (e
->enabled
&& !b
) {
221 assert(e
->mainloop
->deferred_pending
> 0);
222 e
->mainloop
->deferred_pending
--;
223 } else if (!e
->enabled
&& b
) {
224 e
->mainloop
->deferred_pending
++;
225 pa_mainloop_wakeup(e
->mainloop
);
231 static void mainloop_defer_free(pa_defer_event
*e
) {
233 e
->dead
= e
->mainloop
->defer_events_scan_dead
= 1;
237 assert(e
->mainloop
->deferred_pending
> 0);
238 e
->mainloop
->deferred_pending
--;
242 static void mainloop_defer_set_destroy(pa_defer_event
*e
, void (*callback
)(pa_mainloop_api
*a
, pa_defer_event
*e
, void *userdata
)) {
244 e
->destroy_callback
= callback
;
248 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
) {
252 assert(a
&& a
->userdata
&& callback
);
254 assert(a
== &m
->api
);
256 e
= pa_xmalloc(sizeof(pa_time_event
));
264 e
->callback
= callback
;
265 e
->userdata
= userdata
;
266 e
->destroy_callback
= NULL
;
268 pa_idxset_put(m
->time_events
, e
, NULL
);
271 pa_mainloop_wakeup(m
);
276 static void mainloop_time_restart(pa_time_event
*e
, const struct timeval
*tv
) {
283 pa_mainloop_wakeup(e
->mainloop
);
288 static void mainloop_time_free(pa_time_event
*e
) {
291 e
->dead
= e
->mainloop
->time_events_scan_dead
= 1;
293 /* no wakeup needed here. Think about it! */
296 static void mainloop_time_set_destroy(pa_time_event
*e
, void (*callback
)(pa_mainloop_api
*a
, pa_time_event
*e
, void *userdata
)) {
298 e
->destroy_callback
= callback
;
303 static void mainloop_quit(pa_mainloop_api
*a
, int retval
) {
305 assert(a
&& a
->userdata
);
307 assert(a
== &m
->api
);
309 pa_mainloop_quit(m
, retval
);
312 static const pa_mainloop_api vtable
= {
315 .io_new
= mainloop_io_new
,
316 .io_enable
= mainloop_io_enable
,
317 .io_free
= mainloop_io_free
,
318 .io_set_destroy
= mainloop_io_set_destroy
,
320 .time_new
= mainloop_time_new
,
321 .time_restart
= mainloop_time_restart
,
322 .time_free
= mainloop_time_free
,
323 .time_set_destroy
= mainloop_time_set_destroy
,
325 .defer_new
= mainloop_defer_new
,
326 .defer_enable
= mainloop_defer_enable
,
327 .defer_free
= mainloop_defer_free
,
328 .defer_set_destroy
= mainloop_defer_set_destroy
,
330 .quit
= mainloop_quit
,
333 pa_mainloop
*pa_mainloop_new(void) {
336 m
= pa_xmalloc(sizeof(pa_mainloop
));
338 if (pipe(m
->wakeup_pipe
) < 0) {
339 pa_log_error(__FILE__
": ERROR: cannot create wakeup pipe");
344 pa_make_nonblock_fd(m
->wakeup_pipe
[0]);
345 pa_make_nonblock_fd(m
->wakeup_pipe
[1]);
347 m
->io_events
= pa_idxset_new(NULL
, NULL
);
348 m
->defer_events
= pa_idxset_new(NULL
, NULL
);
349 m
->time_events
= pa_idxset_new(NULL
, NULL
);
351 assert(m
->io_events
&& m
->defer_events
&& m
->time_events
);
353 m
->io_events_scan_dead
= m
->defer_events_scan_dead
= m
->time_events_scan_dead
= 0;
356 m
->max_pollfds
= m
->n_pollfds
= 0;
357 m
->rebuild_pollfds
= 1;
359 m
->quit
= m
->retval
= 0;
364 m
->deferred_pending
= 0;
366 m
->state
= STATE_PASSIVE
;
369 m
->poll_func_userdata
= NULL
;
376 static int io_foreach(void *p
, uint32_t PA_GCC_UNUSED idx
, int *del
, void*userdata
) {
379 assert(e
&& del
&& all
);
381 if (!*all
&& !e
->dead
)
384 if (e
->destroy_callback
)
385 e
->destroy_callback(&e
->mainloop
->api
, e
, e
->userdata
);
391 static int time_foreach(void *p
, uint32_t PA_GCC_UNUSED idx
, int *del
, void*userdata
) {
392 pa_time_event
*e
= p
;
394 assert(e
&& del
&& all
);
396 if (!*all
&& !e
->dead
)
399 if (e
->destroy_callback
)
400 e
->destroy_callback(&e
->mainloop
->api
, e
, e
->userdata
);
406 static int defer_foreach(void *p
, PA_GCC_UNUSED
uint32_t idx
, int *del
, void*userdata
) {
407 pa_defer_event
*e
= p
;
409 assert(e
&& del
&& all
);
411 if (!*all
&& !e
->dead
)
414 if (e
->destroy_callback
)
415 e
->destroy_callback(&e
->mainloop
->api
, e
, e
->userdata
);
421 void pa_mainloop_free(pa_mainloop
* m
) {
425 pa_idxset_foreach(m
->io_events
, io_foreach
, &all
);
426 pa_idxset_foreach(m
->time_events
, time_foreach
, &all
);
427 pa_idxset_foreach(m
->defer_events
, defer_foreach
, &all
);
429 pa_idxset_free(m
->io_events
, NULL
, NULL
);
430 pa_idxset_free(m
->time_events
, NULL
, NULL
);
431 pa_idxset_free(m
->defer_events
, NULL
, NULL
);
433 pa_xfree(m
->pollfds
);
435 if (m
->wakeup_pipe
[0] >= 0)
436 close(m
->wakeup_pipe
[0]);
437 if (m
->wakeup_pipe
[1] >= 0)
438 close(m
->wakeup_pipe
[1]);
443 static void scan_dead(pa_mainloop
*m
) {
447 if (m
->io_events_scan_dead
)
448 pa_idxset_foreach(m
->io_events
, io_foreach
, &all
);
449 if (m
->time_events_scan_dead
)
450 pa_idxset_foreach(m
->time_events
, time_foreach
, &all
);
451 if (m
->defer_events_scan_dead
)
452 pa_idxset_foreach(m
->defer_events
, defer_foreach
, &all
);
454 m
->io_events_scan_dead
= m
->time_events_scan_dead
= m
->defer_events_scan_dead
= 0;
457 static void rebuild_pollfds(pa_mainloop
*m
) {
460 uint32_t idx
= PA_IDXSET_INVALID
;
463 l
= pa_idxset_size(m
->io_events
) + 1;
464 if (m
->max_pollfds
< l
) {
465 m
->pollfds
= pa_xrealloc(m
->pollfds
, sizeof(struct pollfd
)*l
);
472 if (m
->wakeup_pipe
[0] >= 0) {
473 m
->pollfds
[0].fd
= m
->wakeup_pipe
[0];
474 m
->pollfds
[0].events
= POLLIN
;
475 m
->pollfds
[0].revents
= 0;
480 for (e
= pa_idxset_first(m
->io_events
, &idx
); e
; e
= pa_idxset_next(m
->io_events
, &idx
)) {
489 ((e
->events
& PA_IO_EVENT_INPUT
) ? POLLIN
: 0) |
490 ((e
->events
& PA_IO_EVENT_OUTPUT
) ? POLLOUT
: 0) |
499 m
->rebuild_pollfds
= 0;
502 static int dispatch_pollfds(pa_mainloop
*m
) {
503 uint32_t idx
= PA_IDXSET_INVALID
;
507 for (e
= pa_idxset_first(m
->io_events
, &idx
); e
&& !m
->quit
; e
= pa_idxset_next(m
->io_events
, &idx
)) {
508 if (e
->dead
|| !e
->pollfd
|| !e
->pollfd
->revents
)
511 assert(e
->pollfd
->fd
== e
->fd
&& e
->callback
);
512 e
->callback(&m
->api
, e
, e
->fd
,
513 (e
->pollfd
->revents
& POLLHUP
? PA_IO_EVENT_HANGUP
: 0) |
514 (e
->pollfd
->revents
& POLLIN
? PA_IO_EVENT_INPUT
: 0) |
515 (e
->pollfd
->revents
& POLLOUT
? PA_IO_EVENT_OUTPUT
: 0) |
516 (e
->pollfd
->revents
& POLLERR
? PA_IO_EVENT_ERROR
: 0),
518 e
->pollfd
->revents
= 0;
525 static int dispatch_defer(pa_mainloop
*m
) {
530 if (!m
->deferred_pending
)
533 for (e
= pa_idxset_first(m
->defer_events
, &idx
); e
&& !m
->quit
; e
= pa_idxset_next(m
->defer_events
, &idx
)) {
534 if (e
->dead
|| !e
->enabled
)
538 e
->callback(&m
->api
, e
, e
->userdata
);
545 static int calc_next_timeout(pa_mainloop
*m
) {
552 if (pa_idxset_isempty(m
->time_events
))
555 for (e
= pa_idxset_first(m
->time_events
, &idx
); e
; e
= pa_idxset_next(m
->time_events
, &idx
)) {
558 if (e
->dead
|| !e
->enabled
)
561 /* Let's save a system call */
563 pa_gettimeofday(&now
);
567 if (e
->timeval
.tv_sec
< now
.tv_sec
|| (e
->timeval
.tv_sec
== now
.tv_sec
&& e
->timeval
.tv_usec
<= now
.tv_usec
))
570 tmp
= (e
->timeval
.tv_sec
- now
.tv_sec
)*1000;
572 if (e
->timeval
.tv_usec
> now
.tv_usec
)
573 tmp
+= (e
->timeval
.tv_usec
- now
.tv_usec
)/1000;
575 tmp
-= (now
.tv_usec
- e
->timeval
.tv_usec
)/1000;
579 else if (t
== -1 || tmp
< t
)
586 static int dispatch_timeout(pa_mainloop
*m
) {
594 if (pa_idxset_isempty(m
->time_events
))
597 for (e
= pa_idxset_first(m
->time_events
, &idx
); e
&& !m
->quit
; e
= pa_idxset_next(m
->time_events
, &idx
)) {
599 if (e
->dead
|| !e
->enabled
)
602 /* Let's save a system call */
604 pa_gettimeofday(&now
);
608 if (e
->timeval
.tv_sec
< now
.tv_sec
|| (e
->timeval
.tv_sec
== now
.tv_sec
&& e
->timeval
.tv_usec
<= now
.tv_usec
)) {
612 e
->callback(&m
->api
, e
, &e
->timeval
, e
->userdata
);
621 void pa_mainloop_wakeup(pa_mainloop
*m
) {
625 if (m
->wakeup_pipe
[1] >= 0)
626 pa_write(m
->wakeup_pipe
[1], &c
, sizeof(c
));
629 static void clear_wakeup(pa_mainloop
*m
) {
634 if (m
->wakeup_pipe
[0] < 0)
637 while (pa_read(m
->wakeup_pipe
[0], &c
, sizeof(c
)) == sizeof(c
));
640 int pa_mainloop_prepare(pa_mainloop
*m
, int timeout
) {
642 assert(m
->state
== STATE_PASSIVE
);
650 if (!m
->deferred_pending
) {
652 if (m
->rebuild_pollfds
)
655 m
->prepared_timeout
= calc_next_timeout(m
);
656 if (timeout
>= 0 && (timeout
< m
->prepared_timeout
|| m
->prepared_timeout
< 0))
657 m
->prepared_timeout
= timeout
;
660 m
->state
= STATE_PREPARED
;
664 m
->state
= STATE_QUIT
;
668 int pa_mainloop_poll(pa_mainloop
*m
) {
672 assert(m
->state
== STATE_PREPARED
);
677 m
->state
= STATE_POLLING
;
679 if (m
->deferred_pending
)
683 r
= m
->poll_func(m
->pollfds
, m
->n_pollfds
, m
->prepared_timeout
, m
->poll_func_userdata
);
685 r
= poll(m
->pollfds
, m
->n_pollfds
, m
->prepared_timeout
);
691 pa_log(__FILE__
": poll(): %s", strerror(errno
));
695 m
->state
= r
< 0 ? STATE_PASSIVE
: STATE_POLLED
;
699 m
->state
= STATE_QUIT
;
703 int pa_mainloop_dispatch(pa_mainloop
*m
) {
707 assert(m
->state
== STATE_POLLED
);
712 if (m
->deferred_pending
)
713 dispatched
+= dispatch_defer(m
);
715 dispatched
+= dispatch_timeout(m
);
720 dispatched
+= dispatch_pollfds(m
);
727 m
->state
= STATE_PASSIVE
;
732 m
->state
= STATE_QUIT
;
736 int pa_mainloop_get_retval(pa_mainloop
*m
) {
741 int pa_mainloop_iterate(pa_mainloop
*m
, int block
, int *retval
) {
745 if ((r
= pa_mainloop_prepare(m
, block
? -1 : 0)) < 0)
748 if ((r
= pa_mainloop_poll(m
)) < 0)
751 if ((r
= pa_mainloop_dispatch(m
)) < 0)
758 if ((r
== -2) && retval
)
759 *retval
= pa_mainloop_get_retval(m
);
763 int pa_mainloop_run(pa_mainloop
*m
, int *retval
) {
766 while ((r
= pa_mainloop_iterate(m
, 1, retval
)) >= 0);
776 void pa_mainloop_quit(pa_mainloop
*m
, int retval
) {
781 pa_mainloop_wakeup(m
);
784 pa_mainloop_api
* pa_mainloop_get_api(pa_mainloop
*m
) {
789 void pa_mainloop_set_poll_func(pa_mainloop
*m
, pa_poll_func poll_func
, void *userdata
) {
792 m
->poll_func
= poll_func
;
793 m
->poll_func_userdata
= userdata
;
798 void pa_mainloop_dump(pa_mainloop
*m
) {
801 pa_log(__FILE__
": Dumping mainloop sources START");
804 uint32_t idx
= PA_IDXSET_INVALID
;
806 for (e
= pa_idxset_first(m
->io_events
, &idx
); e
; e
= pa_idxset_next(m
->io_events
, &idx
)) {
810 pa_log(__FILE__
": kind=io fd=%i events=%i callback=%p userdata=%p", e
->fd
, (int) e
->events
, (void*) e
->callback
, (void*) e
->userdata
);
814 uint32_t idx
= PA_IDXSET_INVALID
;
816 for (e
= pa_idxset_first(m
->defer_events
, &idx
); e
; e
= pa_idxset_next(m
->defer_events
, &idx
)) {
820 pa_log(__FILE__
": kind=defer enabled=%i callback=%p userdata=%p", e
->enabled
, (void*) e
->callback
, (void*) e
->userdata
);
824 uint32_t idx
= PA_IDXSET_INVALID
;
826 for (e
= pa_idxset_first(m
->time_events
, &idx
); e
; e
= pa_idxset_next(m
->time_events
, &idx
)) {
830 pa_log(__FILE__
": kind=time enabled=%i time=%lu.%lu callback=%p userdata=%p", e
->enabled
, (unsigned long) e
->timeval
.tv_sec
, (unsigned long) e
->timeval
.tv_usec
, (void*) e
->callback
, (void*) e
->userdata
);
834 pa_log(__FILE__
": Dumping mainloop sources STOP");