]> code.delx.au - pulseaudio/blob - src/pulse/mainloop.c
a3d7715d578ba5b54cd8caa6a0083fb3c1a27801
[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 pa_bool_t 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 pa_bool_t dead:1;
72
73 pa_bool_t enabled:1;
74 pa_bool_t 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 pa_bool_t dead:1;
87
88 pa_bool_t 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 pa_bool_t 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 pa_bool_t 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, pa_bool_t *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 pa_bool_t 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 pa_bool_t valid;
361 pa_usec_t t;
362 pa_bool_t 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, pa_bool_t 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, pa_bool_t 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, pa_bool_t 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
572 void pa_mainloop_free(pa_mainloop *m) {
573 pa_assert(m);
574
575 cleanup_io_events(m, TRUE);
576 cleanup_defer_events(m, TRUE);
577 cleanup_time_events(m, TRUE);
578
579 pa_xfree(m->pollfds);
580
581 pa_close_pipe(m->wakeup_pipe);
582
583 pa_xfree(m);
584 }
585
586 static void scan_dead(pa_mainloop *m) {
587 pa_assert(m);
588
589 if (m->io_events_please_scan)
590 cleanup_io_events(m, FALSE);
591
592 if (m->time_events_please_scan)
593 cleanup_time_events(m, FALSE);
594
595 if (m->defer_events_please_scan)
596 cleanup_defer_events(m, FALSE);
597 }
598
599 static void rebuild_pollfds(pa_mainloop *m) {
600 pa_io_event*e;
601 struct pollfd *p;
602 unsigned l;
603
604 l = m->n_io_events + 1;
605 if (m->max_pollfds < l) {
606 l *= 2;
607 m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l);
608 m->max_pollfds = l;
609 }
610
611 m->n_pollfds = 0;
612 p = m->pollfds;
613
614 m->pollfds[0].fd = m->wakeup_pipe[0];
615 m->pollfds[0].events = POLLIN;
616 m->pollfds[0].revents = 0;
617 p++;
618 m->n_pollfds++;
619
620 PA_LLIST_FOREACH(e, m->io_events) {
621 if (e->dead) {
622 e->pollfd = NULL;
623 continue;
624 }
625
626 e->pollfd = p;
627 p->fd = e->fd;
628 p->events = map_flags_to_libc(e->events);
629 p->revents = 0;
630
631 p++;
632 m->n_pollfds++;
633 }
634
635 m->rebuild_pollfds = FALSE;
636 }
637
638 static unsigned dispatch_pollfds(pa_mainloop *m) {
639 pa_io_event *e;
640 unsigned r = 0, k;
641
642 pa_assert(m->poll_func_ret > 0);
643
644 k = m->poll_func_ret;
645
646 PA_LLIST_FOREACH(e, m->io_events) {
647
648 if (k <= 0 || m->quit)
649 break;
650
651 if (e->dead || !e->pollfd || !e->pollfd->revents)
652 continue;
653
654 pa_assert(e->pollfd->fd == e->fd);
655 pa_assert(e->callback);
656
657 e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata);
658 e->pollfd->revents = 0;
659 r++;
660 k--;
661 }
662
663 return r;
664 }
665
666 static unsigned dispatch_defer(pa_mainloop *m) {
667 pa_defer_event *e;
668 unsigned r = 0;
669
670 if (m->n_enabled_defer_events <= 0)
671 return 0;
672
673 PA_LLIST_FOREACH(e, m->defer_events) {
674
675 if (m->quit)
676 break;
677
678 if (e->dead || !e->enabled)
679 continue;
680
681 pa_assert(e->callback);
682 e->callback(&m->api, e, e->userdata);
683 r++;
684 }
685
686 return r;
687 }
688
689 static pa_time_event* find_next_time_event(pa_mainloop *m) {
690 pa_time_event *t, *n = NULL;
691 pa_assert(m);
692
693 if (m->cached_next_time_event)
694 return m->cached_next_time_event;
695
696 PA_LLIST_FOREACH(t, m->time_events) {
697
698 if (t->dead || !t->enabled)
699 continue;
700
701 if (!n || t->time < n->time) {
702 n = t;
703
704 /* Shortcut for time == 0 */
705 if (n->time == 0)
706 break;
707 }
708 }
709
710 m->cached_next_time_event = n;
711 return n;
712 }
713
714 static pa_usec_t calc_next_timeout(pa_mainloop *m) {
715 pa_time_event *t;
716 pa_usec_t clock_now;
717
718 if (m->n_enabled_time_events <= 0)
719 return PA_USEC_INVALID;
720
721 pa_assert_se(t = find_next_time_event(m));
722
723 if (t->time <= 0)
724 return 0;
725
726 clock_now = pa_rtclock_now();
727
728 if (t->time <= clock_now)
729 return 0;
730
731 return t->time - clock_now;
732 }
733
734 static unsigned dispatch_timeout(pa_mainloop *m) {
735 pa_time_event *e;
736 pa_usec_t now;
737 unsigned r = 0;
738 pa_assert(m);
739
740 if (m->n_enabled_time_events <= 0)
741 return 0;
742
743 now = pa_rtclock_now();
744
745 PA_LLIST_FOREACH(e, m->time_events) {
746
747 if (m->quit)
748 break;
749
750 if (e->dead || !e->enabled)
751 continue;
752
753 if (e->time <= now) {
754 struct timeval tv;
755 pa_assert(e->callback);
756
757 /* Disable time event */
758 mainloop_time_restart(e, NULL);
759
760 e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, e->use_rtclock), e->userdata);
761
762 r++;
763 }
764 }
765
766 return r;
767 }
768
769 void pa_mainloop_wakeup(pa_mainloop *m) {
770 char c = 'W';
771 pa_assert(m);
772
773 if (pa_write(m->wakeup_pipe[1], &c, sizeof(c), &m->wakeup_pipe_type) < 0)
774 /* Not much options for recovering from the error. Let's at least log something. */
775 pa_log("pa_write() failed while trying to wake up the mainloop: %s", pa_cstrerror(errno));
776
777 pa_atomic_store(&m->wakeup_requested, TRUE);
778 }
779
780 static void clear_wakeup(pa_mainloop *m) {
781 char c[10];
782
783 pa_assert(m);
784
785 if (pa_atomic_cmpxchg(&m->wakeup_requested, TRUE, FALSE)) {
786 while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c))
787 ;
788 }
789 }
790
791 int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
792 pa_assert(m);
793 pa_assert(m->state == STATE_PASSIVE);
794
795 clear_wakeup(m);
796 scan_dead(m);
797
798 if (m->quit)
799 goto quit;
800
801 if (m->n_enabled_defer_events <= 0) {
802
803 if (m->rebuild_pollfds)
804 rebuild_pollfds(m);
805
806 m->prepared_timeout = calc_next_timeout(m);
807 if (timeout >= 0) {
808 uint64_t u = (uint64_t) timeout * PA_USEC_PER_MSEC;
809
810 if (u < m->prepared_timeout || m->prepared_timeout == PA_USEC_INVALID)
811 m->prepared_timeout = timeout;
812 }
813 }
814
815 m->state = STATE_PREPARED;
816 return 0;
817
818 quit:
819 m->state = STATE_QUIT;
820 return -2;
821 }
822
823 static int usec_to_timeout(pa_usec_t u) {
824 int timeout;
825
826 if (u == PA_USEC_INVALID)
827 return -1;
828
829 timeout = (u + PA_USEC_PER_MSEC - 1) / PA_USEC_PER_MSEC;
830 pa_assert(timeout >= 0);
831
832 return timeout;
833 }
834
835 int pa_mainloop_poll(pa_mainloop *m) {
836 pa_assert(m);
837 pa_assert(m->state == STATE_PREPARED);
838
839 if (m->quit)
840 goto quit;
841
842 m->state = STATE_POLLING;
843
844 if (m->n_enabled_defer_events )
845 m->poll_func_ret = 0;
846 else {
847 pa_assert(!m->rebuild_pollfds);
848
849 if (m->poll_func)
850 m->poll_func_ret = m->poll_func(
851 m->pollfds, m->n_pollfds,
852 usec_to_timeout(m->prepared_timeout),
853 m->poll_func_userdata);
854 else {
855 #ifdef HAVE_PPOLL
856 struct timespec ts;
857
858 m->poll_func_ret = ppoll(
859 m->pollfds, m->n_pollfds,
860 m->prepared_timeout == PA_USEC_INVALID ? NULL : pa_timespec_store(&ts, m->prepared_timeout),
861 NULL);
862 #else
863 m->poll_func_ret = pa_poll(
864 m->pollfds, m->n_pollfds,
865 usec_to_timeout(m->prepared_timeout));
866 #endif
867 }
868
869 if (m->poll_func_ret < 0) {
870 if (errno == EINTR)
871 m->poll_func_ret = 0;
872 else
873 pa_log("poll(): %s", pa_cstrerror(errno));
874 }
875 }
876
877 m->state = m->poll_func_ret < 0 ? STATE_PASSIVE : STATE_POLLED;
878 return m->poll_func_ret;
879
880 quit:
881 m->state = STATE_QUIT;
882 return -2;
883 }
884
885 int pa_mainloop_dispatch(pa_mainloop *m) {
886 unsigned dispatched = 0;
887
888 pa_assert(m);
889 pa_assert(m->state == STATE_POLLED);
890
891 if (m->quit)
892 goto quit;
893
894 if (m->n_enabled_defer_events)
895 dispatched += dispatch_defer(m);
896 else {
897 if (m->n_enabled_time_events)
898 dispatched += dispatch_timeout(m);
899
900 if (m->quit)
901 goto quit;
902
903 if (m->poll_func_ret > 0)
904 dispatched += dispatch_pollfds(m);
905 }
906
907 if (m->quit)
908 goto quit;
909
910 m->state = STATE_PASSIVE;
911
912 return (int) dispatched;
913
914 quit:
915 m->state = STATE_QUIT;
916 return -2;
917 }
918
919 int pa_mainloop_get_retval(pa_mainloop *m) {
920 pa_assert(m);
921
922 return m->retval;
923 }
924
925 int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) {
926 int r;
927 pa_assert(m);
928
929 if ((r = pa_mainloop_prepare(m, block ? -1 : 0)) < 0)
930 goto quit;
931
932 if ((r = pa_mainloop_poll(m)) < 0)
933 goto quit;
934
935 if ((r = pa_mainloop_dispatch(m)) < 0)
936 goto quit;
937
938 return r;
939
940 quit:
941
942 if ((r == -2) && retval)
943 *retval = pa_mainloop_get_retval(m);
944 return r;
945 }
946
947 int pa_mainloop_run(pa_mainloop *m, int *retval) {
948 int r;
949
950 while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0)
951 ;
952
953 if (r == -2)
954 return 1;
955 else if (r < 0)
956 return -1;
957 else
958 return 0;
959 }
960
961 void pa_mainloop_quit(pa_mainloop *m, int retval) {
962 pa_assert(m);
963
964 m->quit = TRUE;
965 m->retval = retval;
966 pa_mainloop_wakeup(m);
967 }
968
969 pa_mainloop_api* pa_mainloop_get_api(pa_mainloop *m) {
970 pa_assert(m);
971
972 return &m->api;
973 }
974
975 void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) {
976 pa_assert(m);
977
978 m->poll_func = poll_func;
979 m->poll_func_userdata = userdata;
980 }
981
982 pa_bool_t pa_mainloop_is_our_api(pa_mainloop_api *m) {
983 pa_assert(m);
984
985 return m->io_new == mainloop_io_new;
986 }