diff options
Diffstat (limited to 'src/pulse/glib-mainloop.c')
| -rw-r--r-- | src/pulse/glib-mainloop.c | 247 |
1 files changed, 134 insertions, 113 deletions
diff --git a/src/pulse/glib-mainloop.c b/src/pulse/glib-mainloop.c index cdaecdf8..35c9c6a2 100644 --- a/src/pulse/glib-mainloop.c +++ b/src/pulse/glib-mainloop.c @@ -1,18 +1,18 @@ -/* $Id$ */ - /*** This file is part of PulseAudio. - + + Copyright 2004-2006 Lennart Poettering + 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 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -23,12 +23,9 @@ #include <config.h> #endif -#include <assert.h> - #include <pulse/xmalloc.h> #include <pulse/timeval.h> -#include <pulsecore/idxset.h> #include <pulsecore/core-util.h> #include <pulsecore/log.h> #include <pulsecore/llist.h> @@ -36,7 +33,7 @@ #include <glib.h> #include "glib-mainloop.h" -struct pa_io_event { +struct pa_io_event { pa_glib_mainloop *mainloop; int dead; @@ -69,7 +66,7 @@ struct pa_defer_event { int dead; int enabled; - + pa_defer_event_cb_t callback; void *userdata; pa_defer_event_destroy_cb_t destroy_callback; @@ -79,7 +76,7 @@ struct pa_defer_event { struct pa_glib_mainloop { GSource source; - + pa_mainloop_api api; GMainContext *context; @@ -102,26 +99,28 @@ static void cleanup_io_events(pa_glib_mainloop *g, int force) { if (!force && g->io_events_please_scan <= 0) break; - + if (force || e->dead) { PA_LLIST_REMOVE(pa_io_event, g->io_events, e); - if (e->dead) + if (e->dead) { + g_assert(g->io_events_please_scan > 0); g->io_events_please_scan--; - + } + if (e->poll_fd_added) g_source_remove_poll(&g->source, &e->poll_fd); - + if (e->destroy_callback) e->destroy_callback(&g->api, e, e->userdata); - + pa_xfree(e); } e = n; } - assert(g->io_events_please_scan == 0); + g_assert(g->io_events_please_scan == 0); } static void cleanup_time_events(pa_glib_mainloop *g, int force) { @@ -133,26 +132,30 @@ static void cleanup_time_events(pa_glib_mainloop *g, int force) { if (!force && g->time_events_please_scan <= 0) break; - + if (force || e->dead) { PA_LLIST_REMOVE(pa_time_event, g->time_events, e); - if (e->dead) + if (e->dead) { + g_assert(g->time_events_please_scan > 0); g->time_events_please_scan--; + } - if (!e->dead && e->enabled) + if (!e->dead && e->enabled) { + g_assert(g->n_enabled_time_events > 0); g->n_enabled_time_events--; - + } + if (e->destroy_callback) e->destroy_callback(&g->api, e, e->userdata); - + pa_xfree(e); } e = n; } - assert(g->time_events_please_scan == 0); + g_assert(g->time_events_please_scan == 0); } static void cleanup_defer_events(pa_glib_mainloop *g, int force) { @@ -164,34 +167,38 @@ static void cleanup_defer_events(pa_glib_mainloop *g, int force) { if (!force && g->defer_events_please_scan <= 0) break; - + if (force || e->dead) { PA_LLIST_REMOVE(pa_defer_event, g->defer_events, e); - if (e->dead) + if (e->dead) { + g_assert(g->defer_events_please_scan > 0); g->defer_events_please_scan--; + } - if (!e->dead && e->enabled) + if (!e->dead && e->enabled) { + g_assert(g->n_enabled_defer_events > 0); g->n_enabled_defer_events--; - + } + if (e->destroy_callback) e->destroy_callback(&g->api, e, e->userdata); - + pa_xfree(e); } e = n; } - assert(g->defer_events_please_scan == 0); + g_assert(g->defer_events_please_scan == 0); } static gushort map_flags_to_glib(pa_io_event_flags_t flags) { - return - (flags & PA_IO_EVENT_INPUT ? G_IO_IN : 0) | - (flags & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0) | - (flags & PA_IO_EVENT_ERROR ? G_IO_ERR : 0) | - (flags & PA_IO_EVENT_HANGUP ? G_IO_HUP : 0); + return (gushort) + ((flags & PA_IO_EVENT_INPUT ? G_IO_IN : 0) | + (flags & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0) | + (flags & PA_IO_EVENT_ERROR ? G_IO_ERR : 0) | + (flags & PA_IO_EVENT_HANGUP ? G_IO_HUP : 0)); } static pa_io_event_flags_t map_flags_from_glib(gushort flags) { @@ -208,15 +215,15 @@ static pa_io_event* glib_io_new( pa_io_event_flags_t f, pa_io_event_cb_t cb, void *userdata) { - + pa_io_event *e; pa_glib_mainloop *g; - assert(m); - assert(m->userdata); - assert(fd >= 0); - assert(cb); - + g_assert(m); + g_assert(m->userdata); + g_assert(fd >= 0); + g_assert(cb); + g = m->userdata; e = pa_xnew(pa_io_event, 1); @@ -226,7 +233,7 @@ static pa_io_event* glib_io_new( e->poll_fd.fd = fd; e->poll_fd.events = map_flags_to_glib(f); e->poll_fd.revents = 0; - + e->callback = cb; e->userdata = userdata; e->destroy_callback = NULL; @@ -235,20 +242,20 @@ static pa_io_event* glib_io_new( g_source_add_poll(&g->source, &e->poll_fd); e->poll_fd_added = 1; - + return e; } static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); e->poll_fd.events = map_flags_to_glib(f); } static void glib_io_free(pa_io_event*e) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); e->dead = 1; e->mainloop->io_events_please_scan++; @@ -260,9 +267,9 @@ static void glib_io_free(pa_io_event*e) { } static void glib_io_set_destroy(pa_io_event*e, pa_io_event_destroy_cb_t cb) { - assert(e); - assert(!e->dead); - + g_assert(e); + g_assert(!e->dead); + e->destroy_callback = cb; } @@ -273,14 +280,14 @@ static pa_time_event* glib_time_new( const struct timeval *tv, pa_time_event_cb_t cb, void *userdata) { - + pa_glib_mainloop *g; pa_time_event *e; - - assert(m); - assert(m->userdata); - assert(cb); - + + g_assert(m); + g_assert(m->userdata); + g_assert(cb); + g = m->userdata; e = pa_xnew(pa_time_event, 1); @@ -298,23 +305,24 @@ static pa_time_event* glib_time_new( g->cached_next_time_event = e; } } - + e->callback = cb; e->userdata = userdata; e->destroy_callback = NULL; PA_LLIST_PREPEND(pa_time_event, g->time_events, e); - + return e; } static void glib_time_restart(pa_time_event*e, const struct timeval *tv) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); - if (e->enabled && !!tv) + if (e->enabled && !tv) { + g_assert(e->mainloop->n_enabled_time_events > 0); e->mainloop->n_enabled_time_events--; - else if (!e->enabled && tv) + } else if (!e->enabled && tv) e->mainloop->n_enabled_time_events++; if ((e->enabled = !!tv)) @@ -327,11 +335,11 @@ static void glib_time_restart(pa_time_event*e, const struct timeval *tv) { e->mainloop->cached_next_time_event = e; } else if (e->mainloop->cached_next_time_event == e) e->mainloop->cached_next_time_event = NULL; - } +} static void glib_time_free(pa_time_event *e) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); e->dead = 1; e->mainloop->time_events_please_scan++; @@ -344,9 +352,9 @@ static void glib_time_free(pa_time_event *e) { } static void glib_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t cb) { - assert(e); - assert(!e->dead); - + g_assert(e); + g_assert(!e->dead); + e->destroy_callback = cb; } @@ -356,77 +364,80 @@ static pa_defer_event* glib_defer_new( pa_mainloop_api*m, pa_defer_event_cb_t cb, void *userdata) { - + pa_defer_event *e; pa_glib_mainloop *g; - assert(m); - assert(m->userdata); - assert(cb); - + g_assert(m); + g_assert(m->userdata); + g_assert(cb); + g = m->userdata; - + e = pa_xnew(pa_defer_event, 1); e->mainloop = g; e->dead = 0; e->enabled = 1; g->n_enabled_defer_events++; - + e->callback = cb; e->userdata = userdata; e->destroy_callback = NULL; - + PA_LLIST_PREPEND(pa_defer_event, g->defer_events, e); return e; } static void glib_defer_enable(pa_defer_event *e, int b) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); - if (e->enabled && !b) + if (e->enabled && !b) { + g_assert(e->mainloop->n_enabled_defer_events > 0); e->mainloop->n_enabled_defer_events--; - else if (!e->enabled && b) + } else if (!e->enabled && b) e->mainloop->n_enabled_defer_events++; e->enabled = b; } static void glib_defer_free(pa_defer_event *e) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); e->dead = 1; e->mainloop->defer_events_please_scan++; - if (e->enabled) + if (e->enabled) { + g_assert(e->mainloop->n_enabled_defer_events > 0); e->mainloop->n_enabled_defer_events--; + } } static void glib_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t cb) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); e->destroy_callback = cb; } /* quit() */ -static void glib_quit(pa_mainloop_api*a, PA_GCC_UNUSED int retval) { +static void glib_quit(pa_mainloop_api*a, int retval) { g_warning("quit() ignored"); - + /* NOOP */ } static pa_time_event* find_next_time_event(pa_glib_mainloop *g) { pa_time_event *t, *n = NULL; - assert(g); + g_assert(g); if (g->cached_next_time_event) return g->cached_next_time_event; - + for (t = g->time_events; t; t = t->next) { if (t->dead || !t->enabled) @@ -445,11 +456,8 @@ static pa_time_event* find_next_time_event(pa_glib_mainloop *g) { return n; } -static gboolean prepare_func(GSource *source, gint *timeout) { - pa_glib_mainloop *g = (pa_glib_mainloop*) source; - +static void scan_dead(pa_glib_mainloop *g) { g_assert(g); - g_assert(timeout); if (g->io_events_please_scan) cleanup_io_events(g, 0); @@ -459,6 +467,15 @@ static gboolean prepare_func(GSource *source, gint *timeout) { if (g->defer_events_please_scan) cleanup_defer_events(g, 0); +} + +static gboolean prepare_func(GSource *source, gint *timeout) { + pa_glib_mainloop *g = (pa_glib_mainloop*) source; + + g_assert(g); + g_assert(timeout); + + scan_dead(g); if (g->n_enabled_defer_events) { *timeout = 0; @@ -476,13 +493,11 @@ static gboolean prepare_func(GSource *source, gint *timeout) { tvnow.tv_sec = now.tv_sec; tvnow.tv_usec = now.tv_usec; - usec = pa_timeval_diff(&t->timeval, &tvnow); - - if (usec <= 0) { + if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) { *timeout = 0; return TRUE; } - + usec = pa_timeval_diff(&t->timeval, &tvnow); *timeout = (gint) (usec / 1000); } else *timeout = -1; @@ -501,10 +516,10 @@ static gboolean check_func(GSource *source) { pa_time_event *t; GTimeVal now; struct timeval tvnow; - + t = find_next_time_event(g); g_assert(t); - + g_source_get_current_time(source, &now); tvnow.tv_sec = now.tv_sec; tvnow.tv_usec = now.tv_usec; @@ -520,7 +535,7 @@ static gboolean check_func(GSource *source) { return FALSE; } -static gboolean dispatch_func(GSource *source, PA_GCC_UNUSED GSourceFunc callback, PA_GCC_UNUSED gpointer userdata) { +static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer userdata) { pa_glib_mainloop *g = (pa_glib_mainloop*) source; pa_io_event *e; @@ -536,8 +551,8 @@ static gboolean dispatch_func(GSource *source, PA_GCC_UNUSED GSourceFunc callbac break; } - assert(d); - + g_assert(d); + d->callback(&g->api, d, d->userdata); return TRUE; } @@ -549,12 +564,16 @@ static gboolean dispatch_func(GSource *source, PA_GCC_UNUSED GSourceFunc callbac t = find_next_time_event(g); g_assert(t); - + g_source_get_current_time(source, &now); tvnow.tv_sec = now.tv_sec; tvnow.tv_usec = now.tv_usec; - if (pa_timeval_cmp(&t->timeval, &tvnow) < 0) { + if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) { + + /* Disable time event */ + glib_time_restart(t, NULL); + t->callback(&g->api, t, &t->timeval, t->userdata); return TRUE; } @@ -582,12 +601,12 @@ static const pa_mainloop_api vtable = { .time_restart = glib_time_restart, .time_free = glib_time_free, .time_set_destroy = glib_time_set_destroy, - + .defer_new = glib_defer_new, .defer_enable = glib_defer_enable, .defer_free = glib_defer_free, .defer_set_destroy = glib_defer_set_destroy, - + .quit = glib_quit, }; @@ -602,10 +621,10 @@ pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) { NULL, NULL }; - + g = (pa_glib_mainloop*) g_source_new(&source_funcs, sizeof(pa_glib_mainloop)); g_main_context_ref(g->context = c ? c : g_main_context_default()); - + g->api = vtable; g->api.userdata = g; @@ -615,15 +634,17 @@ pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) { g->n_enabled_defer_events = g->n_enabled_time_events = 0; g->io_events_please_scan = g->time_events_please_scan = g->defer_events_please_scan = 0; - + + g->cached_next_time_event = NULL; + g_source_attach(&g->source, g->context); g_source_set_can_recurse(&g->source, FALSE); - + return g; } void pa_glib_mainloop_free(pa_glib_mainloop* g) { - assert(g); + g_assert(g); cleanup_io_events(g, 1); cleanup_defer_events(g, 1); @@ -635,7 +656,7 @@ void pa_glib_mainloop_free(pa_glib_mainloop* g) { } pa_mainloop_api* pa_glib_mainloop_get_api(pa_glib_mainloop *g) { - assert(g); - + g_assert(g); + return &g->api; } |
