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