]> code.delx.au - pulseaudio/blob - src/pulse/mainloop.c
60fbbb90697bacc77b3ebfd146e1bcbdf38de6a5
[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 <unistd.h>
29 #include <stdlib.h>
30 #include <fcntl.h>
31 #include <errno.h>
32
33 #ifndef HAVE_PIPE
34 #include <pulsecore/pipe.h>
35 #endif
36
37 #include <pulse/rtclock.h>
38 #include <pulse/timeval.h>
39 #include <pulse/xmalloc.h>
40
41 #include <pulsecore/poll.h>
42 #include <pulsecore/core-rtclock.h>
43 #include <pulsecore/core-util.h>
44 #include <pulsecore/i18n.h>
45 #include <pulsecore/llist.h>
46 #include <pulsecore/log.h>
47 #include <pulsecore/core-error.h>
48 #include <pulsecore/socket.h>
49 #include <pulsecore/macro.h>
50
51 #include "mainloop.h"
52 #include "internal.h"
53
54 struct pa_io_event {
55 pa_mainloop *mainloop;
56 bool dead:1;
57
58 int fd;
59 pa_io_event_flags_t events;
60 struct pollfd *pollfd;
61
62 pa_io_event_cb_t callback;
63 void *userdata;
64 pa_io_event_destroy_cb_t destroy_callback;
65
66 PA_LLIST_FIELDS(pa_io_event);
67 };
68
69 struct pa_time_event {
70 pa_mainloop *mainloop;
71 bool dead:1;
72
73 bool enabled:1;
74 bool use_rtclock:1;
75 pa_usec_t time;
76
77 pa_time_event_cb_t callback;
78 void *userdata;
79 pa_time_event_destroy_cb_t destroy_callback;
80
81 PA_LLIST_FIELDS(pa_time_event);
82 };
83
84 struct pa_defer_event {
85 pa_mainloop *mainloop;
86 bool dead:1;
87
88 bool enabled:1;
89
90 pa_defer_event_cb_t callback;
91 void *userdata;
92 pa_defer_event_destroy_cb_t destroy_callback;
93
94 PA_LLIST_FIELDS(pa_defer_event);
95 };
96
97 struct pa_mainloop {
98 PA_LLIST_HEAD(pa_io_event, io_events);
99 PA_LLIST_HEAD(pa_time_event, time_events);
100 PA_LLIST_HEAD(pa_defer_event, defer_events);
101
102 unsigned n_enabled_defer_events, n_enabled_time_events, n_io_events;
103 unsigned io_events_please_scan, time_events_please_scan, defer_events_please_scan;
104
105 bool rebuild_pollfds:1;
106 struct pollfd *pollfds;
107 unsigned max_pollfds, n_pollfds;
108
109 pa_usec_t prepared_timeout;
110 pa_time_event *cached_next_time_event;
111
112 pa_mainloop_api api;
113
114 int retval;
115 bool quit:1;
116
117 pa_atomic_t wakeup_requested;
118 int wakeup_pipe[2];
119 int wakeup_pipe_type;
120
121 enum {
122 STATE_PASSIVE,
123 STATE_PREPARED,
124 STATE_POLLING,
125 STATE_POLLED,
126 STATE_QUIT
127 } state;
128
129 pa_poll_func poll_func;
130 void *poll_func_userdata;
131 int poll_func_ret;
132 };
133
134 static short map_flags_to_libc(pa_io_event_flags_t flags) {
135 return (short)
136 ((flags & PA_IO_EVENT_INPUT ? POLLIN : 0) |
137 (flags & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) |
138 (flags & PA_IO_EVENT_ERROR ? POLLERR : 0) |
139 (flags & PA_IO_EVENT_HANGUP ? POLLHUP : 0));
140 }
141
142 static pa_io_event_flags_t map_flags_from_libc(short flags) {
143 return
144 (flags & POLLIN ? PA_IO_EVENT_INPUT : 0) |
145 (flags & POLLOUT ? PA_IO_EVENT_OUTPUT : 0) |
146 (flags & POLLERR ? PA_IO_EVENT_ERROR : 0) |
147 (flags & POLLHUP ? PA_IO_EVENT_HANGUP : 0);
148 }
149
150 /* IO events */
151 static pa_io_event* mainloop_io_new(
152 pa_mainloop_api *a,
153 int fd,
154 pa_io_event_flags_t events,
155 pa_io_event_cb_t callback,
156 void *userdata) {
157
158 pa_mainloop *m;
159 pa_io_event *e;
160
161 pa_assert(a);
162 pa_assert(a->userdata);
163 pa_assert(fd >= 0);
164 pa_assert(callback);
165
166 m = a->userdata;
167 pa_assert(a == &m->api);
168
169 e = pa_xnew0(pa_io_event, 1);
170 e->mainloop = m;
171
172 e->fd = fd;
173 e->events = events;
174
175 e->callback = callback;
176 e->userdata = userdata;
177
178 PA_LLIST_PREPEND(pa_io_event, m->io_events, e);
179 m->rebuild_pollfds = true;
180 m->n_io_events ++;
181
182 pa_mainloop_wakeup(m);
183
184 return e;
185 }
186
187 static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) {
188 pa_assert(e);
189 pa_assert(!e->dead);
190
191 if (e->events == events)
192 return;
193
194 e->events = events;
195
196 if (e->pollfd)
197 e->pollfd->events = map_flags_to_libc(events);
198 else
199 e->mainloop->rebuild_pollfds = true;
200
201 pa_mainloop_wakeup(e->mainloop);
202 }
203
204 static void mainloop_io_free(pa_io_event *e) {
205 pa_assert(e);
206 pa_assert(!e->dead);
207
208 e->dead = true;
209 e->mainloop->io_events_please_scan ++;
210
211 e->mainloop->n_io_events --;
212 e->mainloop->rebuild_pollfds = true;
213
214 pa_mainloop_wakeup(e->mainloop);
215 }
216
217 static void mainloop_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t callback) {
218 pa_assert(e);
219
220 e->destroy_callback = callback;
221 }
222
223 /* Defer events */
224 static pa_defer_event* mainloop_defer_new(
225 pa_mainloop_api *a,
226 pa_defer_event_cb_t callback,
227 void *userdata) {
228
229 pa_mainloop *m;
230 pa_defer_event *e;
231
232 pa_assert(a);
233 pa_assert(a->userdata);
234 pa_assert(callback);
235
236 m = a->userdata;
237 pa_assert(a == &m->api);
238
239 e = pa_xnew0(pa_defer_event, 1);
240 e->mainloop = m;
241
242 e->enabled = true;
243 m->n_enabled_defer_events++;
244
245 e->callback = callback;
246 e->userdata = userdata;
247
248 PA_LLIST_PREPEND(pa_defer_event, m->defer_events, e);
249
250 pa_mainloop_wakeup(e->mainloop);
251
252 return e;
253 }
254
255 static void mainloop_defer_enable(pa_defer_event *e, int b) {
256 pa_assert(e);
257 pa_assert(!e->dead);
258
259 if (e->enabled && !b) {
260 pa_assert(e->mainloop->n_enabled_defer_events > 0);
261 e->mainloop->n_enabled_defer_events--;
262 } else if (!e->enabled && b) {
263 e->mainloop->n_enabled_defer_events++;
264 pa_mainloop_wakeup(e->mainloop);
265 }
266
267 e->enabled = b;
268 }
269
270 static void mainloop_defer_free(pa_defer_event *e) {
271 pa_assert(e);
272 pa_assert(!e->dead);
273
274 e->dead = true;
275 e->mainloop->defer_events_please_scan ++;
276
277 if (e->enabled) {
278 pa_assert(e->mainloop->n_enabled_defer_events > 0);
279 e->mainloop->n_enabled_defer_events--;
280 e->enabled = false;
281 }
282 }
283
284 static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t callback) {
285 pa_assert(e);
286 pa_assert(!e->dead);
287
288 e->destroy_callback = callback;
289 }
290
291 /* Time events */
292 static pa_usec_t make_rt(const struct timeval *tv, bool *use_rtclock) {
293 struct timeval ttv;
294
295 if (!tv) {
296 *use_rtclock = false;
297 return PA_USEC_INVALID;
298 }
299
300 ttv = *tv;
301 *use_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK);
302
303 if (*use_rtclock)
304 ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK;
305 else
306 pa_rtclock_from_wallclock(&ttv);
307
308 return pa_timeval_load(&ttv);
309 }
310
311 static pa_time_event* mainloop_time_new(
312 pa_mainloop_api *a,
313 const struct timeval *tv,
314 pa_time_event_cb_t callback,
315 void *userdata) {
316
317 pa_mainloop *m;
318 pa_time_event *e;
319 pa_usec_t t;
320 bool use_rtclock = false;
321
322 pa_assert(a);
323 pa_assert(a->userdata);
324 pa_assert(callback);
325
326 t = make_rt(tv, &use_rtclock);
327
328 m = a->userdata;
329 pa_assert(a == &m->api);
330
331 e = pa_xnew0(pa_time_event, 1);
332 e->mainloop = m;
333
334 if ((e->enabled = (t != PA_USEC_INVALID))) {
335 e->time = t;
336 e->use_rtclock = use_rtclock;
337
338 m->n_enabled_time_events++;
339
340 if (m->cached_next_time_event) {
341 pa_assert(m->cached_next_time_event->enabled);
342
343 if (t < m->cached_next_time_event->time)
344 m->cached_next_time_event = e;
345 }
346 }
347
348 e->callback = callback;
349 e->userdata = userdata;
350
351 PA_LLIST_PREPEND(pa_time_event, m->time_events, e);
352
353 if (e->enabled)
354 pa_mainloop_wakeup(m);
355
356 return e;
357 }
358
359 static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
360 bool valid;
361 pa_usec_t t;
362 bool use_rtclock = false;
363
364 pa_assert(e);
365 pa_assert(!e->dead);
366
367 t = make_rt(tv, &use_rtclock);
368
369 valid = (t != PA_USEC_INVALID);
370 if (e->enabled && !valid) {
371 pa_assert(e->mainloop->n_enabled_time_events > 0);
372 e->mainloop->n_enabled_time_events--;
373 } else if (!e->enabled && valid)
374 e->mainloop->n_enabled_time_events++;
375
376 if ((e->enabled = valid)) {
377 e->time = t;
378 e->use_rtclock = use_rtclock;
379 pa_mainloop_wakeup(e->mainloop);
380 }
381
382 if (e->mainloop->cached_next_time_event && e->enabled) {
383 pa_assert(e->mainloop->cached_next_time_event->enabled);
384
385 if (t < e->mainloop->cached_next_time_event->time)
386 e->mainloop->cached_next_time_event = e;
387 } else if (e->mainloop->cached_next_time_event == e)
388 e->mainloop->cached_next_time_event = NULL;
389 }
390
391 static void mainloop_time_free(pa_time_event *e) {
392 pa_assert(e);
393 pa_assert(!e->dead);
394
395 e->dead = true;
396 e->mainloop->time_events_please_scan ++;
397
398 if (e->enabled) {
399 pa_assert(e->mainloop->n_enabled_time_events > 0);
400 e->mainloop->n_enabled_time_events--;
401 e->enabled = false;
402 }
403
404 if (e->mainloop->cached_next_time_event == e)
405 e->mainloop->cached_next_time_event = NULL;
406
407 /* no wakeup needed here. Think about it! */
408 }
409
410 static void mainloop_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t callback) {
411 pa_assert(e);
412 pa_assert(!e->dead);
413
414 e->destroy_callback = callback;
415 }
416
417 /* quit() */
418
419 static void mainloop_quit(pa_mainloop_api *a, int retval) {
420 pa_mainloop *m;
421
422 pa_assert(a);
423 pa_assert(a->userdata);
424 m = a->userdata;
425 pa_assert(a == &m->api);
426
427 pa_mainloop_quit(m, retval);
428 }
429
430 static const pa_mainloop_api vtable = {
431 .userdata = NULL,
432
433 .io_new = mainloop_io_new,
434 .io_enable = mainloop_io_enable,
435 .io_free = mainloop_io_free,
436 .io_set_destroy = mainloop_io_set_destroy,
437
438 .time_new = mainloop_time_new,
439 .time_restart = mainloop_time_restart,
440 .time_free = mainloop_time_free,
441 .time_set_destroy = mainloop_time_set_destroy,
442
443 .defer_new = mainloop_defer_new,
444 .defer_enable = mainloop_defer_enable,
445 .defer_free = mainloop_defer_free,
446 .defer_set_destroy = mainloop_defer_set_destroy,
447
448 .quit = mainloop_quit,
449 };
450
451 pa_mainloop *pa_mainloop_new(void) {
452 pa_mainloop *m;
453
454 pa_init_i18n();
455
456 m = pa_xnew0(pa_mainloop, 1);
457
458 if (pa_pipe_cloexec(m->wakeup_pipe) < 0) {
459 pa_log_error("ERROR: cannot create wakeup pipe");
460 pa_xfree(m);
461 return NULL;
462 }
463
464 pa_make_fd_nonblock(m->wakeup_pipe[0]);
465 pa_make_fd_nonblock(m->wakeup_pipe[1]);
466
467 m->rebuild_pollfds = true;
468
469 m->api = vtable;
470 m->api.userdata = m;
471
472 m->state = STATE_PASSIVE;
473
474 m->poll_func_ret = -1;
475
476 return m;
477 }
478
479 static void cleanup_io_events(pa_mainloop *m, bool force) {
480 pa_io_event *e, *n;
481
482 PA_LLIST_FOREACH_SAFE(e, n, m->io_events) {
483
484 if (!force && m->io_events_please_scan <= 0)
485 break;
486
487 if (force || e->dead) {
488 PA_LLIST_REMOVE(pa_io_event, m->io_events, e);
489
490 if (e->dead) {
491 pa_assert(m->io_events_please_scan > 0);
492 m->io_events_please_scan--;
493 }
494
495 if (e->destroy_callback)
496 e->destroy_callback(&m->api, e, e->userdata);
497
498 pa_xfree(e);
499
500 m->rebuild_pollfds = true;
501 }
502 }
503
504 pa_assert(m->io_events_please_scan == 0);
505 }
506
507 static void cleanup_time_events(pa_mainloop *m, bool force) {
508 pa_time_event *e, *n;
509
510 PA_LLIST_FOREACH_SAFE(e, n, m->time_events) {
511
512 if (!force && m->time_events_please_scan <= 0)
513 break;
514
515 if (force || e->dead) {
516 PA_LLIST_REMOVE(pa_time_event, m->time_events, e);
517
518 if (e->dead) {
519 pa_assert(m->time_events_please_scan > 0);
520 m->time_events_please_scan--;
521 }
522
523 if (!e->dead && e->enabled) {
524 pa_assert(m->n_enabled_time_events > 0);
525 m->n_enabled_time_events--;
526 e->enabled = false;
527 }
528
529 if (e->destroy_callback)
530 e->destroy_callback(&m->api, e, e->userdata);
531
532 pa_xfree(e);
533 }
534 }
535
536 pa_assert(m->time_events_please_scan == 0);
537 }
538
539 static void cleanup_defer_events(pa_mainloop *m, bool force) {
540 pa_defer_event *e, *n;
541
542 PA_LLIST_FOREACH_SAFE(e, n, m->defer_events) {
543
544 if (!force && m->defer_events_please_scan <= 0)
545 break;
546
547 if (force || e->dead) {
548 PA_LLIST_REMOVE(pa_defer_event, m->defer_events, e);
549
550 if (e->dead) {
551 pa_assert(m->defer_events_please_scan > 0);
552 m->defer_events_please_scan--;
553 }
554
555 if (!e->dead && e->enabled) {
556 pa_assert(m->n_enabled_defer_events > 0);
557 m->n_enabled_defer_events--;
558 e->enabled = false;
559 }
560
561 if (e->destroy_callback)
562 e->destroy_callback(&m->api, e, e->userdata);
563
564 pa_xfree(e);
565 }
566 }
567
568 pa_assert(m->defer_events_please_scan == 0);
569 }
570
571 void pa_mainloop_free(pa_mainloop *m) {
572 pa_assert(m);
573
574 cleanup_io_events(m, true);
575 cleanup_defer_events(m, true);
576 cleanup_time_events(m, true);
577
578 pa_xfree(m->pollfds);
579
580 pa_close_pipe(m->wakeup_pipe);
581
582 pa_xfree(m);
583 }
584
585 static void scan_dead(pa_mainloop *m) {
586 pa_assert(m);
587
588 if (m->io_events_please_scan)
589 cleanup_io_events(m, false);
590
591 if (m->time_events_please_scan)
592 cleanup_time_events(m, false);
593
594 if (m->defer_events_please_scan)
595 cleanup_defer_events(m, false);
596 }
597
598 static void rebuild_pollfds(pa_mainloop *m) {
599 pa_io_event*e;
600 struct pollfd *p;
601 unsigned l;
602
603 l = m->n_io_events + 1;
604 if (m->max_pollfds < l) {
605 l *= 2;
606 m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l);
607 m->max_pollfds = l;
608 }
609
610 m->n_pollfds = 0;
611 p = m->pollfds;
612
613 m->pollfds[0].fd = m->wakeup_pipe[0];
614 m->pollfds[0].events = POLLIN;
615 m->pollfds[0].revents = 0;
616 p++;
617 m->n_pollfds++;
618
619 PA_LLIST_FOREACH(e, m->io_events) {
620 if (e->dead) {
621 e->pollfd = NULL;
622 continue;
623 }
624
625 e->pollfd = p;
626 p->fd = e->fd;
627 p->events = map_flags_to_libc(e->events);
628 p->revents = 0;
629
630 p++;
631 m->n_pollfds++;
632 }
633
634 m->rebuild_pollfds = false;
635 }
636
637 static unsigned dispatch_pollfds(pa_mainloop *m) {
638 pa_io_event *e;
639 unsigned r = 0, k;
640
641 pa_assert(m->poll_func_ret > 0);
642
643 k = m->poll_func_ret;
644
645 PA_LLIST_FOREACH(e, m->io_events) {
646
647 if (k <= 0 || m->quit)
648 break;
649
650 if (e->dead || !e->pollfd || !e->pollfd->revents)
651 continue;
652
653 pa_assert(e->pollfd->fd == e->fd);
654 pa_assert(e->callback);
655
656 e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata);
657 e->pollfd->revents = 0;
658 r++;
659 k--;
660 }
661
662 return r;
663 }
664
665 static unsigned dispatch_defer(pa_mainloop *m) {
666 pa_defer_event *e;
667 unsigned r = 0;
668
669 if (m->n_enabled_defer_events <= 0)
670 return 0;
671
672 PA_LLIST_FOREACH(e, m->defer_events) {
673
674 if (m->quit)
675 break;
676
677 if (e->dead || !e->enabled)
678 continue;
679
680 pa_assert(e->callback);
681 e->callback(&m->api, e, e->userdata);
682 r++;
683 }
684
685 return r;
686 }
687
688 static pa_time_event* find_next_time_event(pa_mainloop *m) {
689 pa_time_event *t, *n = NULL;
690 pa_assert(m);
691
692 if (m->cached_next_time_event)
693 return m->cached_next_time_event;
694
695 PA_LLIST_FOREACH(t, m->time_events) {
696
697 if (t->dead || !t->enabled)
698 continue;
699
700 if (!n || t->time < n->time) {
701 n = t;
702
703 /* Shortcut for time == 0 */
704 if (n->time == 0)
705 break;
706 }
707 }
708
709 m->cached_next_time_event = n;
710 return n;
711 }
712
713 static pa_usec_t calc_next_timeout(pa_mainloop *m) {
714 pa_time_event *t;
715 pa_usec_t clock_now;
716
717 if (m->n_enabled_time_events <= 0)
718 return PA_USEC_INVALID;
719
720 pa_assert_se(t = find_next_time_event(m));
721
722 if (t->time <= 0)
723 return 0;
724
725 clock_now = pa_rtclock_now();
726
727 if (t->time <= clock_now)
728 return 0;
729
730 return t->time - clock_now;
731 }
732
733 static unsigned dispatch_timeout(pa_mainloop *m) {
734 pa_time_event *e;
735 pa_usec_t now;
736 unsigned r = 0;
737 pa_assert(m);
738
739 if (m->n_enabled_time_events <= 0)
740 return 0;
741
742 now = pa_rtclock_now();
743
744 PA_LLIST_FOREACH(e, m->time_events) {
745
746 if (m->quit)
747 break;
748
749 if (e->dead || !e->enabled)
750 continue;
751
752 if (e->time <= now) {
753 struct timeval tv;
754 pa_assert(e->callback);
755
756 /* Disable time event */
757 mainloop_time_restart(e, NULL);
758
759 e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, e->use_rtclock), e->userdata);
760
761 r++;
762 }
763 }
764
765 return r;
766 }
767
768 void pa_mainloop_wakeup(pa_mainloop *m) {
769 char c = 'W';
770 pa_assert(m);
771
772 if (pa_write(m->wakeup_pipe[1], &c, sizeof(c), &m->wakeup_pipe_type) < 0)
773 /* Not much options for recovering from the error. Let's at least log something. */
774 pa_log("pa_write() failed while trying to wake up the mainloop: %s", pa_cstrerror(errno));
775
776 pa_atomic_store(&m->wakeup_requested, true);
777 }
778
779 static void clear_wakeup(pa_mainloop *m) {
780 char c[10];
781
782 pa_assert(m);
783
784 if (pa_atomic_cmpxchg(&m->wakeup_requested, true, false)) {
785 while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c))
786 ;
787 }
788 }
789
790 int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
791 pa_assert(m);
792 pa_assert(m->state == STATE_PASSIVE);
793
794 clear_wakeup(m);
795 scan_dead(m);
796
797 if (m->quit)
798 goto quit;
799
800 if (m->n_enabled_defer_events <= 0) {
801
802 if (m->rebuild_pollfds)
803 rebuild_pollfds(m);
804
805 m->prepared_timeout = calc_next_timeout(m);
806 if (timeout >= 0) {
807 uint64_t u = (uint64_t) timeout * PA_USEC_PER_MSEC;
808
809 if (u < m->prepared_timeout || m->prepared_timeout == PA_USEC_INVALID)
810 m->prepared_timeout = timeout;
811 }
812 }
813
814 m->state = STATE_PREPARED;
815 return 0;
816
817 quit:
818 m->state = STATE_QUIT;
819 return -2;
820 }
821
822 static int usec_to_timeout(pa_usec_t u) {
823 int timeout;
824
825 if (u == PA_USEC_INVALID)
826 return -1;
827
828 timeout = (u + PA_USEC_PER_MSEC - 1) / PA_USEC_PER_MSEC;
829 pa_assert(timeout >= 0);
830
831 return timeout;
832 }
833
834 int pa_mainloop_poll(pa_mainloop *m) {
835 pa_assert(m);
836 pa_assert(m->state == STATE_PREPARED);
837
838 if (m->quit)
839 goto quit;
840
841 m->state = STATE_POLLING;
842
843 if (m->n_enabled_defer_events )
844 m->poll_func_ret = 0;
845 else {
846 pa_assert(!m->rebuild_pollfds);
847
848 if (m->poll_func)
849 m->poll_func_ret = m->poll_func(
850 m->pollfds, m->n_pollfds,
851 usec_to_timeout(m->prepared_timeout),
852 m->poll_func_userdata);
853 else {
854 #ifdef HAVE_PPOLL
855 struct timespec ts;
856
857 m->poll_func_ret = ppoll(
858 m->pollfds, m->n_pollfds,
859 m->prepared_timeout == PA_USEC_INVALID ? NULL : pa_timespec_store(&ts, m->prepared_timeout),
860 NULL);
861 #else
862 m->poll_func_ret = pa_poll(
863 m->pollfds, m->n_pollfds,
864 usec_to_timeout(m->prepared_timeout));
865 #endif
866 }
867
868 if (m->poll_func_ret < 0) {
869 if (errno == EINTR)
870 m->poll_func_ret = 0;
871 else
872 pa_log("poll(): %s", pa_cstrerror(errno));
873 }
874 }
875
876 m->state = m->poll_func_ret < 0 ? STATE_PASSIVE : STATE_POLLED;
877 return m->poll_func_ret;
878
879 quit:
880 m->state = STATE_QUIT;
881 return -2;
882 }
883
884 int pa_mainloop_dispatch(pa_mainloop *m) {
885 unsigned dispatched = 0;
886
887 pa_assert(m);
888 pa_assert(m->state == STATE_POLLED);
889
890 if (m->quit)
891 goto quit;
892
893 if (m->n_enabled_defer_events)
894 dispatched += dispatch_defer(m);
895 else {
896 if (m->n_enabled_time_events)
897 dispatched += dispatch_timeout(m);
898
899 if (m->quit)
900 goto quit;
901
902 if (m->poll_func_ret > 0)
903 dispatched += dispatch_pollfds(m);
904 }
905
906 if (m->quit)
907 goto quit;
908
909 m->state = STATE_PASSIVE;
910
911 return (int) dispatched;
912
913 quit:
914 m->state = STATE_QUIT;
915 return -2;
916 }
917
918 int pa_mainloop_get_retval(pa_mainloop *m) {
919 pa_assert(m);
920
921 return m->retval;
922 }
923
924 int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) {
925 int r;
926 pa_assert(m);
927
928 if ((r = pa_mainloop_prepare(m, block ? -1 : 0)) < 0)
929 goto quit;
930
931 if ((r = pa_mainloop_poll(m)) < 0)
932 goto quit;
933
934 if ((r = pa_mainloop_dispatch(m)) < 0)
935 goto quit;
936
937 return r;
938
939 quit:
940
941 if ((r == -2) && retval)
942 *retval = pa_mainloop_get_retval(m);
943 return r;
944 }
945
946 int pa_mainloop_run(pa_mainloop *m, int *retval) {
947 int r;
948
949 while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0)
950 ;
951
952 if (r == -2)
953 return 1;
954 else if (r < 0)
955 return -1;
956 else
957 return 0;
958 }
959
960 void pa_mainloop_quit(pa_mainloop *m, int retval) {
961 pa_assert(m);
962
963 m->quit = true;
964 m->retval = retval;
965 pa_mainloop_wakeup(m);
966 }
967
968 pa_mainloop_api* pa_mainloop_get_api(pa_mainloop *m) {
969 pa_assert(m);
970
971 return &m->api;
972 }
973
974 void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) {
975 pa_assert(m);
976
977 m->poll_func = poll_func;
978 m->poll_func_userdata = userdata;
979 }
980
981 bool pa_mainloop_is_our_api(pa_mainloop_api *m) {
982 pa_assert(m);
983
984 return m->io_new == mainloop_io_new;
985 }