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