X-Git-Url: https://code.delx.au/pulseaudio/blobdiff_plain/63c1eb14d889fe052afad16dfc470802cc48bb4a..d000dd6f4b976894558613f69bdad2974cce7d1e:/src/pulse/mainloop.c?ds=sidebyside diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c index aaed3caf..93a4742d 100644 --- a/src/pulse/mainloop.c +++ b/src/pulse/mainloop.c @@ -6,7 +6,7 @@ PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, + by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. PulseAudio is distributed in the hope that it will be useful, but @@ -42,9 +42,12 @@ #include #endif +#include +#include #include #include +#include #include #include #include @@ -53,10 +56,11 @@ #include #include "mainloop.h" +#include "internal.h" struct pa_io_event { pa_mainloop *mainloop; - int dead; + pa_bool_t dead:1; int fd; pa_io_event_flags_t events; @@ -71,10 +75,10 @@ struct pa_io_event { struct pa_time_event { pa_mainloop *mainloop; - int dead; + pa_bool_t dead:1; - int enabled; - struct timeval timeval; + pa_bool_t enabled:1; + pa_usec_t time; pa_time_event_cb_t callback; void *userdata; @@ -85,9 +89,9 @@ struct pa_time_event { struct pa_defer_event { pa_mainloop *mainloop; - int dead; + pa_bool_t dead:1; - int enabled; + pa_bool_t enabled:1; pa_defer_event_cb_t callback; void *userdata; @@ -101,22 +105,24 @@ struct pa_mainloop { PA_LLIST_HEAD(pa_time_event, time_events); PA_LLIST_HEAD(pa_defer_event, defer_events); - int n_enabled_defer_events, n_enabled_time_events, n_io_events; - int io_events_please_scan, time_events_please_scan, defer_events_please_scan; + unsigned n_enabled_defer_events, n_enabled_time_events, n_io_events; + unsigned io_events_please_scan, time_events_please_scan, defer_events_please_scan; + pa_bool_t rebuild_pollfds:1; struct pollfd *pollfds; unsigned max_pollfds, n_pollfds; - int rebuild_pollfds; int prepared_timeout; pa_time_event *cached_next_time_event; - int quit, retval; pa_mainloop_api api; + int retval; + pa_bool_t quit:1; + + pa_bool_t wakeup_requested:1; int wakeup_pipe[2]; int wakeup_pipe_type; - int wakeup_requested; enum { STATE_PASSIVE, @@ -132,11 +138,11 @@ struct pa_mainloop { }; static short map_flags_to_libc(pa_io_event_flags_t flags) { - return - (flags & PA_IO_EVENT_INPUT ? POLLIN : 0) | - (flags & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) | - (flags & PA_IO_EVENT_ERROR ? POLLERR : 0) | - (flags & PA_IO_EVENT_HANGUP ? POLLHUP : 0); + return (short) + ((flags & PA_IO_EVENT_INPUT ? POLLIN : 0) | + (flags & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) | + (flags & PA_IO_EVENT_ERROR ? POLLERR : 0) | + (flags & PA_IO_EVENT_HANGUP ? POLLHUP : 0)); } static pa_io_event_flags_t map_flags_from_libc(short flags) { @@ -168,7 +174,7 @@ static pa_io_event* mainloop_io_new( e = pa_xnew(pa_io_event, 1); e->mainloop = m; - e->dead = 0; + e->dead = FALSE; e->fd = fd; e->events = events; @@ -193,13 +199,13 @@ static pa_io_event* mainloop_io_new( SELECT_TYPE_ARG5 &tv) == -1) && (WSAGetLastError() == WSAENOTSOCK)) { pa_log_warn("Cannot monitor non-socket file descriptors."); - e->dead = 1; + e->dead = TRUE; } } #endif PA_LLIST_PREPEND(pa_io_event, m->io_events, e); - m->rebuild_pollfds = 1; + m->rebuild_pollfds = TRUE; m->n_io_events ++; pa_mainloop_wakeup(m); @@ -219,7 +225,7 @@ static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) { if (e->pollfd) e->pollfd->events = map_flags_to_libc(events); else - e->mainloop->rebuild_pollfds = 1; + e->mainloop->rebuild_pollfds = TRUE; pa_mainloop_wakeup(e->mainloop); } @@ -228,11 +234,11 @@ static void mainloop_io_free(pa_io_event *e) { pa_assert(e); pa_assert(!e->dead); - e->dead = 1; + e->dead = TRUE; e->mainloop->io_events_please_scan ++; e->mainloop->n_io_events --; - e->mainloop->rebuild_pollfds = 1; + e->mainloop->rebuild_pollfds = TRUE; pa_mainloop_wakeup(e->mainloop); } @@ -261,9 +267,9 @@ static pa_defer_event* mainloop_defer_new( e = pa_xnew(pa_defer_event, 1); e->mainloop = m; - e->dead = 0; + e->dead = FALSE; - e->enabled = 1; + e->enabled = TRUE; m->n_enabled_defer_events++; e->callback = callback; @@ -296,13 +302,13 @@ static void mainloop_defer_free(pa_defer_event *e) { pa_assert(e); pa_assert(!e->dead); - e->dead = 1; + e->dead = TRUE; e->mainloop->defer_events_please_scan ++; if (e->enabled) { pa_assert(e->mainloop->n_enabled_defer_events > 0); e->mainloop->n_enabled_defer_events--; - e->enabled = 0; + e->enabled = FALSE; } } @@ -314,6 +320,23 @@ static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy } /* Time events */ +static pa_usec_t timeval_load(const struct timeval *tv) { + pa_bool_t is_rtclock; + struct timeval ttv; + + if (!tv) + return PA_USEC_INVALID; + + ttv = *tv; + is_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK); + ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK; + + if (!is_rtclock) + pa_rtclock_from_wallclock(&ttv); + + return pa_timeval_load(&ttv); +} + static pa_time_event* mainloop_time_new( pa_mainloop_api*a, const struct timeval *tv, @@ -322,27 +345,30 @@ static pa_time_event* mainloop_time_new( pa_mainloop *m; pa_time_event *e; + pa_usec_t t; pa_assert(a); pa_assert(a->userdata); pa_assert(callback); + t = timeval_load(tv); + m = a->userdata; pa_assert(a == &m->api); e = pa_xnew(pa_time_event, 1); e->mainloop = m; - e->dead = 0; + e->dead = FALSE; - if ((e->enabled = !!tv)) { - e->timeval = *tv; + if ((e->enabled = (t != PA_USEC_INVALID))) { + e->time = t; m->n_enabled_time_events++; if (m->cached_next_time_event) { pa_assert(m->cached_next_time_event->enabled); - if (pa_timeval_cmp(tv, &m->cached_next_time_event->timeval) < 0) + if (t < m->cached_next_time_event->time) m->cached_next_time_event = e; } } @@ -360,24 +386,30 @@ static pa_time_event* mainloop_time_new( } static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { + pa_bool_t valid; + pa_usec_t t; + pa_assert(e); pa_assert(!e->dead); - if (e->enabled && !tv) { + t = timeval_load(tv); + + valid = (t != PA_USEC_INVALID); + if (e->enabled && !valid) { pa_assert(e->mainloop->n_enabled_time_events > 0); e->mainloop->n_enabled_time_events--; - } else if (!e->enabled && tv) + } else if (!e->enabled && valid) e->mainloop->n_enabled_time_events++; - if ((e->enabled = !!tv)) { - e->timeval = *tv; + if ((e->enabled = valid)) { + e->time = t; pa_mainloop_wakeup(e->mainloop); } if (e->mainloop->cached_next_time_event && e->enabled) { pa_assert(e->mainloop->cached_next_time_event->enabled); - if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0) + if (t < e->mainloop->cached_next_time_event->time) e->mainloop->cached_next_time_event = e; } else if (e->mainloop->cached_next_time_event == e) e->mainloop->cached_next_time_event = NULL; @@ -387,13 +419,13 @@ static void mainloop_time_free(pa_time_event *e) { pa_assert(e); pa_assert(!e->dead); - e->dead = 1; + e->dead = TRUE; e->mainloop->time_events_please_scan ++; if (e->enabled) { pa_assert(e->mainloop->n_enabled_time_events > 0); e->mainloop->n_enabled_time_events--; - e->enabled = 0; + e->enabled = FALSE; } if (e->mainloop->cached_next_time_event == e) @@ -425,10 +457,10 @@ static void mainloop_quit(pa_mainloop_api*a, int retval) { static const pa_mainloop_api vtable = { .userdata = NULL, - .io_new= mainloop_io_new, - .io_enable= mainloop_io_enable, - .io_free= mainloop_io_free, - .io_set_destroy= mainloop_io_set_destroy, + .io_new = mainloop_io_new, + .io_enable = mainloop_io_enable, + .io_free = mainloop_io_free, + .io_set_destroy = mainloop_io_set_destroy, .time_new = mainloop_time_new, .time_restart = mainloop_time_restart, @@ -446,6 +478,8 @@ static const pa_mainloop_api vtable = { pa_mainloop *pa_mainloop_new(void) { pa_mainloop *m; + pa_init_i18n(); + m = pa_xnew(pa_mainloop, 1); m->wakeup_pipe_type = 0; @@ -459,7 +493,7 @@ pa_mainloop *pa_mainloop_new(void) { pa_make_fd_nonblock(m->wakeup_pipe[1]); pa_make_fd_cloexec(m->wakeup_pipe[0]); pa_make_fd_cloexec(m->wakeup_pipe[1]); - m->wakeup_requested = 0; + m->wakeup_requested = FALSE; PA_LLIST_HEAD_INIT(pa_io_event, m->io_events); PA_LLIST_HEAD_INIT(pa_time_event, m->time_events); @@ -473,9 +507,10 @@ pa_mainloop *pa_mainloop_new(void) { m->pollfds = NULL; m->max_pollfds = m->n_pollfds = 0; - m->rebuild_pollfds = 1; + m->rebuild_pollfds = TRUE; - m->quit = m->retval = 0; + m->quit = FALSE; + m->retval = 0; m->api = vtable; m->api.userdata = m; @@ -489,7 +524,7 @@ pa_mainloop *pa_mainloop_new(void) { return m; } -static void cleanup_io_events(pa_mainloop *m, int force) { +static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) { pa_io_event *e; e = m->io_events; @@ -512,7 +547,7 @@ static void cleanup_io_events(pa_mainloop *m, int force) { pa_xfree(e); - m->rebuild_pollfds = 1; + m->rebuild_pollfds = TRUE; } e = n; @@ -521,7 +556,7 @@ static void cleanup_io_events(pa_mainloop *m, int force) { pa_assert(m->io_events_please_scan == 0); } -static void cleanup_time_events(pa_mainloop *m, int force) { +static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) { pa_time_event *e; e = m->time_events; @@ -542,7 +577,7 @@ static void cleanup_time_events(pa_mainloop *m, int force) { if (!e->dead && e->enabled) { pa_assert(m->n_enabled_time_events > 0); m->n_enabled_time_events--; - e->enabled = 0; + e->enabled = FALSE; } if (e->destroy_callback) @@ -557,7 +592,7 @@ static void cleanup_time_events(pa_mainloop *m, int force) { pa_assert(m->time_events_please_scan == 0); } -static void cleanup_defer_events(pa_mainloop *m, int force) { +static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) { pa_defer_event *e; e = m->defer_events; @@ -578,7 +613,7 @@ static void cleanup_defer_events(pa_mainloop *m, int force) { if (!e->dead && e->enabled) { pa_assert(m->n_enabled_defer_events > 0); m->n_enabled_defer_events--; - e->enabled = 0; + e->enabled = FALSE; } if (e->destroy_callback) @@ -597,9 +632,9 @@ static void cleanup_defer_events(pa_mainloop *m, int force) { void pa_mainloop_free(pa_mainloop* m) { pa_assert(m); - cleanup_io_events(m, 1); - cleanup_defer_events(m, 1); - cleanup_time_events(m, 1); + cleanup_io_events(m, TRUE); + cleanup_defer_events(m, TRUE); + cleanup_time_events(m, TRUE); pa_xfree(m->pollfds); @@ -612,13 +647,13 @@ static void scan_dead(pa_mainloop *m) { pa_assert(m); if (m->io_events_please_scan) - cleanup_io_events(m, 0); + cleanup_io_events(m, FALSE); if (m->time_events_please_scan) - cleanup_time_events(m, 0); + cleanup_time_events(m, FALSE); if (m->defer_events_please_scan) - cleanup_defer_events(m, 0); + cleanup_defer_events(m, FALSE); } static void rebuild_pollfds(pa_mainloop *m) { @@ -659,7 +694,7 @@ static void rebuild_pollfds(pa_mainloop *m) { m->n_pollfds++; } - m->rebuild_pollfds = 0; + m->rebuild_pollfds = FALSE; } static int dispatch_pollfds(pa_mainloop *m) { @@ -715,11 +750,11 @@ static pa_time_event* find_next_time_event(pa_mainloop *m) { if (t->dead || !t->enabled) continue; - if (!n || pa_timeval_cmp(&t->timeval, &n->timeval) < 0) { + if (!n || t->time < n->time) { n = t; - /* Shortcut for tv = { 0, 0 } */ - if (n->timeval.tv_sec <= 0) + /* Shortcut for time == 0 */ + if (n->time == 0) break; } } @@ -730,50 +765,48 @@ static pa_time_event* find_next_time_event(pa_mainloop *m) { static int calc_next_timeout(pa_mainloop *m) { pa_time_event *t; - struct timeval now; - pa_usec_t usec; + pa_usec_t clock_now; if (!m->n_enabled_time_events) return -1; - t = find_next_time_event(m); - pa_assert(t); + pa_assert_se(t = find_next_time_event(m)); - if (t->timeval.tv_sec <= 0) + if (t->time <= 0) return 0; - pa_gettimeofday(&now); + clock_now = pa_rtclock_now(); - if (pa_timeval_cmp(&t->timeval, &now) <= 0) + if (t->time <= clock_now) return 0; - usec = pa_timeval_diff(&t->timeval, &now); - return (int) (usec / 1000); + return (int) ((t->time - clock_now) / 1000); /* in milliseconds */ } static int dispatch_timeout(pa_mainloop *m) { pa_time_event *e; - struct timeval now; + pa_usec_t now; int r = 0; pa_assert(m); if (m->n_enabled_time_events <= 0) return 0; - pa_gettimeofday(&now); + now = pa_rtclock_now(); for (e = m->time_events; e && !m->quit; e = e->next) { if (e->dead || !e->enabled) continue; - if (pa_timeval_cmp(&e->timeval, &now) <= 0) { + if (e->time <= now) { + struct timeval tv; pa_assert(e->callback); /* Disable time event */ mainloop_time_restart(e, NULL); - e->callback(&m->api, e, &e->timeval, e->userdata); + e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, TRUE), e->userdata); r++; } @@ -945,7 +978,7 @@ int pa_mainloop_run(pa_mainloop *m, int *retval) { void pa_mainloop_quit(pa_mainloop *m, int retval) { pa_assert(m); - m->quit = 1; + m->quit = TRUE; m->retval = retval; pa_mainloop_wakeup(m); } @@ -961,3 +994,9 @@ void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *use m->poll_func = poll_func; m->poll_func_userdata = userdata; } + +pa_bool_t pa_mainloop_is_our_api(pa_mainloop_api*m) { + pa_assert(m); + + return m->io_new == mainloop_io_new; +}