2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
38 #include <pulsecore/poll.h>
42 #include <pulsecore/pipe.h>
45 #include <pulse/i18n.h>
46 #include <pulse/rtclock.h>
47 #include <pulse/timeval.h>
48 #include <pulse/xmalloc.h>
50 #include <pulsecore/core-rtclock.h>
51 #include <pulsecore/core-util.h>
52 #include <pulsecore/llist.h>
53 #include <pulsecore/log.h>
54 #include <pulsecore/core-error.h>
55 #include <pulsecore/winsock.h>
56 #include <pulsecore/macro.h>
62 pa_mainloop
*mainloop
;
66 pa_io_event_flags_t events
;
67 struct pollfd
*pollfd
;
69 pa_io_event_cb_t callback
;
71 pa_io_event_destroy_cb_t destroy_callback
;
73 PA_LLIST_FIELDS(pa_io_event
);
76 struct pa_time_event
{
77 pa_mainloop
*mainloop
;
83 pa_time_event_cb_t callback
;
85 pa_time_event_destroy_cb_t destroy_callback
;
87 PA_LLIST_FIELDS(pa_time_event
);
90 struct pa_defer_event
{
91 pa_mainloop
*mainloop
;
96 pa_defer_event_cb_t callback
;
98 pa_defer_event_destroy_cb_t destroy_callback
;
100 PA_LLIST_FIELDS(pa_defer_event
);
104 PA_LLIST_HEAD(pa_io_event
, io_events
);
105 PA_LLIST_HEAD(pa_time_event
, time_events
);
106 PA_LLIST_HEAD(pa_defer_event
, defer_events
);
108 unsigned n_enabled_defer_events
, n_enabled_time_events
, n_io_events
;
109 unsigned io_events_please_scan
, time_events_please_scan
, defer_events_please_scan
;
111 pa_bool_t rebuild_pollfds
:1;
112 struct pollfd
*pollfds
;
113 unsigned max_pollfds
, n_pollfds
;
115 int prepared_timeout
;
116 pa_time_event
*cached_next_time_event
;
123 pa_bool_t wakeup_requested
:1;
125 int wakeup_pipe_type
;
135 pa_poll_func poll_func
;
136 void *poll_func_userdata
;
140 static short map_flags_to_libc(pa_io_event_flags_t flags
) {
142 ((flags
& PA_IO_EVENT_INPUT
? POLLIN
: 0) |
143 (flags
& PA_IO_EVENT_OUTPUT
? POLLOUT
: 0) |
144 (flags
& PA_IO_EVENT_ERROR
? POLLERR
: 0) |
145 (flags
& PA_IO_EVENT_HANGUP
? POLLHUP
: 0));
148 static pa_io_event_flags_t
map_flags_from_libc(short flags
) {
150 (flags
& POLLIN
? PA_IO_EVENT_INPUT
: 0) |
151 (flags
& POLLOUT
? PA_IO_EVENT_OUTPUT
: 0) |
152 (flags
& POLLERR
? PA_IO_EVENT_ERROR
: 0) |
153 (flags
& POLLHUP
? PA_IO_EVENT_HANGUP
: 0);
157 static pa_io_event
* mainloop_io_new(
160 pa_io_event_flags_t events
,
161 pa_io_event_cb_t callback
,
168 pa_assert(a
->userdata
);
173 pa_assert(a
== &m
->api
);
175 e
= pa_xnew(pa_io_event
, 1);
183 e
->callback
= callback
;
184 e
->userdata
= userdata
;
185 e
->destroy_callback
= NULL
;
198 if ((select((SELECT_TYPE_ARG1
) fd
, NULL
, NULL
, SELECT_TYPE_ARG234
&xset
,
199 SELECT_TYPE_ARG5
&tv
) == -1) &&
200 (WSAGetLastError() == WSAENOTSOCK
)) {
201 pa_log_warn("Cannot monitor non-socket file descriptors.");
207 PA_LLIST_PREPEND(pa_io_event
, m
->io_events
, e
);
208 m
->rebuild_pollfds
= TRUE
;
211 pa_mainloop_wakeup(m
);
216 static void mainloop_io_enable(pa_io_event
*e
, pa_io_event_flags_t events
) {
220 if (e
->events
== events
)
226 e
->pollfd
->events
= map_flags_to_libc(events
);
228 e
->mainloop
->rebuild_pollfds
= TRUE
;
230 pa_mainloop_wakeup(e
->mainloop
);
233 static void mainloop_io_free(pa_io_event
*e
) {
238 e
->mainloop
->io_events_please_scan
++;
240 e
->mainloop
->n_io_events
--;
241 e
->mainloop
->rebuild_pollfds
= TRUE
;
243 pa_mainloop_wakeup(e
->mainloop
);
246 static void mainloop_io_set_destroy(pa_io_event
*e
, pa_io_event_destroy_cb_t callback
) {
249 e
->destroy_callback
= callback
;
253 static pa_defer_event
* mainloop_defer_new(
255 pa_defer_event_cb_t callback
,
262 pa_assert(a
->userdata
);
266 pa_assert(a
== &m
->api
);
268 e
= pa_xnew(pa_defer_event
, 1);
273 m
->n_enabled_defer_events
++;
275 e
->callback
= callback
;
276 e
->userdata
= userdata
;
277 e
->destroy_callback
= NULL
;
279 PA_LLIST_PREPEND(pa_defer_event
, m
->defer_events
, e
);
281 pa_mainloop_wakeup(e
->mainloop
);
286 static void mainloop_defer_enable(pa_defer_event
*e
, int b
) {
290 if (e
->enabled
&& !b
) {
291 pa_assert(e
->mainloop
->n_enabled_defer_events
> 0);
292 e
->mainloop
->n_enabled_defer_events
--;
293 } else if (!e
->enabled
&& b
) {
294 e
->mainloop
->n_enabled_defer_events
++;
295 pa_mainloop_wakeup(e
->mainloop
);
301 static void mainloop_defer_free(pa_defer_event
*e
) {
306 e
->mainloop
->defer_events_please_scan
++;
309 pa_assert(e
->mainloop
->n_enabled_defer_events
> 0);
310 e
->mainloop
->n_enabled_defer_events
--;
315 static void mainloop_defer_set_destroy(pa_defer_event
*e
, pa_defer_event_destroy_cb_t callback
) {
319 e
->destroy_callback
= callback
;
323 static pa_usec_t
timeval_load(const struct timeval
*tv
) {
324 pa_bool_t is_rtclock
;
328 return PA_USEC_INVALID
;
331 is_rtclock
= !!(ttv
.tv_usec
& PA_TIMEVAL_RTCLOCK
);
332 ttv
.tv_usec
&= ~PA_TIMEVAL_RTCLOCK
;
335 pa_rtclock_from_wallclock(&ttv
);
337 return pa_timeval_load(&ttv
);
340 static pa_time_event
* mainloop_time_new(
342 const struct timeval
*tv
,
343 pa_time_event_cb_t callback
,
351 pa_assert(a
->userdata
);
354 t
= timeval_load(tv
);
357 pa_assert(a
== &m
->api
);
359 e
= pa_xnew(pa_time_event
, 1);
363 if ((e
->enabled
= (t
!= PA_USEC_INVALID
))) {
366 m
->n_enabled_time_events
++;
368 if (m
->cached_next_time_event
) {
369 pa_assert(m
->cached_next_time_event
->enabled
);
371 if (t
< m
->cached_next_time_event
->time
)
372 m
->cached_next_time_event
= e
;
376 e
->callback
= callback
;
377 e
->userdata
= userdata
;
378 e
->destroy_callback
= NULL
;
380 PA_LLIST_PREPEND(pa_time_event
, m
->time_events
, e
);
383 pa_mainloop_wakeup(m
);
388 static void mainloop_time_restart(pa_time_event
*e
, const struct timeval
*tv
) {
395 t
= timeval_load(tv
);
397 valid
= (t
!= PA_USEC_INVALID
);
398 if (e
->enabled
&& !valid
) {
399 pa_assert(e
->mainloop
->n_enabled_time_events
> 0);
400 e
->mainloop
->n_enabled_time_events
--;
401 } else if (!e
->enabled
&& valid
)
402 e
->mainloop
->n_enabled_time_events
++;
404 if ((e
->enabled
= valid
)) {
406 pa_mainloop_wakeup(e
->mainloop
);
409 if (e
->mainloop
->cached_next_time_event
&& e
->enabled
) {
410 pa_assert(e
->mainloop
->cached_next_time_event
->enabled
);
412 if (t
< e
->mainloop
->cached_next_time_event
->time
)
413 e
->mainloop
->cached_next_time_event
= e
;
414 } else if (e
->mainloop
->cached_next_time_event
== e
)
415 e
->mainloop
->cached_next_time_event
= NULL
;
418 static void mainloop_time_free(pa_time_event
*e
) {
423 e
->mainloop
->time_events_please_scan
++;
426 pa_assert(e
->mainloop
->n_enabled_time_events
> 0);
427 e
->mainloop
->n_enabled_time_events
--;
431 if (e
->mainloop
->cached_next_time_event
== e
)
432 e
->mainloop
->cached_next_time_event
= NULL
;
434 /* no wakeup needed here. Think about it! */
437 static void mainloop_time_set_destroy(pa_time_event
*e
, pa_time_event_destroy_cb_t callback
) {
441 e
->destroy_callback
= callback
;
446 static void mainloop_quit(pa_mainloop_api
*a
, int retval
) {
450 pa_assert(a
->userdata
);
452 pa_assert(a
== &m
->api
);
454 pa_mainloop_quit(m
, retval
);
457 static const pa_mainloop_api vtable
= {
460 .io_new
= mainloop_io_new
,
461 .io_enable
= mainloop_io_enable
,
462 .io_free
= mainloop_io_free
,
463 .io_set_destroy
= mainloop_io_set_destroy
,
465 .time_new
= mainloop_time_new
,
466 .time_restart
= mainloop_time_restart
,
467 .time_free
= mainloop_time_free
,
468 .time_set_destroy
= mainloop_time_set_destroy
,
470 .defer_new
= mainloop_defer_new
,
471 .defer_enable
= mainloop_defer_enable
,
472 .defer_free
= mainloop_defer_free
,
473 .defer_set_destroy
= mainloop_defer_set_destroy
,
475 .quit
= mainloop_quit
,
478 pa_mainloop
*pa_mainloop_new(void) {
483 m
= pa_xnew(pa_mainloop
, 1);
485 m
->wakeup_pipe_type
= 0;
486 if (pipe(m
->wakeup_pipe
) < 0) {
487 pa_log_error("ERROR: cannot create wakeup pipe");
492 pa_make_fd_nonblock(m
->wakeup_pipe
[0]);
493 pa_make_fd_nonblock(m
->wakeup_pipe
[1]);
494 pa_make_fd_cloexec(m
->wakeup_pipe
[0]);
495 pa_make_fd_cloexec(m
->wakeup_pipe
[1]);
496 m
->wakeup_requested
= FALSE
;
498 PA_LLIST_HEAD_INIT(pa_io_event
, m
->io_events
);
499 PA_LLIST_HEAD_INIT(pa_time_event
, m
->time_events
);
500 PA_LLIST_HEAD_INIT(pa_defer_event
, m
->defer_events
);
502 m
->n_enabled_defer_events
= m
->n_enabled_time_events
= m
->n_io_events
= 0;
503 m
->io_events_please_scan
= m
->time_events_please_scan
= m
->defer_events_please_scan
= 0;
505 m
->cached_next_time_event
= NULL
;
506 m
->prepared_timeout
= 0;
509 m
->max_pollfds
= m
->n_pollfds
= 0;
510 m
->rebuild_pollfds
= TRUE
;
518 m
->state
= STATE_PASSIVE
;
521 m
->poll_func_userdata
= NULL
;
522 m
->poll_func_ret
= -1;
527 static void cleanup_io_events(pa_mainloop
*m
, pa_bool_t force
) {
532 pa_io_event
*n
= e
->next
;
534 if (!force
&& m
->io_events_please_scan
<= 0)
537 if (force
|| e
->dead
) {
538 PA_LLIST_REMOVE(pa_io_event
, m
->io_events
, e
);
541 pa_assert(m
->io_events_please_scan
> 0);
542 m
->io_events_please_scan
--;
545 if (e
->destroy_callback
)
546 e
->destroy_callback(&m
->api
, e
, e
->userdata
);
550 m
->rebuild_pollfds
= TRUE
;
556 pa_assert(m
->io_events_please_scan
== 0);
559 static void cleanup_time_events(pa_mainloop
*m
, pa_bool_t force
) {
564 pa_time_event
*n
= e
->next
;
566 if (!force
&& m
->time_events_please_scan
<= 0)
569 if (force
|| e
->dead
) {
570 PA_LLIST_REMOVE(pa_time_event
, m
->time_events
, e
);
573 pa_assert(m
->time_events_please_scan
> 0);
574 m
->time_events_please_scan
--;
577 if (!e
->dead
&& e
->enabled
) {
578 pa_assert(m
->n_enabled_time_events
> 0);
579 m
->n_enabled_time_events
--;
583 if (e
->destroy_callback
)
584 e
->destroy_callback(&m
->api
, e
, e
->userdata
);
592 pa_assert(m
->time_events_please_scan
== 0);
595 static void cleanup_defer_events(pa_mainloop
*m
, pa_bool_t force
) {
600 pa_defer_event
*n
= e
->next
;
602 if (!force
&& m
->defer_events_please_scan
<= 0)
605 if (force
|| e
->dead
) {
606 PA_LLIST_REMOVE(pa_defer_event
, m
->defer_events
, e
);
609 pa_assert(m
->defer_events_please_scan
> 0);
610 m
->defer_events_please_scan
--;
613 if (!e
->dead
&& e
->enabled
) {
614 pa_assert(m
->n_enabled_defer_events
> 0);
615 m
->n_enabled_defer_events
--;
619 if (e
->destroy_callback
)
620 e
->destroy_callback(&m
->api
, e
, e
->userdata
);
628 pa_assert(m
->defer_events_please_scan
== 0);
632 void pa_mainloop_free(pa_mainloop
* m
) {
635 cleanup_io_events(m
, TRUE
);
636 cleanup_defer_events(m
, TRUE
);
637 cleanup_time_events(m
, TRUE
);
639 pa_xfree(m
->pollfds
);
641 pa_close_pipe(m
->wakeup_pipe
);
646 static void scan_dead(pa_mainloop
*m
) {
649 if (m
->io_events_please_scan
)
650 cleanup_io_events(m
, FALSE
);
652 if (m
->time_events_please_scan
)
653 cleanup_time_events(m
, FALSE
);
655 if (m
->defer_events_please_scan
)
656 cleanup_defer_events(m
, FALSE
);
659 static void rebuild_pollfds(pa_mainloop
*m
) {
664 l
= m
->n_io_events
+ 1;
665 if (m
->max_pollfds
< l
) {
667 m
->pollfds
= pa_xrealloc(m
->pollfds
, sizeof(struct pollfd
)*l
);
674 if (m
->wakeup_pipe
[0] >= 0) {
675 m
->pollfds
[0].fd
= m
->wakeup_pipe
[0];
676 m
->pollfds
[0].events
= POLLIN
;
677 m
->pollfds
[0].revents
= 0;
682 for (e
= m
->io_events
; e
; e
= e
->next
) {
690 p
->events
= map_flags_to_libc(e
->events
);
697 m
->rebuild_pollfds
= FALSE
;
700 static int dispatch_pollfds(pa_mainloop
*m
) {
704 pa_assert(m
->poll_func_ret
> 0);
706 for (e
= m
->io_events
, k
= m
->poll_func_ret
; e
&& !m
->quit
&& k
> 0; e
= e
->next
) {
707 if (e
->dead
|| !e
->pollfd
|| !e
->pollfd
->revents
)
710 pa_assert(e
->pollfd
->fd
== e
->fd
);
711 pa_assert(e
->callback
);
712 e
->callback(&m
->api
, e
, e
->fd
, map_flags_from_libc(e
->pollfd
->revents
), e
->userdata
);
713 e
->pollfd
->revents
= 0;
722 static int dispatch_defer(pa_mainloop
*m
) {
726 if (m
->n_enabled_defer_events
<= 0)
729 for (e
= m
->defer_events
; e
&& !m
->quit
; e
= e
->next
) {
730 if (e
->dead
|| !e
->enabled
)
733 pa_assert(e
->callback
);
734 e
->callback(&m
->api
, e
, e
->userdata
);
741 static pa_time_event
* find_next_time_event(pa_mainloop
*m
) {
742 pa_time_event
*t
, *n
= NULL
;
745 if (m
->cached_next_time_event
)
746 return m
->cached_next_time_event
;
748 for (t
= m
->time_events
; t
; t
= t
->next
) {
750 if (t
->dead
|| !t
->enabled
)
753 if (!n
|| t
->time
< n
->time
) {
756 /* Shortcut for time == 0 */
762 m
->cached_next_time_event
= n
;
766 static int calc_next_timeout(pa_mainloop
*m
) {
770 if (!m
->n_enabled_time_events
)
773 t
= find_next_time_event(m
);
779 usec
= t
->time
- pa_rtclock_now();
784 return (int) (usec
/ 1000); /* in milliseconds */
787 static int dispatch_timeout(pa_mainloop
*m
) {
793 if (m
->n_enabled_time_events
<= 0)
796 now
= pa_rtclock_now();
798 for (e
= m
->time_events
; e
&& !m
->quit
; e
= e
->next
) {
800 if (e
->dead
|| !e
->enabled
)
803 if (e
->time
<= now
) {
805 pa_assert(e
->callback
);
807 /* Disable time event */
808 mainloop_time_restart(e
, NULL
);
810 e
->callback(&m
->api
, e
, pa_timeval_rtstore(&tv
, e
->time
, TRUE
), e
->userdata
);
819 void pa_mainloop_wakeup(pa_mainloop
*m
) {
823 if (m
->wakeup_pipe
[1] >= 0 && m
->state
== STATE_POLLING
) {
824 pa_write(m
->wakeup_pipe
[1], &c
, sizeof(c
), &m
->wakeup_pipe_type
);
825 m
->wakeup_requested
++;
829 static void clear_wakeup(pa_mainloop
*m
) {
834 if (m
->wakeup_pipe
[0] < 0)
837 if (m
->wakeup_requested
) {
838 while (pa_read(m
->wakeup_pipe
[0], &c
, sizeof(c
), &m
->wakeup_pipe_type
) == sizeof(c
));
839 m
->wakeup_requested
= 0;
843 int pa_mainloop_prepare(pa_mainloop
*m
, int timeout
) {
845 pa_assert(m
->state
== STATE_PASSIVE
);
853 if (m
->n_enabled_defer_events
<= 0) {
854 if (m
->rebuild_pollfds
)
857 m
->prepared_timeout
= calc_next_timeout(m
);
858 if (timeout
>= 0 && (timeout
< m
->prepared_timeout
|| m
->prepared_timeout
< 0))
859 m
->prepared_timeout
= timeout
;
862 m
->state
= STATE_PREPARED
;
866 m
->state
= STATE_QUIT
;
870 int pa_mainloop_poll(pa_mainloop
*m
) {
872 pa_assert(m
->state
== STATE_PREPARED
);
877 m
->state
= STATE_POLLING
;
879 if (m
->n_enabled_defer_events
)
880 m
->poll_func_ret
= 0;
882 pa_assert(!m
->rebuild_pollfds
);
885 m
->poll_func_ret
= m
->poll_func(m
->pollfds
, m
->n_pollfds
, m
->prepared_timeout
, m
->poll_func_userdata
);
887 m
->poll_func_ret
= poll(m
->pollfds
, m
->n_pollfds
, m
->prepared_timeout
);
889 if (m
->poll_func_ret
< 0) {
891 m
->poll_func_ret
= 0;
893 pa_log("poll(): %s", pa_cstrerror(errno
));
897 m
->state
= m
->poll_func_ret
< 0 ? STATE_PASSIVE
: STATE_POLLED
;
898 return m
->poll_func_ret
;
901 m
->state
= STATE_QUIT
;
905 int pa_mainloop_dispatch(pa_mainloop
*m
) {
909 pa_assert(m
->state
== STATE_POLLED
);
914 if (m
->n_enabled_defer_events
)
915 dispatched
+= dispatch_defer(m
);
917 if (m
->n_enabled_time_events
)
918 dispatched
+= dispatch_timeout(m
);
923 if (m
->poll_func_ret
> 0)
924 dispatched
+= dispatch_pollfds(m
);
930 m
->state
= STATE_PASSIVE
;
935 m
->state
= STATE_QUIT
;
939 int pa_mainloop_get_retval(pa_mainloop
*m
) {
944 int pa_mainloop_iterate(pa_mainloop
*m
, int block
, int *retval
) {
948 if ((r
= pa_mainloop_prepare(m
, block
? -1 : 0)) < 0)
951 if ((r
= pa_mainloop_poll(m
)) < 0)
954 if ((r
= pa_mainloop_dispatch(m
)) < 0)
961 if ((r
== -2) && retval
)
962 *retval
= pa_mainloop_get_retval(m
);
966 int pa_mainloop_run(pa_mainloop
*m
, int *retval
) {
969 while ((r
= pa_mainloop_iterate(m
, 1, retval
)) >= 0);
979 void pa_mainloop_quit(pa_mainloop
*m
, int retval
) {
984 pa_mainloop_wakeup(m
);
987 pa_mainloop_api
* pa_mainloop_get_api(pa_mainloop
*m
) {
992 void pa_mainloop_set_poll_func(pa_mainloop
*m
, pa_poll_func poll_func
, void *userdata
) {
995 m
->poll_func
= poll_func
;
996 m
->poll_func_userdata
= userdata
;
999 pa_bool_t
pa_mainloop_is_our_api(pa_mainloop_api
*m
) {
1002 return m
->io_new
== mainloop_io_new
;