]> code.delx.au - pulseaudio/blob - src/pulse/mainloop.c
win32: Avoid some compiler warnings when cross-compiling for mingw32
[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_bool_t wakeup_requested:1;
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 #ifdef OS_IS_WIN32
179 {
180 fd_set xset;
181 struct timeval tv;
182
183 tv.tv_sec = 0;
184 tv.tv_usec = 0;
185
186 FD_ZERO (&xset);
187 FD_SET (fd, &xset);
188
189 if ((select(fd, NULL, NULL, &xset, &tv) == -1) && (WSAGetLastError() == WSAENOTSOCK)) {
190 pa_log_warn("Cannot monitor non-socket file descriptors.");
191 e->dead = TRUE;
192 }
193 }
194 #endif
195
196 PA_LLIST_PREPEND(pa_io_event, m->io_events, e);
197 m->rebuild_pollfds = TRUE;
198 m->n_io_events ++;
199
200 pa_mainloop_wakeup(m);
201
202 return e;
203 }
204
205 static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) {
206 pa_assert(e);
207 pa_assert(!e->dead);
208
209 if (e->events == events)
210 return;
211
212 e->events = events;
213
214 if (e->pollfd)
215 e->pollfd->events = map_flags_to_libc(events);
216 else
217 e->mainloop->rebuild_pollfds = TRUE;
218
219 pa_mainloop_wakeup(e->mainloop);
220 }
221
222 static void mainloop_io_free(pa_io_event *e) {
223 pa_assert(e);
224 pa_assert(!e->dead);
225
226 e->dead = TRUE;
227 e->mainloop->io_events_please_scan ++;
228
229 e->mainloop->n_io_events --;
230 e->mainloop->rebuild_pollfds = TRUE;
231
232 pa_mainloop_wakeup(e->mainloop);
233 }
234
235 static void mainloop_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t callback) {
236 pa_assert(e);
237
238 e->destroy_callback = callback;
239 }
240
241 /* Defer events */
242 static pa_defer_event* mainloop_defer_new(
243 pa_mainloop_api *a,
244 pa_defer_event_cb_t callback,
245 void *userdata) {
246
247 pa_mainloop *m;
248 pa_defer_event *e;
249
250 pa_assert(a);
251 pa_assert(a->userdata);
252 pa_assert(callback);
253
254 m = a->userdata;
255 pa_assert(a == &m->api);
256
257 e = pa_xnew0(pa_defer_event, 1);
258 e->mainloop = m;
259
260 e->enabled = TRUE;
261 m->n_enabled_defer_events++;
262
263 e->callback = callback;
264 e->userdata = userdata;
265
266 PA_LLIST_PREPEND(pa_defer_event, m->defer_events, e);
267
268 pa_mainloop_wakeup(e->mainloop);
269
270 return e;
271 }
272
273 static void mainloop_defer_enable(pa_defer_event *e, int b) {
274 pa_assert(e);
275 pa_assert(!e->dead);
276
277 if (e->enabled && !b) {
278 pa_assert(e->mainloop->n_enabled_defer_events > 0);
279 e->mainloop->n_enabled_defer_events--;
280 } else if (!e->enabled && b) {
281 e->mainloop->n_enabled_defer_events++;
282 pa_mainloop_wakeup(e->mainloop);
283 }
284
285 e->enabled = b;
286 }
287
288 static void mainloop_defer_free(pa_defer_event *e) {
289 pa_assert(e);
290 pa_assert(!e->dead);
291
292 e->dead = TRUE;
293 e->mainloop->defer_events_please_scan ++;
294
295 if (e->enabled) {
296 pa_assert(e->mainloop->n_enabled_defer_events > 0);
297 e->mainloop->n_enabled_defer_events--;
298 e->enabled = FALSE;
299 }
300 }
301
302 static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t callback) {
303 pa_assert(e);
304 pa_assert(!e->dead);
305
306 e->destroy_callback = callback;
307 }
308
309 /* Time events */
310 static pa_usec_t make_rt(const struct timeval *tv, pa_bool_t *use_rtclock) {
311 struct timeval ttv;
312
313 if (!tv) {
314 *use_rtclock = FALSE;
315 return PA_USEC_INVALID;
316 }
317
318 ttv = *tv;
319 *use_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK);
320
321 if (*use_rtclock)
322 ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK;
323 else
324 pa_rtclock_from_wallclock(&ttv);
325
326 return pa_timeval_load(&ttv);
327 }
328
329 static pa_time_event* mainloop_time_new(
330 pa_mainloop_api *a,
331 const struct timeval *tv,
332 pa_time_event_cb_t callback,
333 void *userdata) {
334
335 pa_mainloop *m;
336 pa_time_event *e;
337 pa_usec_t t;
338 pa_bool_t use_rtclock = FALSE;
339
340 pa_assert(a);
341 pa_assert(a->userdata);
342 pa_assert(callback);
343
344 t = make_rt(tv, &use_rtclock);
345
346 m = a->userdata;
347 pa_assert(a == &m->api);
348
349 e = pa_xnew0(pa_time_event, 1);
350 e->mainloop = m;
351
352 if ((e->enabled = (t != PA_USEC_INVALID))) {
353 e->time = t;
354 e->use_rtclock = use_rtclock;
355
356 m->n_enabled_time_events++;
357
358 if (m->cached_next_time_event) {
359 pa_assert(m->cached_next_time_event->enabled);
360
361 if (t < m->cached_next_time_event->time)
362 m->cached_next_time_event = e;
363 }
364 }
365
366 e->callback = callback;
367 e->userdata = userdata;
368
369 PA_LLIST_PREPEND(pa_time_event, m->time_events, e);
370
371 if (e->enabled)
372 pa_mainloop_wakeup(m);
373
374 return e;
375 }
376
377 static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
378 pa_bool_t valid;
379 pa_usec_t t;
380 pa_bool_t use_rtclock = FALSE;
381
382 pa_assert(e);
383 pa_assert(!e->dead);
384
385 t = make_rt(tv, &use_rtclock);
386
387 valid = (t != PA_USEC_INVALID);
388 if (e->enabled && !valid) {
389 pa_assert(e->mainloop->n_enabled_time_events > 0);
390 e->mainloop->n_enabled_time_events--;
391 } else if (!e->enabled && valid)
392 e->mainloop->n_enabled_time_events++;
393
394 if ((e->enabled = valid)) {
395 e->time = t;
396 e->use_rtclock = use_rtclock;
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 (pa_pipe_cloexec(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
485 m->rebuild_pollfds = TRUE;
486
487 m->api = vtable;
488 m->api.userdata = m;
489
490 m->state = STATE_PASSIVE;
491
492 m->poll_func_ret = -1;
493
494 return m;
495 }
496
497 static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) {
498 pa_io_event *e, *n;
499
500 PA_LLIST_FOREACH_SAFE(e, n, m->io_events) {
501
502 if (!force && m->io_events_please_scan <= 0)
503 break;
504
505 if (force || e->dead) {
506 PA_LLIST_REMOVE(pa_io_event, m->io_events, e);
507
508 if (e->dead) {
509 pa_assert(m->io_events_please_scan > 0);
510 m->io_events_please_scan--;
511 }
512
513 if (e->destroy_callback)
514 e->destroy_callback(&m->api, e, e->userdata);
515
516 pa_xfree(e);
517
518 m->rebuild_pollfds = TRUE;
519 }
520 }
521
522 pa_assert(m->io_events_please_scan == 0);
523 }
524
525 static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) {
526 pa_time_event *e, *n;
527
528 PA_LLIST_FOREACH_SAFE(e, n, m->time_events) {
529
530 if (!force && m->time_events_please_scan <= 0)
531 break;
532
533 if (force || e->dead) {
534 PA_LLIST_REMOVE(pa_time_event, m->time_events, e);
535
536 if (e->dead) {
537 pa_assert(m->time_events_please_scan > 0);
538 m->time_events_please_scan--;
539 }
540
541 if (!e->dead && e->enabled) {
542 pa_assert(m->n_enabled_time_events > 0);
543 m->n_enabled_time_events--;
544 e->enabled = FALSE;
545 }
546
547 if (e->destroy_callback)
548 e->destroy_callback(&m->api, e, e->userdata);
549
550 pa_xfree(e);
551 }
552 }
553
554 pa_assert(m->time_events_please_scan == 0);
555 }
556
557 static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) {
558 pa_defer_event *e, *n;
559
560 PA_LLIST_FOREACH_SAFE(e, n, m->defer_events) {
561
562 if (!force && m->defer_events_please_scan <= 0)
563 break;
564
565 if (force || e->dead) {
566 PA_LLIST_REMOVE(pa_defer_event, m->defer_events, e);
567
568 if (e->dead) {
569 pa_assert(m->defer_events_please_scan > 0);
570 m->defer_events_please_scan--;
571 }
572
573 if (!e->dead && e->enabled) {
574 pa_assert(m->n_enabled_defer_events > 0);
575 m->n_enabled_defer_events--;
576 e->enabled = FALSE;
577 }
578
579 if (e->destroy_callback)
580 e->destroy_callback(&m->api, e, e->userdata);
581
582 pa_xfree(e);
583 }
584 }
585
586 pa_assert(m->defer_events_please_scan == 0);
587 }
588
589
590 void pa_mainloop_free(pa_mainloop *m) {
591 pa_assert(m);
592
593 cleanup_io_events(m, TRUE);
594 cleanup_defer_events(m, TRUE);
595 cleanup_time_events(m, TRUE);
596
597 pa_xfree(m->pollfds);
598
599 pa_close_pipe(m->wakeup_pipe);
600
601 pa_xfree(m);
602 }
603
604 static void scan_dead(pa_mainloop *m) {
605 pa_assert(m);
606
607 if (m->io_events_please_scan)
608 cleanup_io_events(m, FALSE);
609
610 if (m->time_events_please_scan)
611 cleanup_time_events(m, FALSE);
612
613 if (m->defer_events_please_scan)
614 cleanup_defer_events(m, FALSE);
615 }
616
617 static void rebuild_pollfds(pa_mainloop *m) {
618 pa_io_event*e;
619 struct pollfd *p;
620 unsigned l;
621
622 l = m->n_io_events + 1;
623 if (m->max_pollfds < l) {
624 l *= 2;
625 m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l);
626 m->max_pollfds = l;
627 }
628
629 m->n_pollfds = 0;
630 p = m->pollfds;
631
632 if (m->wakeup_pipe[0] >= 0) {
633 m->pollfds[0].fd = m->wakeup_pipe[0];
634 m->pollfds[0].events = POLLIN;
635 m->pollfds[0].revents = 0;
636 p++;
637 m->n_pollfds++;
638 }
639
640 PA_LLIST_FOREACH(e, m->io_events) {
641 if (e->dead) {
642 e->pollfd = NULL;
643 continue;
644 }
645
646 e->pollfd = p;
647 p->fd = e->fd;
648 p->events = map_flags_to_libc(e->events);
649 p->revents = 0;
650
651 p++;
652 m->n_pollfds++;
653 }
654
655 m->rebuild_pollfds = FALSE;
656 }
657
658 static unsigned dispatch_pollfds(pa_mainloop *m) {
659 pa_io_event *e;
660 unsigned r = 0, k;
661
662 pa_assert(m->poll_func_ret > 0);
663
664 k = m->poll_func_ret;
665
666 PA_LLIST_FOREACH(e, m->io_events) {
667
668 if (k <= 0 || m->quit)
669 break;
670
671 if (e->dead || !e->pollfd || !e->pollfd->revents)
672 continue;
673
674 pa_assert(e->pollfd->fd == e->fd);
675 pa_assert(e->callback);
676
677 e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata);
678 e->pollfd->revents = 0;
679 r++;
680 k--;
681 }
682
683 return r;
684 }
685
686 static unsigned dispatch_defer(pa_mainloop *m) {
687 pa_defer_event *e;
688 unsigned r = 0;
689
690 if (m->n_enabled_defer_events <= 0)
691 return 0;
692
693 PA_LLIST_FOREACH(e, m->defer_events) {
694
695 if (m->quit)
696 break;
697
698 if (e->dead || !e->enabled)
699 continue;
700
701 pa_assert(e->callback);
702 e->callback(&m->api, e, e->userdata);
703 r++;
704 }
705
706 return r;
707 }
708
709 static pa_time_event* find_next_time_event(pa_mainloop *m) {
710 pa_time_event *t, *n = NULL;
711 pa_assert(m);
712
713 if (m->cached_next_time_event)
714 return m->cached_next_time_event;
715
716 PA_LLIST_FOREACH(t, m->time_events) {
717
718 if (t->dead || !t->enabled)
719 continue;
720
721 if (!n || t->time < n->time) {
722 n = t;
723
724 /* Shortcut for time == 0 */
725 if (n->time == 0)
726 break;
727 }
728 }
729
730 m->cached_next_time_event = n;
731 return n;
732 }
733
734 static pa_usec_t calc_next_timeout(pa_mainloop *m) {
735 pa_time_event *t;
736 pa_usec_t clock_now;
737
738 if (m->n_enabled_time_events <= 0)
739 return PA_USEC_INVALID;
740
741 pa_assert_se(t = find_next_time_event(m));
742
743 if (t->time <= 0)
744 return 0;
745
746 clock_now = pa_rtclock_now();
747
748 if (t->time <= clock_now)
749 return 0;
750
751 return t->time - clock_now;
752 }
753
754 static unsigned dispatch_timeout(pa_mainloop *m) {
755 pa_time_event *e;
756 pa_usec_t now;
757 unsigned r = 0;
758 pa_assert(m);
759
760 if (m->n_enabled_time_events <= 0)
761 return 0;
762
763 now = pa_rtclock_now();
764
765 PA_LLIST_FOREACH(e, m->time_events) {
766
767 if (m->quit)
768 break;
769
770 if (e->dead || !e->enabled)
771 continue;
772
773 if (e->time <= now) {
774 struct timeval tv;
775 pa_assert(e->callback);
776
777 /* Disable time event */
778 mainloop_time_restart(e, NULL);
779
780 e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, e->use_rtclock), e->userdata);
781
782 r++;
783 }
784 }
785
786 return r;
787 }
788
789 void pa_mainloop_wakeup(pa_mainloop *m) {
790 char c = 'W';
791 pa_assert(m);
792
793 if (m->wakeup_pipe[1] >= 0 && m->state == STATE_POLLING) {
794 pa_write(m->wakeup_pipe[1], &c, sizeof(c), &m->wakeup_pipe_type);
795 m->wakeup_requested++;
796 }
797 }
798
799 static void clear_wakeup(pa_mainloop *m) {
800 char c[10];
801
802 pa_assert(m);
803
804 if (m->wakeup_pipe[0] < 0)
805 return;
806
807 if (m->wakeup_requested) {
808 while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c))
809 ;
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 int timeout;
848
849 if (u == PA_USEC_INVALID)
850 return -1;
851
852 timeout = (u + PA_USEC_PER_MSEC - 1) / PA_USEC_PER_MSEC;
853 pa_assert(timeout >= 0);
854
855 return timeout;
856 }
857
858 int pa_mainloop_poll(pa_mainloop *m) {
859 pa_assert(m);
860 pa_assert(m->state == STATE_PREPARED);
861
862 if (m->quit)
863 goto quit;
864
865 m->state = STATE_POLLING;
866
867 if (m->n_enabled_defer_events )
868 m->poll_func_ret = 0;
869 else {
870 pa_assert(!m->rebuild_pollfds);
871
872 if (m->poll_func)
873 m->poll_func_ret = m->poll_func(
874 m->pollfds, m->n_pollfds,
875 usec_to_timeout(m->prepared_timeout),
876 m->poll_func_userdata);
877 else {
878 #ifdef HAVE_PPOLL
879 struct timespec ts;
880
881 m->poll_func_ret = ppoll(
882 m->pollfds, m->n_pollfds,
883 m->prepared_timeout == PA_USEC_INVALID ? NULL : pa_timespec_store(&ts, m->prepared_timeout),
884 NULL);
885 #else
886 m->poll_func_ret = pa_poll(
887 m->pollfds, m->n_pollfds,
888 usec_to_timeout(m->prepared_timeout));
889 #endif
890 }
891
892 if (m->poll_func_ret < 0) {
893 if (errno == EINTR)
894 m->poll_func_ret = 0;
895 else
896 pa_log("poll(): %s", pa_cstrerror(errno));
897 }
898 }
899
900 m->state = m->poll_func_ret < 0 ? STATE_PASSIVE : STATE_POLLED;
901 return m->poll_func_ret;
902
903 quit:
904 m->state = STATE_QUIT;
905 return -2;
906 }
907
908 int pa_mainloop_dispatch(pa_mainloop *m) {
909 unsigned dispatched = 0;
910
911 pa_assert(m);
912 pa_assert(m->state == STATE_POLLED);
913
914 if (m->quit)
915 goto quit;
916
917 if (m->n_enabled_defer_events)
918 dispatched += dispatch_defer(m);
919 else {
920 if (m->n_enabled_time_events)
921 dispatched += dispatch_timeout(m);
922
923 if (m->quit)
924 goto quit;
925
926 if (m->poll_func_ret > 0)
927 dispatched += dispatch_pollfds(m);
928 }
929
930 if (m->quit)
931 goto quit;
932
933 m->state = STATE_PASSIVE;
934
935 return (int) dispatched;
936
937 quit:
938 m->state = STATE_QUIT;
939 return -2;
940 }
941
942 int pa_mainloop_get_retval(pa_mainloop *m) {
943 pa_assert(m);
944
945 return m->retval;
946 }
947
948 int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) {
949 int r;
950 pa_assert(m);
951
952 if ((r = pa_mainloop_prepare(m, block ? -1 : 0)) < 0)
953 goto quit;
954
955 if ((r = pa_mainloop_poll(m)) < 0)
956 goto quit;
957
958 if ((r = pa_mainloop_dispatch(m)) < 0)
959 goto quit;
960
961 return r;
962
963 quit:
964
965 if ((r == -2) && retval)
966 *retval = pa_mainloop_get_retval(m);
967 return r;
968 }
969
970 int pa_mainloop_run(pa_mainloop *m, int *retval) {
971 int r;
972
973 while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0)
974 ;
975
976 if (r == -2)
977 return 1;
978 else if (r < 0)
979 return -1;
980 else
981 return 0;
982 }
983
984 void pa_mainloop_quit(pa_mainloop *m, int retval) {
985 pa_assert(m);
986
987 m->quit = TRUE;
988 m->retval = retval;
989 pa_mainloop_wakeup(m);
990 }
991
992 pa_mainloop_api* pa_mainloop_get_api(pa_mainloop *m) {
993 pa_assert(m);
994
995 return &m->api;
996 }
997
998 void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) {
999 pa_assert(m);
1000
1001 m->poll_func = poll_func;
1002 m->poll_func_userdata = userdata;
1003 }
1004
1005 pa_bool_t pa_mainloop_is_our_api(pa_mainloop_api *m) {
1006 pa_assert(m);
1007
1008 return m->io_new == mainloop_io_new;
1009 }