]> code.delx.au - pulseaudio/blob - src/pulse/mainloop.c
Merge commit 'origin/master-tx'
[pulseaudio] / src / pulse / mainloop.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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.
11
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.
16
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 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
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>
34
35 #ifdef HAVE_POLL_H
36 #include <poll.h>
37 #else
38 #include <pulsecore/poll.h>
39 #endif
40
41 #ifndef HAVE_PIPE
42 #include <pulsecore/pipe.h>
43 #endif
44
45 #include <pulse/timeval.h>
46 #include <pulse/xmalloc.h>
47 #include <pulse/i18n.h>
48
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>
55
56 #include "mainloop.h"
57
58 struct pa_io_event {
59 pa_mainloop *mainloop;
60 pa_bool_t dead:1;
61
62 int fd;
63 pa_io_event_flags_t events;
64 struct pollfd *pollfd;
65
66 pa_io_event_cb_t callback;
67 void *userdata;
68 pa_io_event_destroy_cb_t destroy_callback;
69
70 PA_LLIST_FIELDS(pa_io_event);
71 };
72
73 struct pa_time_event {
74 pa_mainloop *mainloop;
75 pa_bool_t dead:1;
76
77 pa_bool_t enabled:1;
78 struct timeval timeval;
79
80 pa_time_event_cb_t callback;
81 void *userdata;
82 pa_time_event_destroy_cb_t destroy_callback;
83
84 PA_LLIST_FIELDS(pa_time_event);
85 };
86
87 struct pa_defer_event {
88 pa_mainloop *mainloop;
89 pa_bool_t dead:1;
90
91 pa_bool_t enabled:1;
92
93 pa_defer_event_cb_t callback;
94 void *userdata;
95 pa_defer_event_destroy_cb_t destroy_callback;
96
97 PA_LLIST_FIELDS(pa_defer_event);
98 };
99
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);
104
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;
107
108 pa_bool_t rebuild_pollfds:1;
109 struct pollfd *pollfds;
110 unsigned max_pollfds, n_pollfds;
111
112 int prepared_timeout;
113 pa_time_event *cached_next_time_event;
114
115 pa_mainloop_api api;
116
117 int retval;
118 pa_bool_t quit:1;
119
120 pa_bool_t wakeup_requested:1;
121 int wakeup_pipe[2];
122 int wakeup_pipe_type;
123
124 enum {
125 STATE_PASSIVE,
126 STATE_PREPARED,
127 STATE_POLLING,
128 STATE_POLLED,
129 STATE_QUIT
130 } state;
131
132 pa_poll_func poll_func;
133 void *poll_func_userdata;
134 int poll_func_ret;
135 };
136
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));
143 }
144
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);
151 }
152
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) {
160
161 pa_mainloop *m;
162 pa_io_event *e;
163
164 pa_assert(a);
165 pa_assert(a->userdata);
166 pa_assert(fd >= 0);
167 pa_assert(callback);
168
169 m = a->userdata;
170 pa_assert(a == &m->api);
171
172 e = pa_xnew(pa_io_event, 1);
173 e->mainloop = m;
174 e->dead = FALSE;
175
176 e->fd = fd;
177 e->events = events;
178 e->pollfd = NULL;
179
180 e->callback = callback;
181 e->userdata = userdata;
182 e->destroy_callback = NULL;
183
184 #ifdef OS_IS_WIN32
185 {
186 fd_set xset;
187 struct timeval tv;
188
189 tv.tv_sec = 0;
190 tv.tv_usec = 0;
191
192 FD_ZERO (&xset);
193 FD_SET (fd, &xset);
194
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;
200 }
201 }
202 #endif
203
204 PA_LLIST_PREPEND(pa_io_event, m->io_events, e);
205 m->rebuild_pollfds = TRUE;
206 m->n_io_events ++;
207
208 pa_mainloop_wakeup(m);
209
210 return e;
211 }
212
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);
216
217 if (e->events == events)
218 return;
219
220 e->events = events;
221
222 if (e->pollfd)
223 e->pollfd->events = map_flags_to_libc(events);
224 else
225 e->mainloop->rebuild_pollfds = TRUE;
226
227 pa_mainloop_wakeup(e->mainloop);
228 }
229
230 static void mainloop_io_free(pa_io_event *e) {
231 pa_assert(e);
232 pa_assert(!e->dead);
233
234 e->dead = TRUE;
235 e->mainloop->io_events_please_scan ++;
236
237 e->mainloop->n_io_events --;
238 e->mainloop->rebuild_pollfds = TRUE;
239
240 pa_mainloop_wakeup(e->mainloop);
241 }
242
243 static void mainloop_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t callback) {
244 pa_assert(e);
245
246 e->destroy_callback = callback;
247 }
248
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) {
254
255 pa_mainloop *m;
256 pa_defer_event *e;
257
258 pa_assert(a);
259 pa_assert(a->userdata);
260 pa_assert(callback);
261
262 m = a->userdata;
263 pa_assert(a == &m->api);
264
265 e = pa_xnew(pa_defer_event, 1);
266 e->mainloop = m;
267 e->dead = FALSE;
268
269 e->enabled = TRUE;
270 m->n_enabled_defer_events++;
271
272 e->callback = callback;
273 e->userdata = userdata;
274 e->destroy_callback = NULL;
275
276 PA_LLIST_PREPEND(pa_defer_event, m->defer_events, e);
277
278 pa_mainloop_wakeup(e->mainloop);
279
280 return e;
281 }
282
283 static void mainloop_defer_enable(pa_defer_event *e, int b) {
284 pa_assert(e);
285 pa_assert(!e->dead);
286
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);
293 }
294
295 e->enabled = b;
296 }
297
298 static void mainloop_defer_free(pa_defer_event *e) {
299 pa_assert(e);
300 pa_assert(!e->dead);
301
302 e->dead = TRUE;
303 e->mainloop->defer_events_please_scan ++;
304
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;
309 }
310 }
311
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);
315
316 e->destroy_callback = callback;
317 }
318
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) {
325
326 pa_mainloop *m;
327 pa_time_event *e;
328
329 pa_assert(a);
330 pa_assert(a->userdata);
331 pa_assert(callback);
332
333 m = a->userdata;
334 pa_assert(a == &m->api);
335
336 e = pa_xnew(pa_time_event, 1);
337 e->mainloop = m;
338 e->dead = FALSE;
339
340 if ((e->enabled = !!tv)) {
341 e->timeval = *tv;
342
343 m->n_enabled_time_events++;
344
345 if (m->cached_next_time_event) {
346 pa_assert(m->cached_next_time_event->enabled);
347
348 if (pa_timeval_cmp(tv, &m->cached_next_time_event->timeval) < 0)
349 m->cached_next_time_event = e;
350 }
351 }
352
353 e->callback = callback;
354 e->userdata = userdata;
355 e->destroy_callback = NULL;
356
357 PA_LLIST_PREPEND(pa_time_event, m->time_events, e);
358
359 if (e->enabled)
360 pa_mainloop_wakeup(m);
361
362 return e;
363 }
364
365 static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
366 pa_assert(e);
367 pa_assert(!e->dead);
368
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++;
374
375 if ((e->enabled = !!tv)) {
376 e->timeval = *tv;
377 pa_mainloop_wakeup(e->mainloop);
378 }
379
380 if (e->mainloop->cached_next_time_event && e->enabled) {
381 pa_assert(e->mainloop->cached_next_time_event->enabled);
382
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;
387 }
388
389 static void mainloop_time_free(pa_time_event *e) {
390 pa_assert(e);
391 pa_assert(!e->dead);
392
393 e->dead = TRUE;
394 e->mainloop->time_events_please_scan ++;
395
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;
400 }
401
402 if (e->mainloop->cached_next_time_event == e)
403 e->mainloop->cached_next_time_event = NULL;
404
405 /* no wakeup needed here. Think about it! */
406 }
407
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);
411
412 e->destroy_callback = callback;
413 }
414
415 /* quit() */
416
417 static void mainloop_quit(pa_mainloop_api*a, int retval) {
418 pa_mainloop *m;
419
420 pa_assert(a);
421 pa_assert(a->userdata);
422 m = a->userdata;
423 pa_assert(a == &m->api);
424
425 pa_mainloop_quit(m, retval);
426 }
427
428 static const pa_mainloop_api vtable = {
429 .userdata = NULL,
430
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,
435
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,
440
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,
445
446 .quit = mainloop_quit,
447 };
448
449 pa_mainloop *pa_mainloop_new(void) {
450 pa_mainloop *m;
451
452 pa_init_i18n();
453
454 m = pa_xnew(pa_mainloop, 1);
455
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;
461 }
462
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;
468
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);
472
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;
475
476 m->cached_next_time_event = NULL;
477 m->prepared_timeout = 0;
478
479 m->pollfds = NULL;
480 m->max_pollfds = m->n_pollfds = 0;
481 m->rebuild_pollfds = TRUE;
482
483 m->quit = FALSE;
484 m->retval = 0;
485
486 m->api = vtable;
487 m->api.userdata = m;
488
489 m->state = STATE_PASSIVE;
490
491 m->poll_func = NULL;
492 m->poll_func_userdata = NULL;
493 m->poll_func_ret = -1;
494
495 return m;
496 }
497
498 static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) {
499 pa_io_event *e;
500
501 e = m->io_events;
502 while (e) {
503 pa_io_event *n = e->next;
504
505 if (!force && m->io_events_please_scan <= 0)
506 break;
507
508 if (force || e->dead) {
509 PA_LLIST_REMOVE(pa_io_event, m->io_events, e);
510
511 if (e->dead) {
512 pa_assert(m->io_events_please_scan > 0);
513 m->io_events_please_scan--;
514 }
515
516 if (e->destroy_callback)
517 e->destroy_callback(&m->api, e, e->userdata);
518
519 pa_xfree(e);
520
521 m->rebuild_pollfds = TRUE;
522 }
523
524 e = n;
525 }
526
527 pa_assert(m->io_events_please_scan == 0);
528 }
529
530 static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) {
531 pa_time_event *e;
532
533 e = m->time_events;
534 while (e) {
535 pa_time_event *n = e->next;
536
537 if (!force && m->time_events_please_scan <= 0)
538 break;
539
540 if (force || e->dead) {
541 PA_LLIST_REMOVE(pa_time_event, m->time_events, e);
542
543 if (e->dead) {
544 pa_assert(m->time_events_please_scan > 0);
545 m->time_events_please_scan--;
546 }
547
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;
552 }
553
554 if (e->destroy_callback)
555 e->destroy_callback(&m->api, e, e->userdata);
556
557 pa_xfree(e);
558 }
559
560 e = n;
561 }
562
563 pa_assert(m->time_events_please_scan == 0);
564 }
565
566 static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) {
567 pa_defer_event *e;
568
569 e = m->defer_events;
570 while (e) {
571 pa_defer_event *n = e->next;
572
573 if (!force && m->defer_events_please_scan <= 0)
574 break;
575
576 if (force || e->dead) {
577 PA_LLIST_REMOVE(pa_defer_event, m->defer_events, e);
578
579 if (e->dead) {
580 pa_assert(m->defer_events_please_scan > 0);
581 m->defer_events_please_scan--;
582 }
583
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;
588 }
589
590 if (e->destroy_callback)
591 e->destroy_callback(&m->api, e, e->userdata);
592
593 pa_xfree(e);
594 }
595
596 e = n;
597 }
598
599 pa_assert(m->defer_events_please_scan == 0);
600 }
601
602
603 void pa_mainloop_free(pa_mainloop* m) {
604 pa_assert(m);
605
606 cleanup_io_events(m, TRUE);
607 cleanup_defer_events(m, TRUE);
608 cleanup_time_events(m, TRUE);
609
610 pa_xfree(m->pollfds);
611
612 pa_close_pipe(m->wakeup_pipe);
613
614 pa_xfree(m);
615 }
616
617 static void scan_dead(pa_mainloop *m) {
618 pa_assert(m);
619
620 if (m->io_events_please_scan)
621 cleanup_io_events(m, FALSE);
622
623 if (m->time_events_please_scan)
624 cleanup_time_events(m, FALSE);
625
626 if (m->defer_events_please_scan)
627 cleanup_defer_events(m, FALSE);
628 }
629
630 static void rebuild_pollfds(pa_mainloop *m) {
631 pa_io_event*e;
632 struct pollfd *p;
633 unsigned l;
634
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;
640 }
641
642 m->n_pollfds = 0;
643 p = m->pollfds;
644
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++;
651 }
652
653 for (e = m->io_events; e; e = e->next) {
654 if (e->dead) {
655 e->pollfd = NULL;
656 continue;
657 }
658
659 e->pollfd = p;
660 p->fd = e->fd;
661 p->events = map_flags_to_libc(e->events);
662 p->revents = 0;
663
664 p++;
665 m->n_pollfds++;
666 }
667
668 m->rebuild_pollfds = FALSE;
669 }
670
671 static int dispatch_pollfds(pa_mainloop *m) {
672 pa_io_event *e;
673 int r = 0, k;
674
675 pa_assert(m->poll_func_ret > 0);
676
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;
680
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++;
686
687 k--;
688 }
689
690 return r;
691 }
692
693 static int dispatch_defer(pa_mainloop *m) {
694 pa_defer_event *e;
695 int r = 0;
696
697 if (m->n_enabled_defer_events <= 0)
698 return 0;
699
700 for (e = m->defer_events; e && !m->quit; e = e->next) {
701 if (e->dead || !e->enabled)
702 continue;
703
704 pa_assert(e->callback);
705 e->callback(&m->api, e, e->userdata);
706 r++;
707 }
708
709 return r;
710 }
711
712 static pa_time_event* find_next_time_event(pa_mainloop *m) {
713 pa_time_event *t, *n = NULL;
714 pa_assert(m);
715
716 if (m->cached_next_time_event)
717 return m->cached_next_time_event;
718
719 for (t = m->time_events; t; t = t->next) {
720
721 if (t->dead || !t->enabled)
722 continue;
723
724 if (!n || pa_timeval_cmp(&t->timeval, &n->timeval) < 0) {
725 n = t;
726
727 /* Shortcut for tv = { 0, 0 } */
728 if (n->timeval.tv_sec <= 0)
729 break;
730 }
731 }
732
733 m->cached_next_time_event = n;
734 return n;
735 }
736
737 static int calc_next_timeout(pa_mainloop *m) {
738 pa_time_event *t;
739 struct timeval now;
740 pa_usec_t usec;
741
742 if (!m->n_enabled_time_events)
743 return -1;
744
745 t = find_next_time_event(m);
746 pa_assert(t);
747
748 if (t->timeval.tv_sec <= 0)
749 return 0;
750
751 pa_gettimeofday(&now);
752
753 if (pa_timeval_cmp(&t->timeval, &now) <= 0)
754 return 0;
755
756 usec = pa_timeval_diff(&t->timeval, &now);
757 return (int) (usec / 1000);
758 }
759
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);
765
766 if (m->n_enabled_time_events <= 0)
767 return 0;
768
769 pa_gettimeofday(&now);
770
771 for (e = m->time_events; e && !m->quit; e = e->next) {
772
773 if (e->dead || !e->enabled)
774 continue;
775
776 if (pa_timeval_cmp(&e->timeval, &now) <= 0) {
777 pa_assert(e->callback);
778
779 /* Disable time event */
780 mainloop_time_restart(e, NULL);
781
782 e->callback(&m->api, e, &e->timeval, e->userdata);
783
784 r++;
785 }
786 }
787
788 return r;
789 }
790
791 void pa_mainloop_wakeup(pa_mainloop *m) {
792 char c = 'W';
793 pa_assert(m);
794
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++;
798 }
799 }
800
801 static void clear_wakeup(pa_mainloop *m) {
802 char c[10];
803
804 pa_assert(m);
805
806 if (m->wakeup_pipe[0] < 0)
807 return;
808
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;
812 }
813 }
814
815 int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
816 pa_assert(m);
817 pa_assert(m->state == STATE_PASSIVE);
818
819 clear_wakeup(m);
820 scan_dead(m);
821
822 if (m->quit)
823 goto quit;
824
825 if (m->n_enabled_defer_events <= 0) {
826 if (m->rebuild_pollfds)
827 rebuild_pollfds(m);
828
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;
832 }
833
834 m->state = STATE_PREPARED;
835 return 0;
836
837 quit:
838 m->state = STATE_QUIT;
839 return -2;
840 }
841
842 int pa_mainloop_poll(pa_mainloop *m) {
843 pa_assert(m);
844 pa_assert(m->state == STATE_PREPARED);
845
846 if (m->quit)
847 goto quit;
848
849 m->state = STATE_POLLING;
850
851 if (m->n_enabled_defer_events )
852 m->poll_func_ret = 0;
853 else {
854 pa_assert(!m->rebuild_pollfds);
855
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);
860
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));
866 }
867 }
868
869 m->state = m->poll_func_ret < 0 ? STATE_PASSIVE : STATE_POLLED;
870 return m->poll_func_ret;
871
872 quit:
873 m->state = STATE_QUIT;
874 return -2;
875 }
876
877 int pa_mainloop_dispatch(pa_mainloop *m) {
878 int dispatched = 0;
879
880 pa_assert(m);
881 pa_assert(m->state == STATE_POLLED);
882
883 if (m->quit)
884 goto quit;
885
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);
891
892 if (m->quit)
893 goto quit;
894
895 if (m->poll_func_ret > 0)
896 dispatched += dispatch_pollfds(m);
897 }
898
899 if (m->quit)
900 goto quit;
901
902 m->state = STATE_PASSIVE;
903
904 return dispatched;
905
906 quit:
907 m->state = STATE_QUIT;
908 return -2;
909 }
910
911 int pa_mainloop_get_retval(pa_mainloop *m) {
912 pa_assert(m);
913 return m->retval;
914 }
915
916 int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) {
917 int r;
918 pa_assert(m);
919
920 if ((r = pa_mainloop_prepare(m, block ? -1 : 0)) < 0)
921 goto quit;
922
923 if ((r = pa_mainloop_poll(m)) < 0)
924 goto quit;
925
926 if ((r = pa_mainloop_dispatch(m)) < 0)
927 goto quit;
928
929 return r;
930
931 quit:
932
933 if ((r == -2) && retval)
934 *retval = pa_mainloop_get_retval(m);
935 return r;
936 }
937
938 int pa_mainloop_run(pa_mainloop *m, int *retval) {
939 int r;
940
941 while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0);
942
943 if (r == -2)
944 return 1;
945 else if (r < 0)
946 return -1;
947 else
948 return 0;
949 }
950
951 void pa_mainloop_quit(pa_mainloop *m, int retval) {
952 pa_assert(m);
953
954 m->quit = TRUE;
955 m->retval = retval;
956 pa_mainloop_wakeup(m);
957 }
958
959 pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) {
960 pa_assert(m);
961 return &m->api;
962 }
963
964 void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) {
965 pa_assert(m);
966
967 m->poll_func = poll_func;
968 m->poll_func_userdata = userdata;
969 }