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