bluetooth: accept temporarily unavailable error
[pulseaudio-mirror.git] / src / pulse / mainloop.c
blob225fd0981451e095b491b9ddecfeb19d909ca430
1 /***
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
20 USA.
21 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <stdio.h>
28 #include <signal.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <errno.h>
35 #ifdef HAVE_POLL_H
36 #include <poll.h>
37 #else
38 #include <pulsecore/poll.h>
39 #endif
41 #ifndef HAVE_PIPE
42 #include <pulsecore/pipe.h>
43 #endif
45 #include <pulse/timeval.h>
46 #include <pulse/xmalloc.h>
47 #include <pulse/i18n.h>
49 #include <pulsecore/core-util.h>
50 #include <pulsecore/llist.h>
51 #include <pulsecore/log.h>
52 #include <pulsecore/core-error.h>
53 #include <pulsecore/winsock.h>
54 #include <pulsecore/macro.h>
56 #include "mainloop.h"
58 struct pa_io_event {
59 pa_mainloop *mainloop;
60 pa_bool_t dead:1;
62 int fd;
63 pa_io_event_flags_t events;
64 struct pollfd *pollfd;
66 pa_io_event_cb_t callback;
67 void *userdata;
68 pa_io_event_destroy_cb_t destroy_callback;
70 PA_LLIST_FIELDS(pa_io_event);
73 struct pa_time_event {
74 pa_mainloop *mainloop;
75 pa_bool_t dead:1;
77 pa_bool_t enabled:1;
78 struct timeval timeval;
80 pa_time_event_cb_t callback;
81 void *userdata;
82 pa_time_event_destroy_cb_t destroy_callback;
84 PA_LLIST_FIELDS(pa_time_event);
87 struct pa_defer_event {
88 pa_mainloop *mainloop;
89 pa_bool_t dead:1;
91 pa_bool_t enabled:1;
93 pa_defer_event_cb_t callback;
94 void *userdata;
95 pa_defer_event_destroy_cb_t destroy_callback;
97 PA_LLIST_FIELDS(pa_defer_event);
100 struct pa_mainloop {
101 PA_LLIST_HEAD(pa_io_event, io_events);
102 PA_LLIST_HEAD(pa_time_event, time_events);
103 PA_LLIST_HEAD(pa_defer_event, defer_events);
105 unsigned n_enabled_defer_events, n_enabled_time_events, n_io_events;
106 unsigned io_events_please_scan, time_events_please_scan, defer_events_please_scan;
108 pa_bool_t rebuild_pollfds:1;
109 struct pollfd *pollfds;
110 unsigned max_pollfds, n_pollfds;
112 int prepared_timeout;
113 pa_time_event *cached_next_time_event;
115 pa_mainloop_api api;
117 int retval;
118 pa_bool_t quit:1;
120 pa_bool_t wakeup_requested:1;
121 int wakeup_pipe[2];
122 int wakeup_pipe_type;
124 enum {
125 STATE_PASSIVE,
126 STATE_PREPARED,
127 STATE_POLLING,
128 STATE_POLLED,
129 STATE_QUIT
130 } state;
132 pa_poll_func poll_func;
133 void *poll_func_userdata;
134 int poll_func_ret;
137 static short map_flags_to_libc(pa_io_event_flags_t flags) {
138 return (short)
139 ((flags & PA_IO_EVENT_INPUT ? POLLIN : 0) |
140 (flags & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) |
141 (flags & PA_IO_EVENT_ERROR ? POLLERR : 0) |
142 (flags & PA_IO_EVENT_HANGUP ? POLLHUP : 0));
145 static pa_io_event_flags_t map_flags_from_libc(short flags) {
146 return
147 (flags & POLLIN ? PA_IO_EVENT_INPUT : 0) |
148 (flags & POLLOUT ? PA_IO_EVENT_OUTPUT : 0) |
149 (flags & POLLERR ? PA_IO_EVENT_ERROR : 0) |
150 (flags & POLLHUP ? PA_IO_EVENT_HANGUP : 0);
153 /* IO events */
154 static pa_io_event* mainloop_io_new(
155 pa_mainloop_api*a,
156 int fd,
157 pa_io_event_flags_t events,
158 pa_io_event_cb_t callback,
159 void *userdata) {
161 pa_mainloop *m;
162 pa_io_event *e;
164 pa_assert(a);
165 pa_assert(a->userdata);
166 pa_assert(fd >= 0);
167 pa_assert(callback);
169 m = a->userdata;
170 pa_assert(a == &m->api);
172 e = pa_xnew(pa_io_event, 1);
173 e->mainloop = m;
174 e->dead = FALSE;
176 e->fd = fd;
177 e->events = events;
178 e->pollfd = NULL;
180 e->callback = callback;
181 e->userdata = userdata;
182 e->destroy_callback = NULL;
184 #ifdef OS_IS_WIN32
186 fd_set xset;
187 struct timeval tv;
189 tv.tv_sec = 0;
190 tv.tv_usec = 0;
192 FD_ZERO (&xset);
193 FD_SET (fd, &xset);
195 if ((select((SELECT_TYPE_ARG1) fd, NULL, NULL, SELECT_TYPE_ARG234 &xset,
196 SELECT_TYPE_ARG5 &tv) == -1) &&
197 (WSAGetLastError() == WSAENOTSOCK)) {
198 pa_log_warn("Cannot monitor non-socket file descriptors.");
199 e->dead = TRUE;
202 #endif
204 PA_LLIST_PREPEND(pa_io_event, m->io_events, e);
205 m->rebuild_pollfds = TRUE;
206 m->n_io_events ++;
208 pa_mainloop_wakeup(m);
210 return e;
213 static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) {
214 pa_assert(e);
215 pa_assert(!e->dead);
217 if (e->events == events)
218 return;
220 e->events = events;
222 if (e->pollfd)
223 e->pollfd->events = map_flags_to_libc(events);
224 else
225 e->mainloop->rebuild_pollfds = TRUE;
227 pa_mainloop_wakeup(e->mainloop);
230 static void mainloop_io_free(pa_io_event *e) {
231 pa_assert(e);
232 pa_assert(!e->dead);
234 e->dead = TRUE;
235 e->mainloop->io_events_please_scan ++;
237 e->mainloop->n_io_events --;
238 e->mainloop->rebuild_pollfds = TRUE;
240 pa_mainloop_wakeup(e->mainloop);
243 static void mainloop_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t callback) {
244 pa_assert(e);
246 e->destroy_callback = callback;
249 /* Defer events */
250 static pa_defer_event* mainloop_defer_new(
251 pa_mainloop_api*a,
252 pa_defer_event_cb_t callback,
253 void *userdata) {
255 pa_mainloop *m;
256 pa_defer_event *e;
258 pa_assert(a);
259 pa_assert(a->userdata);
260 pa_assert(callback);
262 m = a->userdata;
263 pa_assert(a == &m->api);
265 e = pa_xnew(pa_defer_event, 1);
266 e->mainloop = m;
267 e->dead = FALSE;
269 e->enabled = TRUE;
270 m->n_enabled_defer_events++;
272 e->callback = callback;
273 e->userdata = userdata;
274 e->destroy_callback = NULL;
276 PA_LLIST_PREPEND(pa_defer_event, m->defer_events, e);
278 pa_mainloop_wakeup(e->mainloop);
280 return e;
283 static void mainloop_defer_enable(pa_defer_event *e, int b) {
284 pa_assert(e);
285 pa_assert(!e->dead);
287 if (e->enabled && !b) {
288 pa_assert(e->mainloop->n_enabled_defer_events > 0);
289 e->mainloop->n_enabled_defer_events--;
290 } else if (!e->enabled && b) {
291 e->mainloop->n_enabled_defer_events++;
292 pa_mainloop_wakeup(e->mainloop);
295 e->enabled = b;
298 static void mainloop_defer_free(pa_defer_event *e) {
299 pa_assert(e);
300 pa_assert(!e->dead);
302 e->dead = TRUE;
303 e->mainloop->defer_events_please_scan ++;
305 if (e->enabled) {
306 pa_assert(e->mainloop->n_enabled_defer_events > 0);
307 e->mainloop->n_enabled_defer_events--;
308 e->enabled = FALSE;
312 static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t callback) {
313 pa_assert(e);
314 pa_assert(!e->dead);
316 e->destroy_callback = callback;
319 /* Time events */
320 static pa_time_event* mainloop_time_new(
321 pa_mainloop_api*a,
322 const struct timeval *tv,
323 pa_time_event_cb_t callback,
324 void *userdata) {
326 pa_mainloop *m;
327 pa_time_event *e;
329 pa_assert(a);
330 pa_assert(a->userdata);
331 pa_assert(callback);
333 m = a->userdata;
334 pa_assert(a == &m->api);
336 e = pa_xnew(pa_time_event, 1);
337 e->mainloop = m;
338 e->dead = FALSE;
340 if ((e->enabled = !!tv)) {
341 e->timeval = *tv;
343 m->n_enabled_time_events++;
345 if (m->cached_next_time_event) {
346 pa_assert(m->cached_next_time_event->enabled);
348 if (pa_timeval_cmp(tv, &m->cached_next_time_event->timeval) < 0)
349 m->cached_next_time_event = e;
353 e->callback = callback;
354 e->userdata = userdata;
355 e->destroy_callback = NULL;
357 PA_LLIST_PREPEND(pa_time_event, m->time_events, e);
359 if (e->enabled)
360 pa_mainloop_wakeup(m);
362 return e;
365 static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
366 pa_assert(e);
367 pa_assert(!e->dead);
369 if (e->enabled && !tv) {
370 pa_assert(e->mainloop->n_enabled_time_events > 0);
371 e->mainloop->n_enabled_time_events--;
372 } else if (!e->enabled && tv)
373 e->mainloop->n_enabled_time_events++;
375 if ((e->enabled = !!tv)) {
376 e->timeval = *tv;
377 pa_mainloop_wakeup(e->mainloop);
380 if (e->mainloop->cached_next_time_event && e->enabled) {
381 pa_assert(e->mainloop->cached_next_time_event->enabled);
383 if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0)
384 e->mainloop->cached_next_time_event = e;
385 } else if (e->mainloop->cached_next_time_event == e)
386 e->mainloop->cached_next_time_event = NULL;
389 static void mainloop_time_free(pa_time_event *e) {
390 pa_assert(e);
391 pa_assert(!e->dead);
393 e->dead = TRUE;
394 e->mainloop->time_events_please_scan ++;
396 if (e->enabled) {
397 pa_assert(e->mainloop->n_enabled_time_events > 0);
398 e->mainloop->n_enabled_time_events--;
399 e->enabled = FALSE;
402 if (e->mainloop->cached_next_time_event == e)
403 e->mainloop->cached_next_time_event = NULL;
405 /* no wakeup needed here. Think about it! */
408 static void mainloop_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t callback) {
409 pa_assert(e);
410 pa_assert(!e->dead);
412 e->destroy_callback = callback;
415 /* quit() */
417 static void mainloop_quit(pa_mainloop_api*a, int retval) {
418 pa_mainloop *m;
420 pa_assert(a);
421 pa_assert(a->userdata);
422 m = a->userdata;
423 pa_assert(a == &m->api);
425 pa_mainloop_quit(m, retval);
428 static const pa_mainloop_api vtable = {
429 .userdata = NULL,
431 .io_new= mainloop_io_new,
432 .io_enable= mainloop_io_enable,
433 .io_free= mainloop_io_free,
434 .io_set_destroy= mainloop_io_set_destroy,
436 .time_new = mainloop_time_new,
437 .time_restart = mainloop_time_restart,
438 .time_free = mainloop_time_free,
439 .time_set_destroy = mainloop_time_set_destroy,
441 .defer_new = mainloop_defer_new,
442 .defer_enable = mainloop_defer_enable,
443 .defer_free = mainloop_defer_free,
444 .defer_set_destroy = mainloop_defer_set_destroy,
446 .quit = mainloop_quit,
449 pa_mainloop *pa_mainloop_new(void) {
450 pa_mainloop *m;
452 pa_init_i18n();
454 m = pa_xnew(pa_mainloop, 1);
456 m->wakeup_pipe_type = 0;
457 if (pipe(m->wakeup_pipe) < 0) {
458 pa_log_error("ERROR: cannot create wakeup pipe");
459 pa_xfree(m);
460 return NULL;
463 pa_make_fd_nonblock(m->wakeup_pipe[0]);
464 pa_make_fd_nonblock(m->wakeup_pipe[1]);
465 pa_make_fd_cloexec(m->wakeup_pipe[0]);
466 pa_make_fd_cloexec(m->wakeup_pipe[1]);
467 m->wakeup_requested = FALSE;
469 PA_LLIST_HEAD_INIT(pa_io_event, m->io_events);
470 PA_LLIST_HEAD_INIT(pa_time_event, m->time_events);
471 PA_LLIST_HEAD_INIT(pa_defer_event, m->defer_events);
473 m->n_enabled_defer_events = m->n_enabled_time_events = m->n_io_events = 0;
474 m->io_events_please_scan = m->time_events_please_scan = m->defer_events_please_scan = 0;
476 m->cached_next_time_event = NULL;
477 m->prepared_timeout = 0;
479 m->pollfds = NULL;
480 m->max_pollfds = m->n_pollfds = 0;
481 m->rebuild_pollfds = TRUE;
483 m->quit = FALSE;
484 m->retval = 0;
486 m->api = vtable;
487 m->api.userdata = m;
489 m->state = STATE_PASSIVE;
491 m->poll_func = NULL;
492 m->poll_func_userdata = NULL;
493 m->poll_func_ret = -1;
495 return m;
498 static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) {
499 pa_io_event *e;
501 e = m->io_events;
502 while (e) {
503 pa_io_event *n = e->next;
505 if (!force && m->io_events_please_scan <= 0)
506 break;
508 if (force || e->dead) {
509 PA_LLIST_REMOVE(pa_io_event, m->io_events, e);
511 if (e->dead) {
512 pa_assert(m->io_events_please_scan > 0);
513 m->io_events_please_scan--;
516 if (e->destroy_callback)
517 e->destroy_callback(&m->api, e, e->userdata);
519 pa_xfree(e);
521 m->rebuild_pollfds = TRUE;
524 e = n;
527 pa_assert(m->io_events_please_scan == 0);
530 static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) {
531 pa_time_event *e;
533 e = m->time_events;
534 while (e) {
535 pa_time_event *n = e->next;
537 if (!force && m->time_events_please_scan <= 0)
538 break;
540 if (force || e->dead) {
541 PA_LLIST_REMOVE(pa_time_event, m->time_events, e);
543 if (e->dead) {
544 pa_assert(m->time_events_please_scan > 0);
545 m->time_events_please_scan--;
548 if (!e->dead && e->enabled) {
549 pa_assert(m->n_enabled_time_events > 0);
550 m->n_enabled_time_events--;
551 e->enabled = FALSE;
554 if (e->destroy_callback)
555 e->destroy_callback(&m->api, e, e->userdata);
557 pa_xfree(e);
560 e = n;
563 pa_assert(m->time_events_please_scan == 0);
566 static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) {
567 pa_defer_event *e;
569 e = m->defer_events;
570 while (e) {
571 pa_defer_event *n = e->next;
573 if (!force && m->defer_events_please_scan <= 0)
574 break;
576 if (force || e->dead) {
577 PA_LLIST_REMOVE(pa_defer_event, m->defer_events, e);
579 if (e->dead) {
580 pa_assert(m->defer_events_please_scan > 0);
581 m->defer_events_please_scan--;
584 if (!e->dead && e->enabled) {
585 pa_assert(m->n_enabled_defer_events > 0);
586 m->n_enabled_defer_events--;
587 e->enabled = FALSE;
590 if (e->destroy_callback)
591 e->destroy_callback(&m->api, e, e->userdata);
593 pa_xfree(e);
596 e = n;
599 pa_assert(m->defer_events_please_scan == 0);
603 void pa_mainloop_free(pa_mainloop* m) {
604 pa_assert(m);
606 cleanup_io_events(m, TRUE);
607 cleanup_defer_events(m, TRUE);
608 cleanup_time_events(m, TRUE);
610 pa_xfree(m->pollfds);
612 pa_close_pipe(m->wakeup_pipe);
614 pa_xfree(m);
617 static void scan_dead(pa_mainloop *m) {
618 pa_assert(m);
620 if (m->io_events_please_scan)
621 cleanup_io_events(m, FALSE);
623 if (m->time_events_please_scan)
624 cleanup_time_events(m, FALSE);
626 if (m->defer_events_please_scan)
627 cleanup_defer_events(m, FALSE);
630 static void rebuild_pollfds(pa_mainloop *m) {
631 pa_io_event*e;
632 struct pollfd *p;
633 unsigned l;
635 l = m->n_io_events + 1;
636 if (m->max_pollfds < l) {
637 l *= 2;
638 m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l);
639 m->max_pollfds = l;
642 m->n_pollfds = 0;
643 p = m->pollfds;
645 if (m->wakeup_pipe[0] >= 0) {
646 m->pollfds[0].fd = m->wakeup_pipe[0];
647 m->pollfds[0].events = POLLIN;
648 m->pollfds[0].revents = 0;
649 p++;
650 m->n_pollfds++;
653 for (e = m->io_events; e; e = e->next) {
654 if (e->dead) {
655 e->pollfd = NULL;
656 continue;
659 e->pollfd = p;
660 p->fd = e->fd;
661 p->events = map_flags_to_libc(e->events);
662 p->revents = 0;
664 p++;
665 m->n_pollfds++;
668 m->rebuild_pollfds = FALSE;
671 static int dispatch_pollfds(pa_mainloop *m) {
672 pa_io_event *e;
673 int r = 0, k;
675 pa_assert(m->poll_func_ret > 0);
677 for (e = m->io_events, k = m->poll_func_ret; e && !m->quit && k > 0; e = e->next) {
678 if (e->dead || !e->pollfd || !e->pollfd->revents)
679 continue;
681 pa_assert(e->pollfd->fd == e->fd);
682 pa_assert(e->callback);
683 e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata);
684 e->pollfd->revents = 0;
685 r++;
687 k--;
690 return r;
693 static int dispatch_defer(pa_mainloop *m) {
694 pa_defer_event *e;
695 int r = 0;
697 if (m->n_enabled_defer_events <= 0)
698 return 0;
700 for (e = m->defer_events; e && !m->quit; e = e->next) {
701 if (e->dead || !e->enabled)
702 continue;
704 pa_assert(e->callback);
705 e->callback(&m->api, e, e->userdata);
706 r++;
709 return r;
712 static pa_time_event* find_next_time_event(pa_mainloop *m) {
713 pa_time_event *t, *n = NULL;
714 pa_assert(m);
716 if (m->cached_next_time_event)
717 return m->cached_next_time_event;
719 for (t = m->time_events; t; t = t->next) {
721 if (t->dead || !t->enabled)
722 continue;
724 if (!n || pa_timeval_cmp(&t->timeval, &n->timeval) < 0) {
725 n = t;
727 /* Shortcut for tv = { 0, 0 } */
728 if (n->timeval.tv_sec <= 0)
729 break;
733 m->cached_next_time_event = n;
734 return n;
737 static int calc_next_timeout(pa_mainloop *m) {
738 pa_time_event *t;
739 struct timeval now;
740 pa_usec_t usec;
742 if (!m->n_enabled_time_events)
743 return -1;
745 t = find_next_time_event(m);
746 pa_assert(t);
748 if (t->timeval.tv_sec <= 0)
749 return 0;
751 pa_gettimeofday(&now);
753 if (pa_timeval_cmp(&t->timeval, &now) <= 0)
754 return 0;
756 usec = pa_timeval_diff(&t->timeval, &now);
757 return (int) (usec / 1000);
760 static int dispatch_timeout(pa_mainloop *m) {
761 pa_time_event *e;
762 struct timeval now;
763 int r = 0;
764 pa_assert(m);
766 if (m->n_enabled_time_events <= 0)
767 return 0;
769 pa_gettimeofday(&now);
771 for (e = m->time_events; e && !m->quit; e = e->next) {
773 if (e->dead || !e->enabled)
774 continue;
776 if (pa_timeval_cmp(&e->timeval, &now) <= 0) {
777 pa_assert(e->callback);
779 /* Disable time event */
780 mainloop_time_restart(e, NULL);
782 e->callback(&m->api, e, &e->timeval, e->userdata);
784 r++;
788 return r;
791 void pa_mainloop_wakeup(pa_mainloop *m) {
792 char c = 'W';
793 pa_assert(m);
795 if (m->wakeup_pipe[1] >= 0 && m->state == STATE_POLLING) {
796 pa_write(m->wakeup_pipe[1], &c, sizeof(c), &m->wakeup_pipe_type);
797 m->wakeup_requested++;
801 static void clear_wakeup(pa_mainloop *m) {
802 char c[10];
804 pa_assert(m);
806 if (m->wakeup_pipe[0] < 0)
807 return;
809 if (m->wakeup_requested) {
810 while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c));
811 m->wakeup_requested = 0;
815 int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
816 pa_assert(m);
817 pa_assert(m->state == STATE_PASSIVE);
819 clear_wakeup(m);
820 scan_dead(m);
822 if (m->quit)
823 goto quit;
825 if (m->n_enabled_defer_events <= 0) {
826 if (m->rebuild_pollfds)
827 rebuild_pollfds(m);
829 m->prepared_timeout = calc_next_timeout(m);
830 if (timeout >= 0 && (timeout < m->prepared_timeout || m->prepared_timeout < 0))
831 m->prepared_timeout = timeout;
834 m->state = STATE_PREPARED;
835 return 0;
837 quit:
838 m->state = STATE_QUIT;
839 return -2;
842 int pa_mainloop_poll(pa_mainloop *m) {
843 pa_assert(m);
844 pa_assert(m->state == STATE_PREPARED);
846 if (m->quit)
847 goto quit;
849 m->state = STATE_POLLING;
851 if (m->n_enabled_defer_events )
852 m->poll_func_ret = 0;
853 else {
854 pa_assert(!m->rebuild_pollfds);
856 if (m->poll_func)
857 m->poll_func_ret = m->poll_func(m->pollfds, m->n_pollfds, m->prepared_timeout, m->poll_func_userdata);
858 else
859 m->poll_func_ret = poll(m->pollfds, m->n_pollfds, m->prepared_timeout);
861 if (m->poll_func_ret < 0) {
862 if (errno == EINTR)
863 m->poll_func_ret = 0;
864 else
865 pa_log("poll(): %s", pa_cstrerror(errno));
869 m->state = m->poll_func_ret < 0 ? STATE_PASSIVE : STATE_POLLED;
870 return m->poll_func_ret;
872 quit:
873 m->state = STATE_QUIT;
874 return -2;
877 int pa_mainloop_dispatch(pa_mainloop *m) {
878 int dispatched = 0;
880 pa_assert(m);
881 pa_assert(m->state == STATE_POLLED);
883 if (m->quit)
884 goto quit;
886 if (m->n_enabled_defer_events)
887 dispatched += dispatch_defer(m);
888 else {
889 if (m->n_enabled_time_events)
890 dispatched += dispatch_timeout(m);
892 if (m->quit)
893 goto quit;
895 if (m->poll_func_ret > 0)
896 dispatched += dispatch_pollfds(m);
899 if (m->quit)
900 goto quit;
902 m->state = STATE_PASSIVE;
904 return dispatched;
906 quit:
907 m->state = STATE_QUIT;
908 return -2;
911 int pa_mainloop_get_retval(pa_mainloop *m) {
912 pa_assert(m);
913 return m->retval;
916 int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) {
917 int r;
918 pa_assert(m);
920 if ((r = pa_mainloop_prepare(m, block ? -1 : 0)) < 0)
921 goto quit;
923 if ((r = pa_mainloop_poll(m)) < 0)
924 goto quit;
926 if ((r = pa_mainloop_dispatch(m)) < 0)
927 goto quit;
929 return r;
931 quit:
933 if ((r == -2) && retval)
934 *retval = pa_mainloop_get_retval(m);
935 return r;
938 int pa_mainloop_run(pa_mainloop *m, int *retval) {
939 int r;
941 while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0);
943 if (r == -2)
944 return 1;
945 else if (r < 0)
946 return -1;
947 else
948 return 0;
951 void pa_mainloop_quit(pa_mainloop *m, int retval) {
952 pa_assert(m);
954 m->quit = TRUE;
955 m->retval = retval;
956 pa_mainloop_wakeup(m);
959 pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) {
960 pa_assert(m);
961 return &m->api;
964 void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) {
965 pa_assert(m);
967 m->poll_func = poll_func;
968 m->poll_func_userdata = userdata;