153a5a1b3Sopenharmony_ci/*** 253a5a1b3Sopenharmony_ci This file is part of PulseAudio. 353a5a1b3Sopenharmony_ci 453a5a1b3Sopenharmony_ci Copyright 2004-2006 Lennart Poettering 553a5a1b3Sopenharmony_ci Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB 653a5a1b3Sopenharmony_ci 753a5a1b3Sopenharmony_ci PulseAudio is free software; you can redistribute it and/or modify 853a5a1b3Sopenharmony_ci it under the terms of the GNU Lesser General Public License as published 953a5a1b3Sopenharmony_ci by the Free Software Foundation; either version 2.1 of the License, 1053a5a1b3Sopenharmony_ci or (at your option) any later version. 1153a5a1b3Sopenharmony_ci 1253a5a1b3Sopenharmony_ci PulseAudio is distributed in the hope that it will be useful, but 1353a5a1b3Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1453a5a1b3Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1553a5a1b3Sopenharmony_ci General Public License for more details. 1653a5a1b3Sopenharmony_ci 1753a5a1b3Sopenharmony_ci You should have received a copy of the GNU Lesser General Public License 1853a5a1b3Sopenharmony_ci along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 1953a5a1b3Sopenharmony_ci***/ 2053a5a1b3Sopenharmony_ci 2153a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 2253a5a1b3Sopenharmony_ci#include <config.h> 2353a5a1b3Sopenharmony_ci#endif 2453a5a1b3Sopenharmony_ci 2553a5a1b3Sopenharmony_ci#include <stdio.h> 2653a5a1b3Sopenharmony_ci#include <unistd.h> 2753a5a1b3Sopenharmony_ci#include <stdlib.h> 2853a5a1b3Sopenharmony_ci#include <fcntl.h> 2953a5a1b3Sopenharmony_ci#include <errno.h> 3053a5a1b3Sopenharmony_ci 3153a5a1b3Sopenharmony_ci#ifndef HAVE_PIPE 3253a5a1b3Sopenharmony_ci#include <pulsecore/pipe.h> 3353a5a1b3Sopenharmony_ci#endif 3453a5a1b3Sopenharmony_ci 3553a5a1b3Sopenharmony_ci#ifdef OS_IS_WIN32 3653a5a1b3Sopenharmony_ci#include <winsock2.h> 3753a5a1b3Sopenharmony_ci#endif 3853a5a1b3Sopenharmony_ci 3953a5a1b3Sopenharmony_ci#include <pulse/rtclock.h> 4053a5a1b3Sopenharmony_ci#include <pulse/timeval.h> 4153a5a1b3Sopenharmony_ci#include <pulse/xmalloc.h> 4253a5a1b3Sopenharmony_ci 4353a5a1b3Sopenharmony_ci#include <pulsecore/poll.h> 4453a5a1b3Sopenharmony_ci#include <pulsecore/core-rtclock.h> 4553a5a1b3Sopenharmony_ci#include <pulsecore/core-util.h> 4653a5a1b3Sopenharmony_ci#include <pulsecore/i18n.h> 4753a5a1b3Sopenharmony_ci#include <pulsecore/llist.h> 4853a5a1b3Sopenharmony_ci#include <pulsecore/log.h> 4953a5a1b3Sopenharmony_ci#include <pulsecore/core-error.h> 5053a5a1b3Sopenharmony_ci#include <pulsecore/socket.h> 5153a5a1b3Sopenharmony_ci#include <pulsecore/macro.h> 5253a5a1b3Sopenharmony_ci 5353a5a1b3Sopenharmony_ci#include "mainloop.h" 5453a5a1b3Sopenharmony_ci#include "internal.h" 5553a5a1b3Sopenharmony_ci 5653a5a1b3Sopenharmony_cistruct pa_io_event { 5753a5a1b3Sopenharmony_ci pa_mainloop *mainloop; 5853a5a1b3Sopenharmony_ci bool dead:1; 5953a5a1b3Sopenharmony_ci 6053a5a1b3Sopenharmony_ci int fd; 6153a5a1b3Sopenharmony_ci pa_io_event_flags_t events; 6253a5a1b3Sopenharmony_ci struct pollfd *pollfd; 6353a5a1b3Sopenharmony_ci 6453a5a1b3Sopenharmony_ci pa_io_event_cb_t callback; 6553a5a1b3Sopenharmony_ci void *userdata; 6653a5a1b3Sopenharmony_ci pa_io_event_destroy_cb_t destroy_callback; 6753a5a1b3Sopenharmony_ci 6853a5a1b3Sopenharmony_ci PA_LLIST_FIELDS(pa_io_event); 6953a5a1b3Sopenharmony_ci}; 7053a5a1b3Sopenharmony_ci 7153a5a1b3Sopenharmony_cistruct pa_time_event { 7253a5a1b3Sopenharmony_ci pa_mainloop *mainloop; 7353a5a1b3Sopenharmony_ci bool dead:1; 7453a5a1b3Sopenharmony_ci 7553a5a1b3Sopenharmony_ci bool enabled:1; 7653a5a1b3Sopenharmony_ci bool use_rtclock:1; 7753a5a1b3Sopenharmony_ci pa_usec_t time; 7853a5a1b3Sopenharmony_ci 7953a5a1b3Sopenharmony_ci pa_time_event_cb_t callback; 8053a5a1b3Sopenharmony_ci void *userdata; 8153a5a1b3Sopenharmony_ci pa_time_event_destroy_cb_t destroy_callback; 8253a5a1b3Sopenharmony_ci 8353a5a1b3Sopenharmony_ci PA_LLIST_FIELDS(pa_time_event); 8453a5a1b3Sopenharmony_ci}; 8553a5a1b3Sopenharmony_ci 8653a5a1b3Sopenharmony_cistruct pa_defer_event { 8753a5a1b3Sopenharmony_ci pa_mainloop *mainloop; 8853a5a1b3Sopenharmony_ci bool dead:1; 8953a5a1b3Sopenharmony_ci 9053a5a1b3Sopenharmony_ci bool enabled:1; 9153a5a1b3Sopenharmony_ci 9253a5a1b3Sopenharmony_ci pa_defer_event_cb_t callback; 9353a5a1b3Sopenharmony_ci void *userdata; 9453a5a1b3Sopenharmony_ci pa_defer_event_destroy_cb_t destroy_callback; 9553a5a1b3Sopenharmony_ci 9653a5a1b3Sopenharmony_ci PA_LLIST_FIELDS(pa_defer_event); 9753a5a1b3Sopenharmony_ci}; 9853a5a1b3Sopenharmony_ci 9953a5a1b3Sopenharmony_cistruct pa_mainloop { 10053a5a1b3Sopenharmony_ci PA_LLIST_HEAD(pa_io_event, io_events); 10153a5a1b3Sopenharmony_ci PA_LLIST_HEAD(pa_time_event, time_events); 10253a5a1b3Sopenharmony_ci PA_LLIST_HEAD(pa_defer_event, defer_events); 10353a5a1b3Sopenharmony_ci 10453a5a1b3Sopenharmony_ci unsigned n_enabled_defer_events, n_enabled_time_events, n_io_events; 10553a5a1b3Sopenharmony_ci unsigned io_events_please_scan, time_events_please_scan, defer_events_please_scan; 10653a5a1b3Sopenharmony_ci 10753a5a1b3Sopenharmony_ci bool rebuild_pollfds:1; 10853a5a1b3Sopenharmony_ci struct pollfd *pollfds; 10953a5a1b3Sopenharmony_ci unsigned max_pollfds, n_pollfds; 11053a5a1b3Sopenharmony_ci 11153a5a1b3Sopenharmony_ci pa_usec_t prepared_timeout; 11253a5a1b3Sopenharmony_ci pa_time_event *cached_next_time_event; 11353a5a1b3Sopenharmony_ci 11453a5a1b3Sopenharmony_ci pa_mainloop_api api; 11553a5a1b3Sopenharmony_ci 11653a5a1b3Sopenharmony_ci int retval; 11753a5a1b3Sopenharmony_ci bool quit:1; 11853a5a1b3Sopenharmony_ci 11953a5a1b3Sopenharmony_ci int wakeup_pipe[2]; 12053a5a1b3Sopenharmony_ci int wakeup_pipe_type; 12153a5a1b3Sopenharmony_ci 12253a5a1b3Sopenharmony_ci enum { 12353a5a1b3Sopenharmony_ci STATE_PASSIVE, 12453a5a1b3Sopenharmony_ci STATE_PREPARED, 12553a5a1b3Sopenharmony_ci STATE_POLLING, 12653a5a1b3Sopenharmony_ci STATE_POLLED, 12753a5a1b3Sopenharmony_ci STATE_QUIT 12853a5a1b3Sopenharmony_ci } state; 12953a5a1b3Sopenharmony_ci 13053a5a1b3Sopenharmony_ci pa_poll_func poll_func; 13153a5a1b3Sopenharmony_ci void *poll_func_userdata; 13253a5a1b3Sopenharmony_ci int poll_func_ret; 13353a5a1b3Sopenharmony_ci}; 13453a5a1b3Sopenharmony_ci 13553a5a1b3Sopenharmony_cistatic short map_flags_to_libc(pa_io_event_flags_t flags) { 13653a5a1b3Sopenharmony_ci return (short) 13753a5a1b3Sopenharmony_ci ((flags & PA_IO_EVENT_INPUT ? POLLIN : 0) | 13853a5a1b3Sopenharmony_ci (flags & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) | 13953a5a1b3Sopenharmony_ci (flags & PA_IO_EVENT_ERROR ? POLLERR : 0) | 14053a5a1b3Sopenharmony_ci (flags & PA_IO_EVENT_HANGUP ? POLLHUP : 0)); 14153a5a1b3Sopenharmony_ci} 14253a5a1b3Sopenharmony_ci 14353a5a1b3Sopenharmony_cistatic pa_io_event_flags_t map_flags_from_libc(short flags) { 14453a5a1b3Sopenharmony_ci return 14553a5a1b3Sopenharmony_ci (flags & POLLIN ? PA_IO_EVENT_INPUT : 0) | 14653a5a1b3Sopenharmony_ci (flags & POLLOUT ? PA_IO_EVENT_OUTPUT : 0) | 14753a5a1b3Sopenharmony_ci (flags & POLLERR ? PA_IO_EVENT_ERROR : 0) | 14853a5a1b3Sopenharmony_ci (flags & POLLHUP ? PA_IO_EVENT_HANGUP : 0); 14953a5a1b3Sopenharmony_ci} 15053a5a1b3Sopenharmony_ci 15153a5a1b3Sopenharmony_ci/* IO events */ 15253a5a1b3Sopenharmony_cistatic pa_io_event* mainloop_io_new( 15353a5a1b3Sopenharmony_ci pa_mainloop_api *a, 15453a5a1b3Sopenharmony_ci int fd, 15553a5a1b3Sopenharmony_ci pa_io_event_flags_t events, 15653a5a1b3Sopenharmony_ci pa_io_event_cb_t callback, 15753a5a1b3Sopenharmony_ci void *userdata) { 15853a5a1b3Sopenharmony_ci 15953a5a1b3Sopenharmony_ci pa_mainloop *m; 16053a5a1b3Sopenharmony_ci pa_io_event *e; 16153a5a1b3Sopenharmony_ci 16253a5a1b3Sopenharmony_ci pa_assert(a); 16353a5a1b3Sopenharmony_ci pa_assert(a->userdata); 16453a5a1b3Sopenharmony_ci pa_assert(fd >= 0); 16553a5a1b3Sopenharmony_ci pa_assert(callback); 16653a5a1b3Sopenharmony_ci 16753a5a1b3Sopenharmony_ci m = a->userdata; 16853a5a1b3Sopenharmony_ci pa_assert(a == &m->api); 16953a5a1b3Sopenharmony_ci 17053a5a1b3Sopenharmony_ci e = pa_xnew0(pa_io_event, 1); 17153a5a1b3Sopenharmony_ci e->mainloop = m; 17253a5a1b3Sopenharmony_ci 17353a5a1b3Sopenharmony_ci e->fd = fd; 17453a5a1b3Sopenharmony_ci e->events = events; 17553a5a1b3Sopenharmony_ci 17653a5a1b3Sopenharmony_ci e->callback = callback; 17753a5a1b3Sopenharmony_ci e->userdata = userdata; 17853a5a1b3Sopenharmony_ci 17953a5a1b3Sopenharmony_ci PA_LLIST_PREPEND(pa_io_event, m->io_events, e); 18053a5a1b3Sopenharmony_ci m->rebuild_pollfds = true; 18153a5a1b3Sopenharmony_ci m->n_io_events ++; 18253a5a1b3Sopenharmony_ci 18353a5a1b3Sopenharmony_ci pa_mainloop_wakeup(m); 18453a5a1b3Sopenharmony_ci 18553a5a1b3Sopenharmony_ci return e; 18653a5a1b3Sopenharmony_ci} 18753a5a1b3Sopenharmony_ci 18853a5a1b3Sopenharmony_cistatic void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) { 18953a5a1b3Sopenharmony_ci pa_assert(e); 19053a5a1b3Sopenharmony_ci pa_assert(!e->dead); 19153a5a1b3Sopenharmony_ci 19253a5a1b3Sopenharmony_ci if (e->events == events) 19353a5a1b3Sopenharmony_ci return; 19453a5a1b3Sopenharmony_ci 19553a5a1b3Sopenharmony_ci e->events = events; 19653a5a1b3Sopenharmony_ci 19753a5a1b3Sopenharmony_ci if (e->pollfd) 19853a5a1b3Sopenharmony_ci e->pollfd->events = map_flags_to_libc(events); 19953a5a1b3Sopenharmony_ci else 20053a5a1b3Sopenharmony_ci e->mainloop->rebuild_pollfds = true; 20153a5a1b3Sopenharmony_ci 20253a5a1b3Sopenharmony_ci pa_mainloop_wakeup(e->mainloop); 20353a5a1b3Sopenharmony_ci} 20453a5a1b3Sopenharmony_ci 20553a5a1b3Sopenharmony_cistatic void mainloop_io_free(pa_io_event *e) { 20653a5a1b3Sopenharmony_ci pa_assert(e); 20753a5a1b3Sopenharmony_ci pa_assert(!e->dead); 20853a5a1b3Sopenharmony_ci 20953a5a1b3Sopenharmony_ci e->dead = true; 21053a5a1b3Sopenharmony_ci e->mainloop->io_events_please_scan ++; 21153a5a1b3Sopenharmony_ci 21253a5a1b3Sopenharmony_ci e->mainloop->n_io_events --; 21353a5a1b3Sopenharmony_ci e->mainloop->rebuild_pollfds = true; 21453a5a1b3Sopenharmony_ci 21553a5a1b3Sopenharmony_ci pa_mainloop_wakeup(e->mainloop); 21653a5a1b3Sopenharmony_ci} 21753a5a1b3Sopenharmony_ci 21853a5a1b3Sopenharmony_cistatic void mainloop_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t callback) { 21953a5a1b3Sopenharmony_ci pa_assert(e); 22053a5a1b3Sopenharmony_ci 22153a5a1b3Sopenharmony_ci e->destroy_callback = callback; 22253a5a1b3Sopenharmony_ci} 22353a5a1b3Sopenharmony_ci 22453a5a1b3Sopenharmony_ci/* Defer events */ 22553a5a1b3Sopenharmony_cistatic pa_defer_event* mainloop_defer_new( 22653a5a1b3Sopenharmony_ci pa_mainloop_api *a, 22753a5a1b3Sopenharmony_ci pa_defer_event_cb_t callback, 22853a5a1b3Sopenharmony_ci void *userdata) { 22953a5a1b3Sopenharmony_ci 23053a5a1b3Sopenharmony_ci pa_mainloop *m; 23153a5a1b3Sopenharmony_ci pa_defer_event *e; 23253a5a1b3Sopenharmony_ci 23353a5a1b3Sopenharmony_ci pa_assert(a); 23453a5a1b3Sopenharmony_ci pa_assert(a->userdata); 23553a5a1b3Sopenharmony_ci pa_assert(callback); 23653a5a1b3Sopenharmony_ci 23753a5a1b3Sopenharmony_ci m = a->userdata; 23853a5a1b3Sopenharmony_ci pa_assert(a == &m->api); 23953a5a1b3Sopenharmony_ci 24053a5a1b3Sopenharmony_ci e = pa_xnew0(pa_defer_event, 1); 24153a5a1b3Sopenharmony_ci e->mainloop = m; 24253a5a1b3Sopenharmony_ci 24353a5a1b3Sopenharmony_ci e->enabled = true; 24453a5a1b3Sopenharmony_ci m->n_enabled_defer_events++; 24553a5a1b3Sopenharmony_ci 24653a5a1b3Sopenharmony_ci e->callback = callback; 24753a5a1b3Sopenharmony_ci e->userdata = userdata; 24853a5a1b3Sopenharmony_ci 24953a5a1b3Sopenharmony_ci PA_LLIST_PREPEND(pa_defer_event, m->defer_events, e); 25053a5a1b3Sopenharmony_ci 25153a5a1b3Sopenharmony_ci pa_mainloop_wakeup(e->mainloop); 25253a5a1b3Sopenharmony_ci 25353a5a1b3Sopenharmony_ci return e; 25453a5a1b3Sopenharmony_ci} 25553a5a1b3Sopenharmony_ci 25653a5a1b3Sopenharmony_cistatic void mainloop_defer_enable(pa_defer_event *e, int b) { 25753a5a1b3Sopenharmony_ci pa_assert(e); 25853a5a1b3Sopenharmony_ci pa_assert(!e->dead); 25953a5a1b3Sopenharmony_ci 26053a5a1b3Sopenharmony_ci if (e->enabled && !b) { 26153a5a1b3Sopenharmony_ci pa_assert(e->mainloop->n_enabled_defer_events > 0); 26253a5a1b3Sopenharmony_ci e->mainloop->n_enabled_defer_events--; 26353a5a1b3Sopenharmony_ci } else if (!e->enabled && b) { 26453a5a1b3Sopenharmony_ci e->mainloop->n_enabled_defer_events++; 26553a5a1b3Sopenharmony_ci pa_mainloop_wakeup(e->mainloop); 26653a5a1b3Sopenharmony_ci } 26753a5a1b3Sopenharmony_ci 26853a5a1b3Sopenharmony_ci e->enabled = b; 26953a5a1b3Sopenharmony_ci} 27053a5a1b3Sopenharmony_ci 27153a5a1b3Sopenharmony_cistatic void mainloop_defer_free(pa_defer_event *e) { 27253a5a1b3Sopenharmony_ci pa_assert(e); 27353a5a1b3Sopenharmony_ci pa_assert(!e->dead); 27453a5a1b3Sopenharmony_ci 27553a5a1b3Sopenharmony_ci e->dead = true; 27653a5a1b3Sopenharmony_ci e->mainloop->defer_events_please_scan ++; 27753a5a1b3Sopenharmony_ci 27853a5a1b3Sopenharmony_ci if (e->enabled) { 27953a5a1b3Sopenharmony_ci pa_assert(e->mainloop->n_enabled_defer_events > 0); 28053a5a1b3Sopenharmony_ci e->mainloop->n_enabled_defer_events--; 28153a5a1b3Sopenharmony_ci e->enabled = false; 28253a5a1b3Sopenharmony_ci } 28353a5a1b3Sopenharmony_ci} 28453a5a1b3Sopenharmony_ci 28553a5a1b3Sopenharmony_cistatic void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t callback) { 28653a5a1b3Sopenharmony_ci pa_assert(e); 28753a5a1b3Sopenharmony_ci pa_assert(!e->dead); 28853a5a1b3Sopenharmony_ci 28953a5a1b3Sopenharmony_ci e->destroy_callback = callback; 29053a5a1b3Sopenharmony_ci} 29153a5a1b3Sopenharmony_ci 29253a5a1b3Sopenharmony_ci/* Time events */ 29353a5a1b3Sopenharmony_cistatic pa_usec_t make_rt(const struct timeval *tv, bool *use_rtclock) { 29453a5a1b3Sopenharmony_ci struct timeval ttv; 29553a5a1b3Sopenharmony_ci 29653a5a1b3Sopenharmony_ci if (!tv) { 29753a5a1b3Sopenharmony_ci *use_rtclock = false; 29853a5a1b3Sopenharmony_ci return PA_USEC_INVALID; 29953a5a1b3Sopenharmony_ci } 30053a5a1b3Sopenharmony_ci 30153a5a1b3Sopenharmony_ci ttv = *tv; 30253a5a1b3Sopenharmony_ci *use_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK); 30353a5a1b3Sopenharmony_ci 30453a5a1b3Sopenharmony_ci if (*use_rtclock) 30553a5a1b3Sopenharmony_ci ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK; 30653a5a1b3Sopenharmony_ci else 30753a5a1b3Sopenharmony_ci pa_rtclock_from_wallclock(&ttv); 30853a5a1b3Sopenharmony_ci 30953a5a1b3Sopenharmony_ci return pa_timeval_load(&ttv); 31053a5a1b3Sopenharmony_ci} 31153a5a1b3Sopenharmony_ci 31253a5a1b3Sopenharmony_cistatic pa_time_event* mainloop_time_new( 31353a5a1b3Sopenharmony_ci pa_mainloop_api *a, 31453a5a1b3Sopenharmony_ci const struct timeval *tv, 31553a5a1b3Sopenharmony_ci pa_time_event_cb_t callback, 31653a5a1b3Sopenharmony_ci void *userdata) { 31753a5a1b3Sopenharmony_ci 31853a5a1b3Sopenharmony_ci pa_mainloop *m; 31953a5a1b3Sopenharmony_ci pa_time_event *e; 32053a5a1b3Sopenharmony_ci pa_usec_t t; 32153a5a1b3Sopenharmony_ci bool use_rtclock = false; 32253a5a1b3Sopenharmony_ci 32353a5a1b3Sopenharmony_ci pa_assert(a); 32453a5a1b3Sopenharmony_ci pa_assert(a->userdata); 32553a5a1b3Sopenharmony_ci pa_assert(callback); 32653a5a1b3Sopenharmony_ci 32753a5a1b3Sopenharmony_ci t = make_rt(tv, &use_rtclock); 32853a5a1b3Sopenharmony_ci 32953a5a1b3Sopenharmony_ci m = a->userdata; 33053a5a1b3Sopenharmony_ci pa_assert(a == &m->api); 33153a5a1b3Sopenharmony_ci 33253a5a1b3Sopenharmony_ci e = pa_xnew0(pa_time_event, 1); 33353a5a1b3Sopenharmony_ci e->mainloop = m; 33453a5a1b3Sopenharmony_ci 33553a5a1b3Sopenharmony_ci if ((e->enabled = (t != PA_USEC_INVALID))) { 33653a5a1b3Sopenharmony_ci e->time = t; 33753a5a1b3Sopenharmony_ci e->use_rtclock = use_rtclock; 33853a5a1b3Sopenharmony_ci 33953a5a1b3Sopenharmony_ci m->n_enabled_time_events++; 34053a5a1b3Sopenharmony_ci 34153a5a1b3Sopenharmony_ci if (m->cached_next_time_event) { 34253a5a1b3Sopenharmony_ci pa_assert(m->cached_next_time_event->enabled); 34353a5a1b3Sopenharmony_ci 34453a5a1b3Sopenharmony_ci if (t < m->cached_next_time_event->time) 34553a5a1b3Sopenharmony_ci m->cached_next_time_event = e; 34653a5a1b3Sopenharmony_ci } 34753a5a1b3Sopenharmony_ci } 34853a5a1b3Sopenharmony_ci 34953a5a1b3Sopenharmony_ci e->callback = callback; 35053a5a1b3Sopenharmony_ci e->userdata = userdata; 35153a5a1b3Sopenharmony_ci 35253a5a1b3Sopenharmony_ci PA_LLIST_PREPEND(pa_time_event, m->time_events, e); 35353a5a1b3Sopenharmony_ci 35453a5a1b3Sopenharmony_ci if (e->enabled) 35553a5a1b3Sopenharmony_ci pa_mainloop_wakeup(m); 35653a5a1b3Sopenharmony_ci 35753a5a1b3Sopenharmony_ci return e; 35853a5a1b3Sopenharmony_ci} 35953a5a1b3Sopenharmony_ci 36053a5a1b3Sopenharmony_cistatic void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { 36153a5a1b3Sopenharmony_ci bool valid; 36253a5a1b3Sopenharmony_ci pa_usec_t t; 36353a5a1b3Sopenharmony_ci bool use_rtclock = false; 36453a5a1b3Sopenharmony_ci 36553a5a1b3Sopenharmony_ci pa_assert(e); 36653a5a1b3Sopenharmony_ci pa_assert(!e->dead); 36753a5a1b3Sopenharmony_ci 36853a5a1b3Sopenharmony_ci t = make_rt(tv, &use_rtclock); 36953a5a1b3Sopenharmony_ci 37053a5a1b3Sopenharmony_ci valid = (t != PA_USEC_INVALID); 37153a5a1b3Sopenharmony_ci if (e->enabled && !valid) { 37253a5a1b3Sopenharmony_ci pa_assert(e->mainloop->n_enabled_time_events > 0); 37353a5a1b3Sopenharmony_ci e->mainloop->n_enabled_time_events--; 37453a5a1b3Sopenharmony_ci } else if (!e->enabled && valid) 37553a5a1b3Sopenharmony_ci e->mainloop->n_enabled_time_events++; 37653a5a1b3Sopenharmony_ci 37753a5a1b3Sopenharmony_ci if ((e->enabled = valid)) { 37853a5a1b3Sopenharmony_ci e->time = t; 37953a5a1b3Sopenharmony_ci e->use_rtclock = use_rtclock; 38053a5a1b3Sopenharmony_ci pa_mainloop_wakeup(e->mainloop); 38153a5a1b3Sopenharmony_ci } 38253a5a1b3Sopenharmony_ci 38353a5a1b3Sopenharmony_ci if (e->mainloop->cached_next_time_event == e) 38453a5a1b3Sopenharmony_ci e->mainloop->cached_next_time_event = NULL; 38553a5a1b3Sopenharmony_ci 38653a5a1b3Sopenharmony_ci if (e->mainloop->cached_next_time_event && e->enabled) { 38753a5a1b3Sopenharmony_ci pa_assert(e->mainloop->cached_next_time_event->enabled); 38853a5a1b3Sopenharmony_ci 38953a5a1b3Sopenharmony_ci if (t < e->mainloop->cached_next_time_event->time) 39053a5a1b3Sopenharmony_ci e->mainloop->cached_next_time_event = e; 39153a5a1b3Sopenharmony_ci } 39253a5a1b3Sopenharmony_ci} 39353a5a1b3Sopenharmony_ci 39453a5a1b3Sopenharmony_cistatic void mainloop_time_free(pa_time_event *e) { 39553a5a1b3Sopenharmony_ci pa_assert(e); 39653a5a1b3Sopenharmony_ci pa_assert(!e->dead); 39753a5a1b3Sopenharmony_ci 39853a5a1b3Sopenharmony_ci e->dead = true; 39953a5a1b3Sopenharmony_ci e->mainloop->time_events_please_scan ++; 40053a5a1b3Sopenharmony_ci 40153a5a1b3Sopenharmony_ci if (e->enabled) { 40253a5a1b3Sopenharmony_ci pa_assert(e->mainloop->n_enabled_time_events > 0); 40353a5a1b3Sopenharmony_ci e->mainloop->n_enabled_time_events--; 40453a5a1b3Sopenharmony_ci e->enabled = false; 40553a5a1b3Sopenharmony_ci } 40653a5a1b3Sopenharmony_ci 40753a5a1b3Sopenharmony_ci if (e->mainloop->cached_next_time_event == e) 40853a5a1b3Sopenharmony_ci e->mainloop->cached_next_time_event = NULL; 40953a5a1b3Sopenharmony_ci 41053a5a1b3Sopenharmony_ci /* no wakeup needed here. Think about it! */ 41153a5a1b3Sopenharmony_ci} 41253a5a1b3Sopenharmony_ci 41353a5a1b3Sopenharmony_cistatic void mainloop_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t callback) { 41453a5a1b3Sopenharmony_ci pa_assert(e); 41553a5a1b3Sopenharmony_ci pa_assert(!e->dead); 41653a5a1b3Sopenharmony_ci 41753a5a1b3Sopenharmony_ci e->destroy_callback = callback; 41853a5a1b3Sopenharmony_ci} 41953a5a1b3Sopenharmony_ci 42053a5a1b3Sopenharmony_ci/* quit() */ 42153a5a1b3Sopenharmony_ci 42253a5a1b3Sopenharmony_cistatic void mainloop_quit(pa_mainloop_api *a, int retval) { 42353a5a1b3Sopenharmony_ci pa_mainloop *m; 42453a5a1b3Sopenharmony_ci 42553a5a1b3Sopenharmony_ci pa_assert(a); 42653a5a1b3Sopenharmony_ci pa_assert(a->userdata); 42753a5a1b3Sopenharmony_ci m = a->userdata; 42853a5a1b3Sopenharmony_ci pa_assert(a == &m->api); 42953a5a1b3Sopenharmony_ci 43053a5a1b3Sopenharmony_ci pa_mainloop_quit(m, retval); 43153a5a1b3Sopenharmony_ci} 43253a5a1b3Sopenharmony_ci 43353a5a1b3Sopenharmony_cistatic const pa_mainloop_api vtable = { 43453a5a1b3Sopenharmony_ci .userdata = NULL, 43553a5a1b3Sopenharmony_ci 43653a5a1b3Sopenharmony_ci .io_new = mainloop_io_new, 43753a5a1b3Sopenharmony_ci .io_enable = mainloop_io_enable, 43853a5a1b3Sopenharmony_ci .io_free = mainloop_io_free, 43953a5a1b3Sopenharmony_ci .io_set_destroy = mainloop_io_set_destroy, 44053a5a1b3Sopenharmony_ci 44153a5a1b3Sopenharmony_ci .time_new = mainloop_time_new, 44253a5a1b3Sopenharmony_ci .time_restart = mainloop_time_restart, 44353a5a1b3Sopenharmony_ci .time_free = mainloop_time_free, 44453a5a1b3Sopenharmony_ci .time_set_destroy = mainloop_time_set_destroy, 44553a5a1b3Sopenharmony_ci 44653a5a1b3Sopenharmony_ci .defer_new = mainloop_defer_new, 44753a5a1b3Sopenharmony_ci .defer_enable = mainloop_defer_enable, 44853a5a1b3Sopenharmony_ci .defer_free = mainloop_defer_free, 44953a5a1b3Sopenharmony_ci .defer_set_destroy = mainloop_defer_set_destroy, 45053a5a1b3Sopenharmony_ci 45153a5a1b3Sopenharmony_ci .quit = mainloop_quit, 45253a5a1b3Sopenharmony_ci}; 45353a5a1b3Sopenharmony_ci 45453a5a1b3Sopenharmony_cipa_mainloop *pa_mainloop_new(void) { 45553a5a1b3Sopenharmony_ci pa_mainloop *m; 45653a5a1b3Sopenharmony_ci 45753a5a1b3Sopenharmony_ci#ifdef OS_IS_WIN32 45853a5a1b3Sopenharmony_ci { 45953a5a1b3Sopenharmony_ci int r; 46053a5a1b3Sopenharmony_ci WSADATA data; 46153a5a1b3Sopenharmony_ci if ((r = WSAStartup(MAKEWORD(2, 0), &data))) { 46253a5a1b3Sopenharmony_ci pa_log_error("ERROR: cannot initialize Winsock2 (%d)", r); 46353a5a1b3Sopenharmony_ci return NULL; 46453a5a1b3Sopenharmony_ci } 46553a5a1b3Sopenharmony_ci } 46653a5a1b3Sopenharmony_ci#endif 46753a5a1b3Sopenharmony_ci 46853a5a1b3Sopenharmony_ci pa_init_i18n(); 46953a5a1b3Sopenharmony_ci 47053a5a1b3Sopenharmony_ci m = pa_xnew0(pa_mainloop, 1); 47153a5a1b3Sopenharmony_ci 47253a5a1b3Sopenharmony_ci if (pa_pipe_cloexec(m->wakeup_pipe) < 0) { 47353a5a1b3Sopenharmony_ci pa_log_error("ERROR: cannot create wakeup pipe"); 47453a5a1b3Sopenharmony_ci pa_xfree(m); 47553a5a1b3Sopenharmony_ci return NULL; 47653a5a1b3Sopenharmony_ci } 47753a5a1b3Sopenharmony_ci 47853a5a1b3Sopenharmony_ci pa_make_fd_nonblock(m->wakeup_pipe[0]); 47953a5a1b3Sopenharmony_ci pa_make_fd_nonblock(m->wakeup_pipe[1]); 48053a5a1b3Sopenharmony_ci 48153a5a1b3Sopenharmony_ci m->rebuild_pollfds = true; 48253a5a1b3Sopenharmony_ci 48353a5a1b3Sopenharmony_ci m->api = vtable; 48453a5a1b3Sopenharmony_ci m->api.userdata = m; 48553a5a1b3Sopenharmony_ci 48653a5a1b3Sopenharmony_ci m->state = STATE_PASSIVE; 48753a5a1b3Sopenharmony_ci 48853a5a1b3Sopenharmony_ci m->poll_func_ret = -1; 48953a5a1b3Sopenharmony_ci 49053a5a1b3Sopenharmony_ci return m; 49153a5a1b3Sopenharmony_ci} 49253a5a1b3Sopenharmony_ci 49353a5a1b3Sopenharmony_cistatic void cleanup_io_events(pa_mainloop *m, bool force) { 49453a5a1b3Sopenharmony_ci pa_io_event *e, *n; 49553a5a1b3Sopenharmony_ci 49653a5a1b3Sopenharmony_ci PA_LLIST_FOREACH_SAFE(e, n, m->io_events) { 49753a5a1b3Sopenharmony_ci 49853a5a1b3Sopenharmony_ci if (!force && m->io_events_please_scan <= 0) 49953a5a1b3Sopenharmony_ci break; 50053a5a1b3Sopenharmony_ci 50153a5a1b3Sopenharmony_ci if (force || e->dead) { 50253a5a1b3Sopenharmony_ci PA_LLIST_REMOVE(pa_io_event, m->io_events, e); 50353a5a1b3Sopenharmony_ci 50453a5a1b3Sopenharmony_ci if (e->dead) { 50553a5a1b3Sopenharmony_ci pa_assert(m->io_events_please_scan > 0); 50653a5a1b3Sopenharmony_ci m->io_events_please_scan--; 50753a5a1b3Sopenharmony_ci } 50853a5a1b3Sopenharmony_ci 50953a5a1b3Sopenharmony_ci if (e->destroy_callback) 51053a5a1b3Sopenharmony_ci e->destroy_callback(&m->api, e, e->userdata); 51153a5a1b3Sopenharmony_ci 51253a5a1b3Sopenharmony_ci pa_xfree(e); 51353a5a1b3Sopenharmony_ci 51453a5a1b3Sopenharmony_ci m->rebuild_pollfds = true; 51553a5a1b3Sopenharmony_ci } 51653a5a1b3Sopenharmony_ci } 51753a5a1b3Sopenharmony_ci 51853a5a1b3Sopenharmony_ci pa_assert(m->io_events_please_scan == 0); 51953a5a1b3Sopenharmony_ci} 52053a5a1b3Sopenharmony_ci 52153a5a1b3Sopenharmony_cistatic void cleanup_time_events(pa_mainloop *m, bool force) { 52253a5a1b3Sopenharmony_ci pa_time_event *e, *n; 52353a5a1b3Sopenharmony_ci 52453a5a1b3Sopenharmony_ci PA_LLIST_FOREACH_SAFE(e, n, m->time_events) { 52553a5a1b3Sopenharmony_ci 52653a5a1b3Sopenharmony_ci if (!force && m->time_events_please_scan <= 0) 52753a5a1b3Sopenharmony_ci break; 52853a5a1b3Sopenharmony_ci 52953a5a1b3Sopenharmony_ci if (force || e->dead) { 53053a5a1b3Sopenharmony_ci PA_LLIST_REMOVE(pa_time_event, m->time_events, e); 53153a5a1b3Sopenharmony_ci 53253a5a1b3Sopenharmony_ci if (e->dead) { 53353a5a1b3Sopenharmony_ci pa_assert(m->time_events_please_scan > 0); 53453a5a1b3Sopenharmony_ci m->time_events_please_scan--; 53553a5a1b3Sopenharmony_ci } 53653a5a1b3Sopenharmony_ci 53753a5a1b3Sopenharmony_ci if (!e->dead && e->enabled) { 53853a5a1b3Sopenharmony_ci pa_assert(m->n_enabled_time_events > 0); 53953a5a1b3Sopenharmony_ci m->n_enabled_time_events--; 54053a5a1b3Sopenharmony_ci e->enabled = false; 54153a5a1b3Sopenharmony_ci } 54253a5a1b3Sopenharmony_ci 54353a5a1b3Sopenharmony_ci if (e->destroy_callback) 54453a5a1b3Sopenharmony_ci e->destroy_callback(&m->api, e, e->userdata); 54553a5a1b3Sopenharmony_ci 54653a5a1b3Sopenharmony_ci pa_xfree(e); 54753a5a1b3Sopenharmony_ci } 54853a5a1b3Sopenharmony_ci } 54953a5a1b3Sopenharmony_ci 55053a5a1b3Sopenharmony_ci pa_assert(m->time_events_please_scan == 0); 55153a5a1b3Sopenharmony_ci} 55253a5a1b3Sopenharmony_ci 55353a5a1b3Sopenharmony_cistatic void cleanup_defer_events(pa_mainloop *m, bool force) { 55453a5a1b3Sopenharmony_ci pa_defer_event *e, *n; 55553a5a1b3Sopenharmony_ci 55653a5a1b3Sopenharmony_ci PA_LLIST_FOREACH_SAFE(e, n, m->defer_events) { 55753a5a1b3Sopenharmony_ci 55853a5a1b3Sopenharmony_ci if (!force && m->defer_events_please_scan <= 0) 55953a5a1b3Sopenharmony_ci break; 56053a5a1b3Sopenharmony_ci 56153a5a1b3Sopenharmony_ci if (force || e->dead) { 56253a5a1b3Sopenharmony_ci PA_LLIST_REMOVE(pa_defer_event, m->defer_events, e); 56353a5a1b3Sopenharmony_ci 56453a5a1b3Sopenharmony_ci if (e->dead) { 56553a5a1b3Sopenharmony_ci pa_assert(m->defer_events_please_scan > 0); 56653a5a1b3Sopenharmony_ci m->defer_events_please_scan--; 56753a5a1b3Sopenharmony_ci } 56853a5a1b3Sopenharmony_ci 56953a5a1b3Sopenharmony_ci if (!e->dead && e->enabled) { 57053a5a1b3Sopenharmony_ci pa_assert(m->n_enabled_defer_events > 0); 57153a5a1b3Sopenharmony_ci m->n_enabled_defer_events--; 57253a5a1b3Sopenharmony_ci e->enabled = false; 57353a5a1b3Sopenharmony_ci } 57453a5a1b3Sopenharmony_ci 57553a5a1b3Sopenharmony_ci if (e->destroy_callback) 57653a5a1b3Sopenharmony_ci e->destroy_callback(&m->api, e, e->userdata); 57753a5a1b3Sopenharmony_ci 57853a5a1b3Sopenharmony_ci pa_xfree(e); 57953a5a1b3Sopenharmony_ci } 58053a5a1b3Sopenharmony_ci } 58153a5a1b3Sopenharmony_ci 58253a5a1b3Sopenharmony_ci pa_assert(m->defer_events_please_scan == 0); 58353a5a1b3Sopenharmony_ci} 58453a5a1b3Sopenharmony_ci 58553a5a1b3Sopenharmony_civoid pa_mainloop_free(pa_mainloop *m) { 58653a5a1b3Sopenharmony_ci pa_assert(m); 58753a5a1b3Sopenharmony_ci 58853a5a1b3Sopenharmony_ci cleanup_io_events(m, true); 58953a5a1b3Sopenharmony_ci cleanup_defer_events(m, true); 59053a5a1b3Sopenharmony_ci cleanup_time_events(m, true); 59153a5a1b3Sopenharmony_ci 59253a5a1b3Sopenharmony_ci pa_xfree(m->pollfds); 59353a5a1b3Sopenharmony_ci 59453a5a1b3Sopenharmony_ci pa_close_pipe(m->wakeup_pipe); 59553a5a1b3Sopenharmony_ci 59653a5a1b3Sopenharmony_ci pa_xfree(m); 59753a5a1b3Sopenharmony_ci 59853a5a1b3Sopenharmony_ci#ifdef OS_IS_WIN32 59953a5a1b3Sopenharmony_ci { 60053a5a1b3Sopenharmony_ci WSACleanup(); 60153a5a1b3Sopenharmony_ci } 60253a5a1b3Sopenharmony_ci#endif 60353a5a1b3Sopenharmony_ci} 60453a5a1b3Sopenharmony_ci 60553a5a1b3Sopenharmony_cistatic void scan_dead(pa_mainloop *m) { 60653a5a1b3Sopenharmony_ci pa_assert(m); 60753a5a1b3Sopenharmony_ci 60853a5a1b3Sopenharmony_ci if (m->io_events_please_scan) 60953a5a1b3Sopenharmony_ci cleanup_io_events(m, false); 61053a5a1b3Sopenharmony_ci 61153a5a1b3Sopenharmony_ci if (m->time_events_please_scan) 61253a5a1b3Sopenharmony_ci cleanup_time_events(m, false); 61353a5a1b3Sopenharmony_ci 61453a5a1b3Sopenharmony_ci if (m->defer_events_please_scan) 61553a5a1b3Sopenharmony_ci cleanup_defer_events(m, false); 61653a5a1b3Sopenharmony_ci} 61753a5a1b3Sopenharmony_ci 61853a5a1b3Sopenharmony_cistatic void rebuild_pollfds(pa_mainloop *m) { 61953a5a1b3Sopenharmony_ci pa_io_event*e; 62053a5a1b3Sopenharmony_ci struct pollfd *p; 62153a5a1b3Sopenharmony_ci unsigned l; 62253a5a1b3Sopenharmony_ci 62353a5a1b3Sopenharmony_ci l = m->n_io_events + 1; 62453a5a1b3Sopenharmony_ci if (m->max_pollfds < l) { 62553a5a1b3Sopenharmony_ci l *= 2; 62653a5a1b3Sopenharmony_ci m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l); 62753a5a1b3Sopenharmony_ci m->max_pollfds = l; 62853a5a1b3Sopenharmony_ci } 62953a5a1b3Sopenharmony_ci 63053a5a1b3Sopenharmony_ci m->n_pollfds = 0; 63153a5a1b3Sopenharmony_ci p = m->pollfds; 63253a5a1b3Sopenharmony_ci 63353a5a1b3Sopenharmony_ci m->pollfds[0].fd = m->wakeup_pipe[0]; 63453a5a1b3Sopenharmony_ci m->pollfds[0].events = POLLIN; 63553a5a1b3Sopenharmony_ci m->pollfds[0].revents = 0; 63653a5a1b3Sopenharmony_ci p++; 63753a5a1b3Sopenharmony_ci m->n_pollfds++; 63853a5a1b3Sopenharmony_ci 63953a5a1b3Sopenharmony_ci PA_LLIST_FOREACH(e, m->io_events) { 64053a5a1b3Sopenharmony_ci if (e->dead) { 64153a5a1b3Sopenharmony_ci e->pollfd = NULL; 64253a5a1b3Sopenharmony_ci continue; 64353a5a1b3Sopenharmony_ci } 64453a5a1b3Sopenharmony_ci 64553a5a1b3Sopenharmony_ci e->pollfd = p; 64653a5a1b3Sopenharmony_ci p->fd = e->fd; 64753a5a1b3Sopenharmony_ci p->events = map_flags_to_libc(e->events); 64853a5a1b3Sopenharmony_ci p->revents = 0; 64953a5a1b3Sopenharmony_ci 65053a5a1b3Sopenharmony_ci p++; 65153a5a1b3Sopenharmony_ci m->n_pollfds++; 65253a5a1b3Sopenharmony_ci } 65353a5a1b3Sopenharmony_ci 65453a5a1b3Sopenharmony_ci m->rebuild_pollfds = false; 65553a5a1b3Sopenharmony_ci} 65653a5a1b3Sopenharmony_ci 65753a5a1b3Sopenharmony_cistatic unsigned dispatch_pollfds(pa_mainloop *m) { 65853a5a1b3Sopenharmony_ci pa_io_event *e; 65953a5a1b3Sopenharmony_ci unsigned r = 0, k; 66053a5a1b3Sopenharmony_ci 66153a5a1b3Sopenharmony_ci pa_assert(m->poll_func_ret > 0); 66253a5a1b3Sopenharmony_ci 66353a5a1b3Sopenharmony_ci k = m->poll_func_ret; 66453a5a1b3Sopenharmony_ci 66553a5a1b3Sopenharmony_ci PA_LLIST_FOREACH(e, m->io_events) { 66653a5a1b3Sopenharmony_ci 66753a5a1b3Sopenharmony_ci if (k <= 0 || m->quit) 66853a5a1b3Sopenharmony_ci break; 66953a5a1b3Sopenharmony_ci 67053a5a1b3Sopenharmony_ci if (e->dead || !e->pollfd || !e->pollfd->revents) 67153a5a1b3Sopenharmony_ci continue; 67253a5a1b3Sopenharmony_ci 67353a5a1b3Sopenharmony_ci pa_assert(e->pollfd->fd == e->fd); 67453a5a1b3Sopenharmony_ci pa_assert(e->callback); 67553a5a1b3Sopenharmony_ci 67653a5a1b3Sopenharmony_ci e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata); 67753a5a1b3Sopenharmony_ci e->pollfd->revents = 0; 67853a5a1b3Sopenharmony_ci r++; 67953a5a1b3Sopenharmony_ci k--; 68053a5a1b3Sopenharmony_ci } 68153a5a1b3Sopenharmony_ci 68253a5a1b3Sopenharmony_ci return r; 68353a5a1b3Sopenharmony_ci} 68453a5a1b3Sopenharmony_ci 68553a5a1b3Sopenharmony_cistatic unsigned dispatch_defer(pa_mainloop *m) { 68653a5a1b3Sopenharmony_ci pa_defer_event *e; 68753a5a1b3Sopenharmony_ci unsigned r = 0; 68853a5a1b3Sopenharmony_ci 68953a5a1b3Sopenharmony_ci if (m->n_enabled_defer_events <= 0) 69053a5a1b3Sopenharmony_ci return 0; 69153a5a1b3Sopenharmony_ci 69253a5a1b3Sopenharmony_ci PA_LLIST_FOREACH(e, m->defer_events) { 69353a5a1b3Sopenharmony_ci 69453a5a1b3Sopenharmony_ci if (m->quit) 69553a5a1b3Sopenharmony_ci break; 69653a5a1b3Sopenharmony_ci 69753a5a1b3Sopenharmony_ci if (e->dead || !e->enabled) 69853a5a1b3Sopenharmony_ci continue; 69953a5a1b3Sopenharmony_ci 70053a5a1b3Sopenharmony_ci pa_assert(e->callback); 70153a5a1b3Sopenharmony_ci e->callback(&m->api, e, e->userdata); 70253a5a1b3Sopenharmony_ci r++; 70353a5a1b3Sopenharmony_ci } 70453a5a1b3Sopenharmony_ci 70553a5a1b3Sopenharmony_ci return r; 70653a5a1b3Sopenharmony_ci} 70753a5a1b3Sopenharmony_ci 70853a5a1b3Sopenharmony_cistatic pa_time_event* find_next_time_event(pa_mainloop *m) { 70953a5a1b3Sopenharmony_ci pa_time_event *t, *n = NULL; 71053a5a1b3Sopenharmony_ci pa_assert(m); 71153a5a1b3Sopenharmony_ci 71253a5a1b3Sopenharmony_ci if (m->cached_next_time_event) 71353a5a1b3Sopenharmony_ci return m->cached_next_time_event; 71453a5a1b3Sopenharmony_ci 71553a5a1b3Sopenharmony_ci PA_LLIST_FOREACH(t, m->time_events) { 71653a5a1b3Sopenharmony_ci 71753a5a1b3Sopenharmony_ci if (t->dead || !t->enabled) 71853a5a1b3Sopenharmony_ci continue; 71953a5a1b3Sopenharmony_ci 72053a5a1b3Sopenharmony_ci if (!n || t->time < n->time) { 72153a5a1b3Sopenharmony_ci n = t; 72253a5a1b3Sopenharmony_ci 72353a5a1b3Sopenharmony_ci /* Shortcut for time == 0 */ 72453a5a1b3Sopenharmony_ci if (n->time == 0) 72553a5a1b3Sopenharmony_ci break; 72653a5a1b3Sopenharmony_ci } 72753a5a1b3Sopenharmony_ci } 72853a5a1b3Sopenharmony_ci 72953a5a1b3Sopenharmony_ci m->cached_next_time_event = n; 73053a5a1b3Sopenharmony_ci return n; 73153a5a1b3Sopenharmony_ci} 73253a5a1b3Sopenharmony_ci 73353a5a1b3Sopenharmony_cistatic pa_usec_t calc_next_timeout(pa_mainloop *m) { 73453a5a1b3Sopenharmony_ci pa_time_event *t; 73553a5a1b3Sopenharmony_ci pa_usec_t clock_now; 73653a5a1b3Sopenharmony_ci 73753a5a1b3Sopenharmony_ci if (m->n_enabled_time_events <= 0) 73853a5a1b3Sopenharmony_ci return PA_USEC_INVALID; 73953a5a1b3Sopenharmony_ci 74053a5a1b3Sopenharmony_ci pa_assert_se(t = find_next_time_event(m)); 74153a5a1b3Sopenharmony_ci 74253a5a1b3Sopenharmony_ci if (t->time <= 0) 74353a5a1b3Sopenharmony_ci return 0; 74453a5a1b3Sopenharmony_ci 74553a5a1b3Sopenharmony_ci clock_now = pa_rtclock_now(); 74653a5a1b3Sopenharmony_ci 74753a5a1b3Sopenharmony_ci if (t->time <= clock_now) 74853a5a1b3Sopenharmony_ci return 0; 74953a5a1b3Sopenharmony_ci 75053a5a1b3Sopenharmony_ci return t->time - clock_now; 75153a5a1b3Sopenharmony_ci} 75253a5a1b3Sopenharmony_ci 75353a5a1b3Sopenharmony_cistatic unsigned dispatch_timeout(pa_mainloop *m) { 75453a5a1b3Sopenharmony_ci pa_time_event *e; 75553a5a1b3Sopenharmony_ci pa_usec_t now; 75653a5a1b3Sopenharmony_ci unsigned r = 0; 75753a5a1b3Sopenharmony_ci pa_assert(m); 75853a5a1b3Sopenharmony_ci 75953a5a1b3Sopenharmony_ci if (m->n_enabled_time_events <= 0) 76053a5a1b3Sopenharmony_ci return 0; 76153a5a1b3Sopenharmony_ci 76253a5a1b3Sopenharmony_ci now = pa_rtclock_now(); 76353a5a1b3Sopenharmony_ci 76453a5a1b3Sopenharmony_ci PA_LLIST_FOREACH(e, m->time_events) { 76553a5a1b3Sopenharmony_ci 76653a5a1b3Sopenharmony_ci if (m->quit) 76753a5a1b3Sopenharmony_ci break; 76853a5a1b3Sopenharmony_ci 76953a5a1b3Sopenharmony_ci if (e->dead || !e->enabled) 77053a5a1b3Sopenharmony_ci continue; 77153a5a1b3Sopenharmony_ci 77253a5a1b3Sopenharmony_ci if (e->time <= now) { 77353a5a1b3Sopenharmony_ci struct timeval tv; 77453a5a1b3Sopenharmony_ci pa_assert(e->callback); 77553a5a1b3Sopenharmony_ci 77653a5a1b3Sopenharmony_ci /* Disable time event */ 77753a5a1b3Sopenharmony_ci mainloop_time_restart(e, NULL); 77853a5a1b3Sopenharmony_ci 77953a5a1b3Sopenharmony_ci e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, e->use_rtclock), e->userdata); 78053a5a1b3Sopenharmony_ci 78153a5a1b3Sopenharmony_ci r++; 78253a5a1b3Sopenharmony_ci } 78353a5a1b3Sopenharmony_ci } 78453a5a1b3Sopenharmony_ci 78553a5a1b3Sopenharmony_ci return r; 78653a5a1b3Sopenharmony_ci} 78753a5a1b3Sopenharmony_ci 78853a5a1b3Sopenharmony_civoid pa_mainloop_wakeup(pa_mainloop *m) { 78953a5a1b3Sopenharmony_ci char c = 'W'; 79053a5a1b3Sopenharmony_ci pa_assert(m); 79153a5a1b3Sopenharmony_ci 79253a5a1b3Sopenharmony_ci if (pa_write(m->wakeup_pipe[1], &c, sizeof(c), &m->wakeup_pipe_type) < 0) 79353a5a1b3Sopenharmony_ci /* Not many options for recovering from the error. Let's at least log something. */ 79453a5a1b3Sopenharmony_ci pa_log("pa_write() failed while trying to wake up the mainloop: %s", pa_cstrerror(errno)); 79553a5a1b3Sopenharmony_ci} 79653a5a1b3Sopenharmony_ci 79753a5a1b3Sopenharmony_cistatic void clear_wakeup(pa_mainloop *m) { 79853a5a1b3Sopenharmony_ci char c[10]; 79953a5a1b3Sopenharmony_ci 80053a5a1b3Sopenharmony_ci pa_assert(m); 80153a5a1b3Sopenharmony_ci 80253a5a1b3Sopenharmony_ci while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c)) 80353a5a1b3Sopenharmony_ci ; 80453a5a1b3Sopenharmony_ci} 80553a5a1b3Sopenharmony_ci 80653a5a1b3Sopenharmony_ciint pa_mainloop_prepare(pa_mainloop *m, int timeout) { 80753a5a1b3Sopenharmony_ci pa_assert(m); 80853a5a1b3Sopenharmony_ci pa_assert(m->state == STATE_PASSIVE); 80953a5a1b3Sopenharmony_ci 81053a5a1b3Sopenharmony_ci clear_wakeup(m); 81153a5a1b3Sopenharmony_ci scan_dead(m); 81253a5a1b3Sopenharmony_ci 81353a5a1b3Sopenharmony_ci if (m->quit) 81453a5a1b3Sopenharmony_ci goto quit; 81553a5a1b3Sopenharmony_ci 81653a5a1b3Sopenharmony_ci if (m->n_enabled_defer_events <= 0) { 81753a5a1b3Sopenharmony_ci 81853a5a1b3Sopenharmony_ci if (m->rebuild_pollfds) 81953a5a1b3Sopenharmony_ci rebuild_pollfds(m); 82053a5a1b3Sopenharmony_ci 82153a5a1b3Sopenharmony_ci m->prepared_timeout = calc_next_timeout(m); 82253a5a1b3Sopenharmony_ci if (timeout >= 0) { 82353a5a1b3Sopenharmony_ci if (timeout < m->prepared_timeout || m->prepared_timeout == PA_USEC_INVALID) 82453a5a1b3Sopenharmony_ci m->prepared_timeout = timeout; 82553a5a1b3Sopenharmony_ci } 82653a5a1b3Sopenharmony_ci } 82753a5a1b3Sopenharmony_ci 82853a5a1b3Sopenharmony_ci m->state = STATE_PREPARED; 82953a5a1b3Sopenharmony_ci return 0; 83053a5a1b3Sopenharmony_ci 83153a5a1b3Sopenharmony_ciquit: 83253a5a1b3Sopenharmony_ci m->state = STATE_QUIT; 83353a5a1b3Sopenharmony_ci return -2; 83453a5a1b3Sopenharmony_ci} 83553a5a1b3Sopenharmony_ci 83653a5a1b3Sopenharmony_cistatic int usec_to_timeout(pa_usec_t u) { 83753a5a1b3Sopenharmony_ci int timeout; 83853a5a1b3Sopenharmony_ci 83953a5a1b3Sopenharmony_ci if (u == PA_USEC_INVALID) 84053a5a1b3Sopenharmony_ci return -1; 84153a5a1b3Sopenharmony_ci 84253a5a1b3Sopenharmony_ci timeout = (u + PA_USEC_PER_MSEC - 1) / PA_USEC_PER_MSEC; 84353a5a1b3Sopenharmony_ci pa_assert(timeout >= 0); 84453a5a1b3Sopenharmony_ci 84553a5a1b3Sopenharmony_ci return timeout; 84653a5a1b3Sopenharmony_ci} 84753a5a1b3Sopenharmony_ci 84853a5a1b3Sopenharmony_ciint pa_mainloop_poll(pa_mainloop *m) { 84953a5a1b3Sopenharmony_ci pa_assert(m); 85053a5a1b3Sopenharmony_ci pa_assert(m->state == STATE_PREPARED); 85153a5a1b3Sopenharmony_ci 85253a5a1b3Sopenharmony_ci if (m->quit) 85353a5a1b3Sopenharmony_ci goto quit; 85453a5a1b3Sopenharmony_ci 85553a5a1b3Sopenharmony_ci m->state = STATE_POLLING; 85653a5a1b3Sopenharmony_ci 85753a5a1b3Sopenharmony_ci if (m->n_enabled_defer_events) 85853a5a1b3Sopenharmony_ci m->poll_func_ret = 0; 85953a5a1b3Sopenharmony_ci else { 86053a5a1b3Sopenharmony_ci pa_assert(!m->rebuild_pollfds); 86153a5a1b3Sopenharmony_ci 86253a5a1b3Sopenharmony_ci if (m->poll_func) 86353a5a1b3Sopenharmony_ci m->poll_func_ret = m->poll_func( 86453a5a1b3Sopenharmony_ci m->pollfds, m->n_pollfds, 86553a5a1b3Sopenharmony_ci usec_to_timeout(m->prepared_timeout), 86653a5a1b3Sopenharmony_ci m->poll_func_userdata); 86753a5a1b3Sopenharmony_ci else { 86853a5a1b3Sopenharmony_ci#ifdef HAVE_PPOLL 86953a5a1b3Sopenharmony_ci struct timespec ts; 87053a5a1b3Sopenharmony_ci 87153a5a1b3Sopenharmony_ci m->poll_func_ret = ppoll( 87253a5a1b3Sopenharmony_ci m->pollfds, m->n_pollfds, 87353a5a1b3Sopenharmony_ci m->prepared_timeout == PA_USEC_INVALID ? NULL : pa_timespec_store(&ts, m->prepared_timeout), 87453a5a1b3Sopenharmony_ci NULL); 87553a5a1b3Sopenharmony_ci#else 87653a5a1b3Sopenharmony_ci m->poll_func_ret = pa_poll( 87753a5a1b3Sopenharmony_ci m->pollfds, m->n_pollfds, 87853a5a1b3Sopenharmony_ci usec_to_timeout(m->prepared_timeout)); 87953a5a1b3Sopenharmony_ci#endif 88053a5a1b3Sopenharmony_ci } 88153a5a1b3Sopenharmony_ci 88253a5a1b3Sopenharmony_ci if (m->poll_func_ret < 0) { 88353a5a1b3Sopenharmony_ci if (errno == EINTR) 88453a5a1b3Sopenharmony_ci m->poll_func_ret = 0; 88553a5a1b3Sopenharmony_ci else 88653a5a1b3Sopenharmony_ci pa_log("poll(): %s", pa_cstrerror(errno)); 88753a5a1b3Sopenharmony_ci } 88853a5a1b3Sopenharmony_ci } 88953a5a1b3Sopenharmony_ci 89053a5a1b3Sopenharmony_ci m->state = m->poll_func_ret < 0 ? STATE_PASSIVE : STATE_POLLED; 89153a5a1b3Sopenharmony_ci return m->poll_func_ret; 89253a5a1b3Sopenharmony_ci 89353a5a1b3Sopenharmony_ciquit: 89453a5a1b3Sopenharmony_ci m->state = STATE_QUIT; 89553a5a1b3Sopenharmony_ci return -2; 89653a5a1b3Sopenharmony_ci} 89753a5a1b3Sopenharmony_ci 89853a5a1b3Sopenharmony_ciint pa_mainloop_dispatch(pa_mainloop *m) { 89953a5a1b3Sopenharmony_ci unsigned dispatched = 0; 90053a5a1b3Sopenharmony_ci 90153a5a1b3Sopenharmony_ci pa_assert(m); 90253a5a1b3Sopenharmony_ci pa_assert(m->state == STATE_POLLED); 90353a5a1b3Sopenharmony_ci 90453a5a1b3Sopenharmony_ci if (m->quit) 90553a5a1b3Sopenharmony_ci goto quit; 90653a5a1b3Sopenharmony_ci 90753a5a1b3Sopenharmony_ci if (m->n_enabled_defer_events) 90853a5a1b3Sopenharmony_ci dispatched += dispatch_defer(m); 90953a5a1b3Sopenharmony_ci else { 91053a5a1b3Sopenharmony_ci if (m->n_enabled_time_events) 91153a5a1b3Sopenharmony_ci dispatched += dispatch_timeout(m); 91253a5a1b3Sopenharmony_ci 91353a5a1b3Sopenharmony_ci if (m->quit) 91453a5a1b3Sopenharmony_ci goto quit; 91553a5a1b3Sopenharmony_ci 91653a5a1b3Sopenharmony_ci if (m->poll_func_ret > 0) 91753a5a1b3Sopenharmony_ci dispatched += dispatch_pollfds(m); 91853a5a1b3Sopenharmony_ci } 91953a5a1b3Sopenharmony_ci 92053a5a1b3Sopenharmony_ci if (m->quit) 92153a5a1b3Sopenharmony_ci goto quit; 92253a5a1b3Sopenharmony_ci 92353a5a1b3Sopenharmony_ci m->state = STATE_PASSIVE; 92453a5a1b3Sopenharmony_ci 92553a5a1b3Sopenharmony_ci return (int) dispatched; 92653a5a1b3Sopenharmony_ci 92753a5a1b3Sopenharmony_ciquit: 92853a5a1b3Sopenharmony_ci m->state = STATE_QUIT; 92953a5a1b3Sopenharmony_ci return -2; 93053a5a1b3Sopenharmony_ci} 93153a5a1b3Sopenharmony_ci 93253a5a1b3Sopenharmony_ciint pa_mainloop_get_retval(const pa_mainloop *m) { 93353a5a1b3Sopenharmony_ci pa_assert(m); 93453a5a1b3Sopenharmony_ci 93553a5a1b3Sopenharmony_ci return m->retval; 93653a5a1b3Sopenharmony_ci} 93753a5a1b3Sopenharmony_ci 93853a5a1b3Sopenharmony_ciint pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) { 93953a5a1b3Sopenharmony_ci int r; 94053a5a1b3Sopenharmony_ci pa_assert(m); 94153a5a1b3Sopenharmony_ci 94253a5a1b3Sopenharmony_ci if ((r = pa_mainloop_prepare(m, block ? -1 : 0)) < 0) 94353a5a1b3Sopenharmony_ci goto quit; 94453a5a1b3Sopenharmony_ci 94553a5a1b3Sopenharmony_ci if ((r = pa_mainloop_poll(m)) < 0) 94653a5a1b3Sopenharmony_ci goto quit; 94753a5a1b3Sopenharmony_ci 94853a5a1b3Sopenharmony_ci if ((r = pa_mainloop_dispatch(m)) < 0) 94953a5a1b3Sopenharmony_ci goto quit; 95053a5a1b3Sopenharmony_ci 95153a5a1b3Sopenharmony_ci return r; 95253a5a1b3Sopenharmony_ci 95353a5a1b3Sopenharmony_ciquit: 95453a5a1b3Sopenharmony_ci 95553a5a1b3Sopenharmony_ci if ((r == -2) && retval) 95653a5a1b3Sopenharmony_ci *retval = pa_mainloop_get_retval(m); 95753a5a1b3Sopenharmony_ci return r; 95853a5a1b3Sopenharmony_ci} 95953a5a1b3Sopenharmony_ci 96053a5a1b3Sopenharmony_ciint pa_mainloop_run(pa_mainloop *m, int *retval) { 96153a5a1b3Sopenharmony_ci int r; 96253a5a1b3Sopenharmony_ci 96353a5a1b3Sopenharmony_ci while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0) 96453a5a1b3Sopenharmony_ci ; 96553a5a1b3Sopenharmony_ci 96653a5a1b3Sopenharmony_ci if (r == -2) { 96753a5a1b3Sopenharmony_ci pa_log_error("mainloop exit with code -2"); 96853a5a1b3Sopenharmony_ci return 1; 96953a5a1b3Sopenharmony_ci } else { 97053a5a1b3Sopenharmony_ci pa_log_error("mainloop exit with code -1"); 97153a5a1b3Sopenharmony_ci return -1; 97253a5a1b3Sopenharmony_ci } 97353a5a1b3Sopenharmony_ci} 97453a5a1b3Sopenharmony_ci 97553a5a1b3Sopenharmony_civoid pa_mainloop_quit(pa_mainloop *m, int retval) { 97653a5a1b3Sopenharmony_ci pa_assert(m); 97753a5a1b3Sopenharmony_ci 97853a5a1b3Sopenharmony_ci m->quit = true; 97953a5a1b3Sopenharmony_ci m->retval = retval; 98053a5a1b3Sopenharmony_ci pa_mainloop_wakeup(m); 98153a5a1b3Sopenharmony_ci} 98253a5a1b3Sopenharmony_ci 98353a5a1b3Sopenharmony_cipa_mainloop_api* pa_mainloop_get_api(pa_mainloop *m) { 98453a5a1b3Sopenharmony_ci pa_assert(m); 98553a5a1b3Sopenharmony_ci 98653a5a1b3Sopenharmony_ci return &m->api; 98753a5a1b3Sopenharmony_ci} 98853a5a1b3Sopenharmony_ci 98953a5a1b3Sopenharmony_civoid pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) { 99053a5a1b3Sopenharmony_ci pa_assert(m); 99153a5a1b3Sopenharmony_ci 99253a5a1b3Sopenharmony_ci m->poll_func = poll_func; 99353a5a1b3Sopenharmony_ci m->poll_func_userdata = userdata; 99453a5a1b3Sopenharmony_ci} 99553a5a1b3Sopenharmony_ci 99653a5a1b3Sopenharmony_cibool pa_mainloop_is_our_api(const pa_mainloop_api *m) { 99753a5a1b3Sopenharmony_ci pa_assert(m); 99853a5a1b3Sopenharmony_ci 99953a5a1b3Sopenharmony_ci return m->io_new == mainloop_io_new; 100053a5a1b3Sopenharmony_ci} 1001