From 964bdfd1e8255b57e9d22cd22b3784e2fc79b905 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 5 Aug 2004 19:53:57 +0000 Subject: add initial glib mainloop adapter clean up mainloop API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@105 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 + polyp/Makefile.am | 7 +- polyp/alsa-util.c | 34 +-- polyp/alsa-util.h | 4 +- polyp/core.c | 1 + polyp/core.h | 2 +- polyp/glib-mainloop.c | 503 ++++++++++++++++++++++++++++++++++++ polyp/glib-mainloop.h | 14 ++ polyp/iochannel.c | 60 ++--- polyp/main.c | 11 +- polyp/mainloop-api.c | 34 +-- polyp/mainloop-api.h | 48 ++-- polyp/mainloop-signal.c | 99 ++++---- polyp/mainloop-signal.h | 8 +- polyp/mainloop.c | 616 ++++++++++++++++++++++----------------------- polyp/module-alsa-sink.c | 14 +- polyp/module-alsa-source.c | 14 +- polyp/module-oss-mmap.c | 19 +- polyp/module-pipe-sink.c | 16 +- polyp/module-x11-bell.c | 10 +- polyp/module.c | 20 +- polyp/module.h | 1 - polyp/native-common.h | 16 +- polyp/pacat.c | 46 ++-- polyp/pactl.c | 4 +- polyp/pdispatch.c | 12 +- polyp/play-memchunk.c | 2 +- polyp/polypaudio.pa | 30 ++- polyp/polyplib.h | 30 +++ polyp/protocol-esound.c | 35 +-- polyp/protocol-native.c | 122 +++++++++ polyp/protocol-simple.c | 30 +-- polyp/pstream.c | 18 +- polyp/socket-client.c | 39 +-- polyp/socket-server.c | 12 +- polyp/xmalloc.h | 1 + 36 files changed, 1310 insertions(+), 626 deletions(-) create mode 100644 polyp/glib-mainloop.c create mode 100644 polyp/glib-mainloop.h diff --git a/configure.ac b/configure.ac index 9e5352a5..3183d174 100644 --- a/configure.ac +++ b/configure.ac @@ -54,6 +54,10 @@ PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ]) AC_SUBST(ASOUNDLIB_CFLAGS) AC_SUBST(ASOUNDLIB_LIBS) +PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ]) +AC_SUBST(GLIB20_CFLAGS) +AC_SUBST(GLIB20_LIBS) + # If using GCC specifiy some additional parameters if test "x$GCC" = "xyes" ; then CFLAGS="$CFLAGS -pipe -Wall -W -Wno-unused-parameter" diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 0af99110..c0be8ce0 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -71,7 +71,8 @@ pkglib_LTLIBRARIES=libiochannel.la \ lib_LTLIBRARIES=libpolyp.la \ libpolyp-simple.la \ libpolyp-error.la \ - libpolyp-mainloop.la + libpolyp-mainloop.la \ + libpolyp-mainloop-glib.la polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ @@ -307,6 +308,10 @@ parec_simple_SOURCES = parec-simple.c parec_simple_LDADD = $(AM_LDADD) libpolyp-simple.la libpolyp-error.la parec_simple_CFLAGS = $(AM_CFLAGS) +libpolyp_mainloop_glib_la_SOURCES = glib-mainloop.h glib-mainloop.c +libpolyp_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) +libpolyp_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop.la $(GLIB20_LIBS) + if BUILD_LIBPOLYPCORE pkginclude_HEADERS+=cli-command.h\ diff --git a/polyp/alsa-util.c b/polyp/alsa-util.c index 43562378..70e2e072 100644 --- a/polyp/alsa-util.c +++ b/polyp/alsa-util.c @@ -59,26 +59,26 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint return ret; } -int pa_create_io_sources(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, void ***io_sources, unsigned *n_io_sources, void (*cb)(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata) { +int pa_create_io_events(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, struct pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata) { unsigned i; struct pollfd *pfds, *ppfd; - void **ios; - assert(pcm_handle && m && io_sources && n_io_sources && cb); + struct pa_io_event **ios; + assert(pcm_handle && m && io_events && n_io_events && cb); - *n_io_sources = snd_pcm_poll_descriptors_count(pcm_handle); + *n_io_events = snd_pcm_poll_descriptors_count(pcm_handle); - pfds = pa_xmalloc(sizeof(struct pollfd) * *n_io_sources); - if (snd_pcm_poll_descriptors(pcm_handle, pfds, *n_io_sources) < 0) { + pfds = pa_xmalloc(sizeof(struct pollfd) * *n_io_events); + if (snd_pcm_poll_descriptors(pcm_handle, pfds, *n_io_events) < 0) { pa_xfree(pfds); return -1; } - *io_sources = pa_xmalloc(sizeof(void*) * *n_io_sources); + *io_events = pa_xmalloc(sizeof(void*) * *n_io_events); - for (i = 0, ios = *io_sources, ppfd = pfds; i < *n_io_sources; i++, ios++, ppfd++) { - *ios = m->source_io(m, ppfd->fd, - ((ppfd->events & POLLIN) ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | - ((ppfd->events & POLLOUT) ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), cb, userdata); + for (i = 0, ios = *io_events, ppfd = pfds; i < *n_io_events; i++, ios++, ppfd++) { + *ios = m->io_new(m, ppfd->fd, + ((ppfd->events & POLLIN) ? PA_IO_EVENT_INPUT : 0) | + ((ppfd->events & POLLOUT) ? PA_IO_EVENT_OUTPUT : 0), cb, userdata); assert(*ios); } @@ -86,12 +86,12 @@ int pa_create_io_sources(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, void return 0; } -void pa_free_io_sources(struct pa_mainloop_api* m, void **io_sources, unsigned n_io_sources) { +void pa_free_io_events(struct pa_mainloop_api* m, struct pa_io_event **io_events, unsigned n_io_events) { unsigned i; - void **ios; - assert(m && io_sources); + struct pa_io_event **ios; + assert(m && io_events); - for (ios = io_sources, i = 0; i < n_io_sources; i++, ios++) - m->cancel_io(m, *ios); - pa_xfree(io_sources); + for (ios = io_events, i = 0; i < n_io_events; i++, ios++) + m->io_free(*ios); + pa_xfree(io_events); } diff --git a/polyp/alsa-util.h b/polyp/alsa-util.h index 03e427d9..2627a75c 100644 --- a/polyp/alsa-util.h +++ b/polyp/alsa-util.h @@ -29,7 +29,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *buffer_size); -int pa_create_io_sources(snd_pcm_t *pcm_handle, struct pa_mainloop_api *m, void ***io_sources, unsigned *n_io_sources, void (*cb)(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata); -void pa_free_io_sources(struct pa_mainloop_api* m, void **io_sources, unsigned n_io_sources); +int pa_create_io_events(snd_pcm_t *pcm_handle, struct pa_mainloop_api *m, struct pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata); +void pa_free_io_events(struct pa_mainloop_api* m, struct pa_io_event **io_sources, unsigned n_io_sources); #endif diff --git a/polyp/core.c b/polyp/core.c index ffc11cec..0444fa96 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -62,6 +62,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->default_sample_spec.channels = 2; c->auto_unload_time = 20; + c->auto_unload_event = NULL; pa_check_for_sigpipe(); diff --git a/polyp/core.h b/polyp/core.h index b125083d..e1e48cbc 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -38,7 +38,7 @@ struct pa_core { struct pa_sample_spec default_sample_spec; int auto_unload_time; - void *auto_unload_mainloop_source; + struct pa_time_event *auto_unload_event; }; struct pa_core* pa_core_new(struct pa_mainloop_api *m); diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c new file mode 100644 index 00000000..978cad07 --- /dev/null +++ b/polyp/glib-mainloop.c @@ -0,0 +1,503 @@ +#include + +#include "glib-mainloop.h" +#include "idxset.h" +#include "xmalloc.h" + +struct pa_io_event { + GSource source; + int dead; + struct pa_glib_mainloop *mainloop; + int fd; + GPollFD pollfd; + void (*callback) (struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata); + void *userdata; + void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_io_event*e, void *userdata); + struct pa_io_event *next, *prev; +}; + +struct pa_time_event { + struct pa_glib_mainloop *mainloop; + int dead; + GSource *source; + struct timeval timeval; + void (*callback) (struct pa_mainloop_api*m, struct pa_time_event *e, const struct timeval *tv, void *userdata); + void *userdata; + void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_time_event*e, void *userdata); + struct pa_time_event *next, *prev; +}; + +struct pa_defer_event { + struct pa_glib_mainloop *mainloop; + int dead; + GSource *source; + void (*callback) (struct pa_mainloop_api*m, struct pa_defer_event *e, void *userdata); + void *userdata; + void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_defer_event*e, void *userdata); + struct pa_defer_event *next, *prev; +}; + +struct pa_glib_mainloop { + GMainLoop *glib_mainloop; + struct pa_mainloop_api api; + GSource *cleanup_source; + struct pa_io_event *io_events, *dead_io_events; + struct pa_time_event *time_events, *dead_time_events; + struct pa_defer_event *defer_events, *dead_defer_events; +}; + +static void schedule_free_dead_events(struct pa_glib_mainloop *g); + +static gboolean glib_source_prepare(GSource *source, gint *timeout) { + return FALSE; +} + +static gboolean glib_source_check(GSource *source) { + struct pa_io_event *e = (struct pa_io_event*) source; + assert(e); + return !!e->pollfd.revents; +} + +static gboolean glib_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { + struct pa_io_event *e = (struct pa_io_event*) source; + assert(e); + + if (e->pollfd.revents) { + int f = + (e->pollfd.revents ? G_IO_IN : PA_IO_EVENT_INPUT) | + (e->pollfd.revents ? G_IO_OUT : PA_IO_EVENT_OUTPUT) | + (e->pollfd.revents ? G_IO_HUP : PA_IO_EVENT_HANGUP) | + (e->pollfd.revents ? G_IO_ERR : PA_IO_EVENT_ERROR); + e->pollfd.revents = 0; + + assert(e->callback); + e->callback(&e->mainloop->api, e, e->fd, f, e->userdata); + } + + return TRUE; +} + +static void glib_io_enable(struct pa_io_event*e, enum pa_io_event_flags f); + +static struct pa_io_event* glib_io_new(struct pa_mainloop_api*m, int fd, enum pa_io_event_flags f, void (*callback) (struct pa_mainloop_api*m, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata), void *userdata) { + struct pa_io_event *e; + struct pa_glib_mainloop *g; + + GSourceFuncs io_source_funcs = { + prepare: glib_source_prepare, + check: glib_source_check, + dispatch: glib_source_dispatch, + finalize: NULL, + closure_callback: NULL, + closure_marshal : NULL, + }; + + assert(m && m->userdata && fd >= 0 && callback); + g = m->userdata; + + e = (struct pa_io_event*) g_source_new(&io_source_funcs, sizeof(struct pa_io_event)); + assert(e); + e->mainloop = m->userdata; + e->dead = 0; + e->fd = fd; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + + e->pollfd.fd = fd; + e->pollfd.events = e->pollfd.revents = 0; + + g_source_attach(&e->source, g_main_loop_get_context(g->glib_mainloop)); + + glib_io_enable(e, f); + + e->next = g->io_events; + if (e->next) e->next->prev = e; + g->io_events = e; + e->prev = NULL; + + return e; +} + +static void glib_io_enable(struct pa_io_event*e, enum pa_io_event_flags f) { + int o; + assert(e && !e->dead); + + o = e->pollfd.events; + e->pollfd.events = (f & PA_IO_EVENT_INPUT ? G_IO_IN : 0) | (f & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0) | G_IO_HUP | G_IO_ERR; + + if (!o && e->pollfd.events) + g_source_add_poll(&e->source, &e->pollfd); + else if (o && !e->pollfd.events) + g_source_remove_poll(&e->source, &e->pollfd); +} + +static void glib_io_free(struct pa_io_event*e) { + assert(e && !e->dead); + + g_source_destroy(&e->source); + + if (e->prev) + e->prev->next = e->next; + else + e->mainloop->io_events = e->next; + + if (e->next) + e->next->prev = e->prev; + + if ((e->next = e->mainloop->dead_io_events)) + e->next->prev = e; + + e->mainloop->dead_io_events = e; + e->prev = NULL; + + e->dead = 1; + schedule_free_dead_events(e->mainloop); +} + +static void glib_io_set_destroy(struct pa_io_event*e, void (*callback)(struct pa_mainloop_api*m, struct pa_io_event *e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* Time sources */ + +static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv); + +static struct pa_time_event* glib_time_new(struct pa_mainloop_api*m, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*m, struct pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) { + struct pa_glib_mainloop *g; + struct pa_time_event *e; + + assert(m && m->userdata && tv && callback); + g = m->userdata; + + e = pa_xmalloc(sizeof(struct pa_time_event)); + e->mainloop = g; + e->dead = 0; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + e->source = NULL; + + glib_time_restart(e, tv); + + e->next = g->time_events; + if (e->next) e->next->prev = e; + g->time_events = e; + e->prev = NULL; + + return e; +} + +static guint msec_diff(const struct timeval *a, const struct timeval *b) { + guint r; + assert(a && b); + + if (a->tv_sec < b->tv_sec) + return 0; + + if (a->tv_sec == b->tv_sec && a->tv_sec <= b->tv_sec) + return 0; + + r = (a->tv_sec-b->tv_sec)*1000; + + if (a->tv_usec >= b->tv_usec) + r += (a->tv_usec - b->tv_usec) / 1000; + else + r -= (b->tv_usec - a->tv_usec) / 1000; + + return r; +} + +static gboolean time_cb(gpointer data) { + struct pa_time_event* e = data; + assert(e && e->mainloop && e->source); + + g_source_unref(e->source); + e->source = NULL; + + e->callback(&e->mainloop->api, e, &e->timeval, e->userdata); + return FALSE; +} + +static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv) { + struct timeval now; + assert(e && e->mainloop); + + gettimeofday(&now, NULL); + if (e->source) { + g_source_destroy(e->source); + g_source_unref(e->source); + } + + if (tv) { + e->timeval = *tv; + e->source = g_timeout_source_new(msec_diff(tv, &now)); + assert(e->source); + g_source_set_callback(e->source, time_cb, e, NULL); + g_source_attach(e->source, g_main_loop_get_context(e->mainloop->glib_mainloop)); + } else + e->source = NULL; + } + +static void glib_time_free(struct pa_time_event *e) { + assert(e && e->mainloop); + + if (e->source) { + g_source_destroy(e->source); + g_source_unref(e->source); + e->source = NULL; + } + + if (e->prev) + e->prev->next = e->next; + else + e->mainloop->time_events = e->next; + + if (e->next) + e->next->prev = e->prev; + + if ((e->next = e->mainloop->dead_time_events)) + e->next->prev = e; + + e->mainloop->dead_time_events = e; + e->prev = NULL; + + e->dead = 1; + schedule_free_dead_events(e->mainloop); +} + +static void glib_time_set_destroy(struct pa_time_event *e, void (*callback)(struct pa_mainloop_api*m, struct pa_time_event*e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* Deferred sources */ + +static void glib_defer_enable(struct pa_defer_event *e, int b); + +static struct pa_defer_event* glib_defer_new(struct pa_mainloop_api*m, void (*callback) (struct pa_mainloop_api*m, struct pa_defer_event *e, void *userdata), void *userdata) { + struct pa_defer_event *e; + struct pa_glib_mainloop *g; + + assert(m && m->userdata && callback); + g = m->userdata; + + e = pa_xmalloc(sizeof(struct pa_defer_event)); + e->mainloop = g; + e->dead = 0; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + e->source = NULL; + + glib_defer_enable(e, 1); + + e->next = g->defer_events; + if (e->next) e->next->prev = e; + g->defer_events = e; + e->prev = NULL; + return e; +} + +static gboolean idle_cb(gpointer data) { + struct pa_defer_event* e = data; + assert(e && e->mainloop && e->source); + + e->callback(&e->mainloop->api, e, e->userdata); + return TRUE; +} + +static void glib_defer_enable(struct pa_defer_event *e, int b) { + assert(e && e->mainloop); + + if (e->source && !b) { + g_source_destroy(e->source); + g_source_unref(e->source); + e->source = NULL; + } else if (!e->source && b) { + e->source = g_idle_source_new(); + assert(e->source); + g_source_set_callback(e->source, idle_cb, e, NULL); + g_source_attach(e->source, g_main_loop_get_context(e->mainloop->glib_mainloop)); + g_source_set_priority(e->source, G_PRIORITY_HIGH_IDLE); + } +} + +static void glib_defer_free(struct pa_defer_event *e) { + assert(e && e->mainloop); + + if (e->source) { + g_source_destroy(e->source); + g_source_unref(e->source); + e->source = NULL; + } + + if (e->prev) + e->prev->next = e->next; + else + e->mainloop->defer_events = e->next; + + if (e->next) + e->next->prev = e->prev; + + if ((e->next = e->mainloop->dead_defer_events)) + e->next->prev = e; + + e->mainloop->dead_defer_events = e; + e->prev = NULL; + + e->dead = 1; + schedule_free_dead_events(e->mainloop); +} + +static void glib_defer_set_destroy(struct pa_defer_event *e, void (*callback)(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* quit() */ + +static void glib_quit(struct pa_mainloop_api*a, int retval) { + struct pa_glib_mainloop *g; + assert(a && a->userdata); + g = a->userdata; + + g_main_loop_quit(g->glib_mainloop); +} + +static const struct pa_mainloop_api vtable = { + userdata: NULL, + + io_new: glib_io_new, + io_enable: glib_io_enable, + io_free: glib_io_free, + io_set_destroy: glib_io_set_destroy, + + time_new : glib_time_new, + 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, +}; + +struct pa_glib_mainloop *pa_glib_mainloop_new(GMainLoop *ml) { + struct pa_glib_mainloop *g; + assert(ml); + + g = pa_xmalloc(sizeof(struct pa_glib_mainloop)); + g->glib_mainloop = g_main_loop_ref(ml); + g->api = vtable; + g->api.userdata = g; + + g->io_events = g->dead_io_events = NULL; + g->time_events = g->dead_time_events = NULL; + g->defer_events = g->dead_defer_events = NULL; + + g->cleanup_source = NULL; + return g; +} + +static void free_io_events(struct pa_io_event *e) { + while (e) { + struct pa_io_event *r = e; + e = r->next; + + if (r->pollfd.events) + g_source_remove_poll(&r->source, &r->pollfd); + + if (!r->dead) + g_source_destroy(&r->source); + + if (r->destroy_callback) + r->destroy_callback(&r->mainloop->api, r, r->userdata); + + g_source_unref(&r->source); + } +} + +static void free_time_events(struct pa_time_event *e) { + while (e) { + struct pa_time_event *r = e; + e = r->next; + + if (r->source) { + g_source_destroy(r->source); + g_source_unref(r->source); + } + + if (r->destroy_callback) + r->destroy_callback(&r->mainloop->api, r, r->userdata); + + pa_xfree(r); + } +} + +static void free_defer_events(struct pa_defer_event *e) { + while (e) { + struct pa_defer_event *r = e; + e = r->next; + + if (r->source) { + g_source_destroy(r->source); + g_source_unref(r->source); + } + + if (r->destroy_callback) + r->destroy_callback(&r->mainloop->api, r, r->userdata); + + pa_xfree(r); + } +} + +void pa_glib_mainloop_free(struct pa_glib_mainloop* g) { + assert(g); + + free_io_events(g->io_events); + free_io_events(g->dead_io_events); + free_defer_events(g->defer_events); + free_defer_events(g->dead_defer_events); + free_time_events(g->time_events); + free_time_events(g->dead_time_events); + + g_main_loop_unref(g->glib_mainloop); + pa_xfree(g); +} + +struct pa_mainloop_api* pa_glib_mainloop_get_api(struct pa_glib_mainloop *g) { + assert(g); + return &g->api; +} + +static gboolean free_dead_events(gpointer p) { + struct pa_glib_mainloop *g = p; + assert(g); + + free_io_events(g->dead_io_events); + free_defer_events(g->dead_defer_events); + free_time_events(g->dead_time_events); + + g_source_destroy(g->cleanup_source); + g_source_unref(g->cleanup_source); + g->cleanup_source = NULL; + + return FALSE; +} + +static void schedule_free_dead_events(struct pa_glib_mainloop *g) { + assert(g && g->glib_mainloop); + + if (g->cleanup_source) + return; + + g->cleanup_source = g_idle_source_new(); + assert(g->cleanup_source); + g_source_set_callback(g->cleanup_source, free_dead_events, g, NULL); + g_source_attach(g->cleanup_source, g_main_loop_get_context(g->glib_mainloop)); +} diff --git a/polyp/glib-mainloop.h b/polyp/glib-mainloop.h new file mode 100644 index 00000000..50fe8b9c --- /dev/null +++ b/polyp/glib-mainloop.h @@ -0,0 +1,14 @@ +#ifndef fooglibmainloophfoo +#define fooglibmainloophfoo + +#include + +#include "mainloop-api.h" + +struct pa_glib_mainloop; + +struct pa_glib_mainloop *pa_glib_mainloop_new(GMainLoop *ml); +void pa_glib_mainloop_free(struct pa_glib_mainloop* g); +struct pa_mainloop_api* pa_glib_mainloop_get_api(struct pa_glib_mainloop *g); + +#endif diff --git a/polyp/iochannel.c b/polyp/iochannel.c index 77f8fb08..813347d4 100644 --- a/polyp/iochannel.c +++ b/polyp/iochannel.c @@ -46,50 +46,50 @@ struct pa_iochannel { int no_close; - void* input_source, *output_source; + struct pa_io_event* input_event, *output_event; }; static void enable_mainloop_sources(struct pa_iochannel *io) { assert(io); - if (io->input_source == io->output_source) { - enum pa_mainloop_api_io_events e = PA_MAINLOOP_API_IO_EVENT_NULL; - assert(io->input_source); + if (io->input_event == io->output_event) { + enum pa_io_event_flags f = PA_IO_EVENT_NULL; + assert(io->input_event); if (!io->readable) - e |= PA_MAINLOOP_API_IO_EVENT_INPUT; + f |= PA_IO_EVENT_INPUT; if (!io->writable) - e |= PA_MAINLOOP_API_IO_EVENT_OUTPUT; + f |= PA_IO_EVENT_OUTPUT; - io->mainloop->enable_io(io->mainloop, io->input_source, e); + io->mainloop->io_enable(io->input_event, f); } else { - if (io->input_source) - io->mainloop->enable_io(io->mainloop, io->input_source, io->readable ? PA_MAINLOOP_API_IO_EVENT_NULL : PA_MAINLOOP_API_IO_EVENT_INPUT); - if (io->output_source) - io->mainloop->enable_io(io->mainloop, io->output_source, io->writable ? PA_MAINLOOP_API_IO_EVENT_NULL : PA_MAINLOOP_API_IO_EVENT_OUTPUT); + if (io->input_event) + io->mainloop->io_enable(io->input_event, io->readable ? PA_IO_EVENT_NULL : PA_IO_EVENT_INPUT); + if (io->output_event) + io->mainloop->io_enable(io->output_event, io->writable ? PA_IO_EVENT_NULL : PA_IO_EVENT_OUTPUT); } } -static void callback(struct pa_mainloop_api* m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void callback(struct pa_mainloop_api* m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct pa_iochannel *io = userdata; int changed = 0; - assert(m && fd >= 0 && events && userdata); + assert(m && e && fd >= 0 && userdata); - if ((events & PA_MAINLOOP_API_IO_EVENT_HUP) && !io->hungup) { + if ((f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) && !io->hungup) { io->hungup = 1; changed = 1; } - if ((events & PA_MAINLOOP_API_IO_EVENT_INPUT) && !io->readable) { + if ((f & PA_IO_EVENT_INPUT) && !io->readable) { io->readable = 1; changed = 1; - assert(id == io->input_source); + assert(e == io->input_event); } - if ((events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) && !io->writable) { + if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) { io->writable = 1; changed = 1; - assert(id == io->output_source); + assert(e == io->output_event); } if (changed) { @@ -116,23 +116,23 @@ struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd io->hungup = 0; io->no_close = 0; + io->input_event = io->output_event = NULL; + if (ifd == ofd) { assert(ifd >= 0); pa_make_nonblock_fd(io->ifd); - io->input_source = io->output_source = m->source_io(m, ifd, PA_MAINLOOP_API_IO_EVENT_BOTH, callback, io); + io->input_event = io->output_event = m->io_new(m, ifd, PA_IO_EVENT_INPUT|PA_IO_EVENT_OUTPUT, callback, io); } else { if (ifd >= 0) { pa_make_nonblock_fd(io->ifd); - io->input_source = m->source_io(m, ifd, PA_MAINLOOP_API_IO_EVENT_INPUT, callback, io); - } else - io->input_source = NULL; + io->input_event = m->io_new(m, ifd, PA_IO_EVENT_INPUT, callback, io); + } if (ofd >= 0) { pa_make_nonblock_fd(io->ofd); - io->output_source = m->source_io(m, ofd, PA_MAINLOOP_API_IO_EVENT_OUTPUT, callback, io); - } else - io->output_source = NULL; + io->output_event = m->io_new(m, ofd, PA_IO_EVENT_OUTPUT, callback, io); + } } return io; @@ -141,17 +141,17 @@ struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd void pa_iochannel_free(struct pa_iochannel*io) { assert(io); + if (io->input_event) + io->mainloop->io_free(io->input_event); + if (io->output_event && (io->output_event != io->input_event)) + io->mainloop->io_free(io->output_event); + if (!io->no_close) { if (io->ifd >= 0) close(io->ifd); if (io->ofd >= 0 && io->ofd != io->ifd) close(io->ofd); } - - if (io->input_source) - io->mainloop->cancel_io(io->mainloop, io->input_source); - if (io->output_source && (io->output_source != io->input_source)) - io->mainloop->cancel_io(io->mainloop, io->output_source); pa_xfree(io); } diff --git a/polyp/main.c b/polyp/main.c index de66f1c8..9f3d3406 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -46,13 +46,12 @@ static struct pa_mainloop *mainloop; -static void exit_signal_callback(void *id, int sig, void *userdata) { - struct pa_mainloop_api* m = pa_mainloop_get_api(mainloop); +static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { m->quit(m, 1); fprintf(stderr, __FILE__": got signal.\n"); } -static void aux_signal_callback(void *id, int sig, void *userdata) { +static void aux_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { struct pa_core *c = userdata; assert(c); pa_module_load(c, sig == SIGUSR1 ? "module-cli" : "module-cli-protocol-unix", NULL); @@ -135,14 +134,14 @@ int main(int argc, char *argv[]) { r = pa_signal_init(pa_mainloop_get_api(mainloop)); assert(r == 0); - pa_signal_register(SIGINT, exit_signal_callback, NULL); + pa_signal_new(SIGINT, exit_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); c = pa_core_new(pa_mainloop_get_api(mainloop)); assert(c); - pa_signal_register(SIGUSR1, aux_signal_callback, c); - pa_signal_register(SIGUSR2, aux_signal_callback, c); + pa_signal_new(SIGUSR1, aux_signal_callback, c); + pa_signal_new(SIGUSR2, aux_signal_callback, c); buf = pa_strbuf_new(); assert(buf); diff --git a/polyp/mainloop-api.c b/polyp/mainloop-api.c index 8b4e09ac..952fce0a 100644 --- a/polyp/mainloop-api.c +++ b/polyp/mainloop-api.c @@ -30,32 +30,38 @@ #include "xmalloc.h" struct once_info { - void (*callback)(void *userdata); + void (*callback)(struct pa_mainloop_api*m, void *userdata); void *userdata; }; -static void once_callback(struct pa_mainloop_api *api, void *id, void *userdata) { +static void once_callback(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { struct once_info *i = userdata; - assert(api && i && i->callback); - i->callback(i->userdata); - assert(api->cancel_fixed); - api->cancel_fixed(api, id); + assert(m && i && i->callback); + + i->callback(m, i->userdata); + + assert(m->defer_free); + m->defer_free(e); +} + +static void free_callback(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { + struct once_info *i = userdata; + assert(m && i); pa_xfree(i); } -void pa_mainloop_api_once(struct pa_mainloop_api* api, void (*callback)(void *userdata), void *userdata) { +void pa_mainloop_api_once(struct pa_mainloop_api* m, void (*callback)(struct pa_mainloop_api *m, void *userdata), void *userdata) { struct once_info *i; - void *id; - assert(api && callback); + struct pa_defer_event *e; + assert(m && callback); i = pa_xmalloc(sizeof(struct once_info)); i->callback = callback; i->userdata = userdata; - assert(api->source_fixed); - id = api->source_fixed(api, once_callback, i); - assert(id); - - /* Note: if the mainloop is destroyed before once_callback() was called, some memory is leaked. */ + assert(m->defer_new); + e = m->defer_new(m, once_callback, i); + assert(e); + m->defer_set_destroy(e, free_callback); } diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h index 0228f580..4c8e379b 100644 --- a/polyp/mainloop-api.h +++ b/polyp/mainloop-api.h @@ -25,41 +25,43 @@ #include #include -enum pa_mainloop_api_io_events { - PA_MAINLOOP_API_IO_EVENT_NULL = 0, - PA_MAINLOOP_API_IO_EVENT_INPUT = 1, - PA_MAINLOOP_API_IO_EVENT_OUTPUT = 2, - PA_MAINLOOP_API_IO_EVENT_BOTH = 3, - PA_MAINLOOP_API_IO_EVENT_HUP = 4 +enum pa_io_event_flags { + PA_IO_EVENT_NULL = 0, + PA_IO_EVENT_INPUT = 1, + PA_IO_EVENT_OUTPUT = 2, + PA_IO_EVENT_HANGUP = 4, + PA_IO_EVENT_ERROR = 8, }; +struct pa_io_event; +struct pa_defer_event; +struct pa_time_event; + struct pa_mainloop_api { void *userdata; /* IO sources */ - void* (*source_io)(struct pa_mainloop_api*a, int fd, enum pa_mainloop_api_io_events events, void (*callback) (struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata); - void (*enable_io)(struct pa_mainloop_api*a, void* id, enum pa_mainloop_api_io_events events); - void (*cancel_io)(struct pa_mainloop_api*a, void* id); - - /* Fixed sources */ - void* (*source_fixed)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata); - void (*enable_fixed)(struct pa_mainloop_api*a, void* id, int b); - void (*cancel_fixed)(struct pa_mainloop_api*a, void* id); + struct pa_io_event* (*io_new)(struct pa_mainloop_api*a, int fd, enum pa_io_event_flags events, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event* e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata); + void (*io_enable)(struct pa_io_event* e, enum pa_io_event_flags events); + void (*io_free)(struct pa_io_event* e); + void (*io_set_destroy)(struct pa_io_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata)); - /* Idle sources */ - void* (*source_idle)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata); - void (*enable_idle)(struct pa_mainloop_api*a, void* id, int b); - void (*cancel_idle)(struct pa_mainloop_api*a, void* id); - /* Time sources */ - void* (*source_time)(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, void *id, const struct timeval *tv, void *userdata), void *userdata); - void (*enable_time)(struct pa_mainloop_api*a, void *id, const struct timeval *tv); - void (*cancel_time)(struct pa_mainloop_api*a, void* id); + struct pa_time_event* (*time_new)(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event* e, const struct timeval *tv, void *userdata), void *userdata); + void (*time_restart)(struct pa_time_event* e, const struct timeval *tv); + void (*time_free)(struct pa_time_event* e); + void (*time_set_destroy)(struct pa_time_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata)); + + /* Deferred sources */ + struct pa_defer_event* (*defer_new)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event* e, void *userdata), void *userdata); + void (*defer_enable)(struct pa_defer_event* e, int b); + void (*defer_free)(struct pa_defer_event* e); + void (*defer_set_destroy)(struct pa_defer_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata)); /* Exit mainloop */ void (*quit)(struct pa_mainloop_api*a, int retval); }; -void pa_mainloop_api_once(struct pa_mainloop_api*m, void (*callback)(void *userdata), void *userdata); +void pa_mainloop_api_once(struct pa_mainloop_api*m, void (*callback)(struct pa_mainloop_api*m, void *userdata), void *userdata); #endif diff --git a/polyp/mainloop-signal.c b/polyp/mainloop-signal.c index 6e79767a..f7ff7e93 100644 --- a/polyp/mainloop-signal.c +++ b/polyp/mainloop-signal.c @@ -35,30 +35,31 @@ #include "util.h" #include "xmalloc.h" -struct signal_info { +struct pa_signal_event { int sig; struct sigaction saved_sigaction; - void (*callback) (void *id, int signal, void *userdata); + void (*callback) (struct pa_mainloop_api*a, struct pa_signal_event *e, int signal, void *userdata); void *userdata; - struct signal_info *previous, *next; + void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_signal_event*e, void *userdata); + struct pa_signal_event *previous, *next; }; static struct pa_mainloop_api *api = NULL; static int signal_pipe[2] = { -1, -1 }; -static void* mainloop_source = NULL; -static struct signal_info *signals = NULL; +static struct pa_io_event* io_event = NULL; +static struct pa_signal_event *signals = NULL; static void signal_handler(int sig) { write(signal_pipe[1], &sig, sizeof(sig)); } -static void callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { - assert(a && id && events == PA_MAINLOOP_API_IO_EVENT_INPUT && id == mainloop_source && fd == signal_pipe[0]); +static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) { + assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]); for (;;) { ssize_t r; int sig; - struct signal_info*s; + struct pa_signal_event*s; if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) { if (errno == EAGAIN) @@ -76,14 +77,15 @@ static void callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloo for (s = signals; s; s = s->next) if (s->sig == sig) { assert(s->callback); - s->callback(s, sig, s->userdata); + s->callback(a, s, sig, s->userdata); break; } } } int pa_signal_init(struct pa_mainloop_api *a) { - assert(a); + assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event); + if (pipe(signal_pipe) < 0) { fprintf(stderr, "pipe() failed: %s\n", strerror(errno)); return -1; @@ -93,71 +95,80 @@ int pa_signal_init(struct pa_mainloop_api *a) { pa_make_nonblock_fd(signal_pipe[1]); api = a; - mainloop_source = api->source_io(api, signal_pipe[0], PA_MAINLOOP_API_IO_EVENT_INPUT, callback, NULL); - assert(mainloop_source); + io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL); + assert(io_event); return 0; } void pa_signal_done(void) { - assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && mainloop_source); + assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && io_event); + + while (signals) + pa_signal_free(signals); - api->cancel_io(api, mainloop_source); - mainloop_source = NULL; + api->io_free(io_event); + io_event = NULL; close(signal_pipe[0]); close(signal_pipe[1]); signal_pipe[0] = signal_pipe[1] = -1; - while (signals) - pa_signal_unregister(signals); - api = NULL; } -void* pa_signal_register(int sig, void (*callback) (void *id, int signal, void *userdata), void *userdata) { - struct signal_info *s = NULL; +struct pa_signal_event* pa_signal_new(int sig, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, int sig, void *userdata), void *userdata) { + struct pa_signal_event *e = NULL; struct sigaction sa; assert(sig > 0 && callback); - - for (s = signals; s; s = s->next) - if (s->sig == sig) + + for (e = signals; e; e = e->next) + if (e->sig == sig) goto fail; - s = pa_xmalloc(sizeof(struct signal_info)); - s->sig = sig; - s->callback = callback; - s->userdata = userdata; + e = pa_xmalloc(sizeof(struct pa_signal_event)); + e->sig = sig; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; memset(&sa, 0, sizeof(sa)); sa.sa_handler = signal_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - if (sigaction(sig, &sa, &s->saved_sigaction) < 0) + if (sigaction(sig, &sa, &e->saved_sigaction) < 0) goto fail; - s->previous = NULL; - s->next = signals; - signals = s; + e->previous = NULL; + e->next = signals; + signals = e; - return s; + return e; fail: - if (s) - pa_xfree(s); + if (e) + pa_xfree(e); return NULL; } -void pa_signal_unregister(void *id) { - struct signal_info *s = id; - assert(s); +void pa_signal_free(struct pa_signal_event *e) { + assert(e); - if (s->next) - s->next->previous = s->previous; - if (s->previous) - s->previous->next = s->next; + if (e->next) + e->next->previous = e->previous; + if (e->previous) + e->previous->next = e->next; else - signals = s->next; + signals = e->next; + + sigaction(e->sig, &e->saved_sigaction, NULL); + + if (e->destroy_callback) + e->destroy_callback(api, e, e->userdata); + + pa_xfree(e); +} - sigaction(s->sig, &s->saved_sigaction, NULL); - pa_xfree(s); +void pa_signal_set_destroy(struct pa_signal_event *e, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, void *userdata)) { + assert(e); + e->destroy_callback = callback; } diff --git a/polyp/mainloop-signal.h b/polyp/mainloop-signal.h index 8afe9c8d..dacbc153 100644 --- a/polyp/mainloop-signal.h +++ b/polyp/mainloop-signal.h @@ -27,7 +27,11 @@ int pa_signal_init(struct pa_mainloop_api *api); void pa_signal_done(void); -void* pa_signal_register(int signal, void (*callback) (void *id, int signal, void *userdata), void *userdata); -void pa_signal_unregister(void *id); +struct pa_signal_event; + +struct pa_signal_event* pa_signal_new(int signal, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, int signal, void *userdata), void *userdata); +void pa_signal_free(struct pa_signal_event *e); + +void pa_signal_set_destroy(struct pa_signal_event *e, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, void *userdata)); #endif diff --git a/polyp/mainloop.c b/polyp/mainloop.c index f3d8e781..c678537e 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -38,42 +38,42 @@ #include "idxset.h" #include "xmalloc.h" -struct mainloop_source_header { +struct pa_base_event { +}; + +struct pa_io_event { struct pa_mainloop *mainloop; int dead; -}; - -struct mainloop_source_io { - struct mainloop_source_header header; - int fd; - enum pa_mainloop_api_io_events events; - void (*callback) (struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata); - void *userdata; - + enum pa_io_event_flags events; + void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata); struct pollfd *pollfd; + void *userdata; + void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata); }; -struct mainloop_source_fixed_or_idle { - struct mainloop_source_header header; +struct pa_time_event { + struct pa_mainloop *mainloop; + int dead; int enabled; - - void (*callback)(struct pa_mainloop_api*a, void *id, void *userdata); + struct timeval timeval; + void (*callback)(struct pa_mainloop_api*a, struct pa_time_event *e, const struct timeval*tv, void *userdata); void *userdata; + void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata); }; -struct mainloop_source_time { - struct mainloop_source_header header; +struct pa_defer_event { + struct pa_mainloop *mainloop; + int dead; int enabled; - - struct timeval timeval; - void (*callback)(struct pa_mainloop_api*a, void *id, const struct timeval*tv, void *userdata); + void (*callback)(struct pa_mainloop_api*a, struct pa_defer_event*e, void *userdata); void *userdata; + void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata); }; struct pa_mainloop { - struct pa_idxset *io_sources, *fixed_sources, *idle_sources, *time_sources; - int io_sources_scan_dead, fixed_sources_scan_dead, idle_sources_scan_dead, time_sources_scan_dead; + struct pa_idxset *io_events, *time_events, *defer_events; + int io_events_scan_dead, defer_events_scan_dead, time_events_scan_dead; struct pollfd *pollfds; unsigned max_pollfds, n_pollfds; @@ -83,57 +83,248 @@ struct pa_mainloop { struct pa_mainloop_api api; }; -static void setup_api(struct pa_mainloop *m); +/* IO events */ +static struct pa_io_event* mainloop_io_new(struct pa_mainloop_api*a, int fd, enum pa_io_event_flags events, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata) { + struct pa_mainloop *m; + struct pa_io_event *e; + + assert(a && a->userdata && fd >= 0 && callback); + m = a->userdata; + assert(a == &m->api); + + e = pa_xmalloc(sizeof(struct pa_io_event)); + e->mainloop = m; + e->dead = 0; + + e->fd = fd; + e->events = events; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + e->pollfd = NULL; + + pa_idxset_put(m->io_events, e, NULL); + m->rebuild_pollfds = 1; + return e; +} + +static void mainloop_io_enable(struct pa_io_event *e, enum pa_io_event_flags events) { + assert(e && e->mainloop); + + e->events = events; + if (e->pollfd) + e->pollfd->events = + (events & PA_IO_EVENT_INPUT ? POLLIN : 0) | + (events & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) | + POLLHUP | + POLLERR; +} + +static void mainloop_io_free(struct pa_io_event *e) { + assert(e && e->mainloop); + e->dead = e->mainloop->io_events_scan_dead = e->mainloop->rebuild_pollfds = 1; +} + +static void mainloop_io_set_destroy(struct pa_io_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* Defer events */ +struct pa_defer_event* mainloop_defer_new(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata), void *userdata) { + struct pa_mainloop *m; + struct pa_defer_event *e; + + assert(a && a->userdata && callback); + m = a->userdata; + assert(a == &m->api); + + e = pa_xmalloc(sizeof(struct pa_defer_event)); + e->mainloop = m; + e->dead = 0; + + e->enabled = 1; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + + pa_idxset_put(m->defer_events, e, NULL); + return e; +} + +static void mainloop_defer_enable(struct pa_defer_event *e, int b) { + assert(e); + e->enabled = b; +} + +static void mainloop_defer_free(struct pa_defer_event *e) { + assert(e); + e->dead = e->mainloop->defer_events_scan_dead = 1; +} + +static void mainloop_defer_set_destroy(struct pa_defer_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* Time events */ +static struct pa_time_event* mainloop_time_new(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) { + struct pa_mainloop *m; + struct pa_time_event *e; + + assert(a && a->userdata && callback); + m = a->userdata; + assert(a == &m->api); + + e = pa_xmalloc(sizeof(struct pa_time_event)); + e->mainloop = m; + e->dead = 0; + + e->enabled = !!tv; + if (tv) + e->timeval = *tv; + + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + + pa_idxset_put(m->time_events, e, NULL); + return e; +} + +static void mainloop_time_restart(struct pa_time_event *e, const struct timeval *tv) { + assert(e); + + if (tv) { + e->enabled = 1; + e->timeval = *tv; + } else + e->enabled = 0; +} + +static void mainloop_time_free(struct pa_time_event *e) { + assert(e); + e->dead = e->mainloop->time_events_scan_dead = 1; +} + +static void mainloop_time_set_destroy(struct pa_time_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* quit() */ + +static void mainloop_quit(struct pa_mainloop_api*a, int retval) { + struct pa_mainloop *m; + assert(a && a->userdata); + m = a->userdata; + assert(a == &m->api); + + m->quit = 1; + m->retval = retval; +} + +static const struct 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, + + time_new : mainloop_time_new, + time_restart : mainloop_time_restart, + time_free : mainloop_time_free, + time_set_destroy : mainloop_time_set_destroy, + + defer_new : mainloop_defer_new, + defer_enable : mainloop_defer_enable, + defer_free : mainloop_defer_free, + defer_set_destroy : mainloop_defer_set_destroy, + + quit : mainloop_quit, +}; struct pa_mainloop *pa_mainloop_new(void) { struct pa_mainloop *m; m = pa_xmalloc(sizeof(struct pa_mainloop)); - m->io_sources = pa_idxset_new(NULL, NULL); - m->fixed_sources = pa_idxset_new(NULL, NULL); - m->idle_sources = pa_idxset_new(NULL, NULL); - m->time_sources = pa_idxset_new(NULL, NULL); + m->io_events = pa_idxset_new(NULL, NULL); + m->defer_events = pa_idxset_new(NULL, NULL); + m->time_events = pa_idxset_new(NULL, NULL); - assert(m->io_sources && m->fixed_sources && m->idle_sources && m->time_sources); + assert(m->io_events && m->defer_events && m->time_events); - m->io_sources_scan_dead = m->fixed_sources_scan_dead = m->idle_sources_scan_dead = m->time_sources_scan_dead = 0; + m->io_events_scan_dead = m->defer_events_scan_dead = m->time_events_scan_dead = 0; m->pollfds = NULL; m->max_pollfds = m->n_pollfds = m->rebuild_pollfds = 0; m->quit = m->running = m->retval = 0; - setup_api(m); + m->api = vtable; + m->api.userdata = m; return m; } -static int foreach(void *p, uint32_t index, int *del, void*userdata) { - struct mainloop_source_header *h = p; +static int io_foreach(void *p, uint32_t index, int *del, void*userdata) { + struct pa_io_event *e = p; int *all = userdata; - assert(p && del && all); + assert(e && del && all); - if (*all || h->dead) { - pa_xfree(h); - *del = 1; - } + if (!*all || !e->dead) + return 0; + + if (e->destroy_callback) + e->destroy_callback(&e->mainloop->api, e, e->userdata); + pa_xfree(e); + *del = 1; + return 0; +}; +static int time_foreach(void *p, uint32_t index, int *del, void*userdata) { + struct pa_time_event *e = p; + int *all = userdata; + assert(e && del && all); + + if (!*all || !e->dead) + return 0; + + if (e->destroy_callback) + e->destroy_callback(&e->mainloop->api, e, e->userdata); + pa_xfree(e); + *del = 1; + return 0; +}; + +static int defer_foreach(void *p, uint32_t index, int *del, void*userdata) { + struct pa_defer_event *e = p; + int *all = userdata; + assert(e && del && all); + + if (!*all || !e->dead) + return 0; + + if (e->destroy_callback) + e->destroy_callback(&e->mainloop->api, e, e->userdata); + pa_xfree(e); + *del = 1; return 0; }; void pa_mainloop_free(struct pa_mainloop* m) { int all = 1; assert(m); - pa_idxset_foreach(m->io_sources, foreach, &all); - pa_idxset_foreach(m->fixed_sources, foreach, &all); - pa_idxset_foreach(m->idle_sources, foreach, &all); - pa_idxset_foreach(m->time_sources, foreach, &all); - pa_idxset_free(m->io_sources, NULL, NULL); - pa_idxset_free(m->fixed_sources, NULL, NULL); - pa_idxset_free(m->idle_sources, NULL, NULL); - pa_idxset_free(m->time_sources, NULL, NULL); + pa_idxset_foreach(m->io_events, io_foreach, &all); + pa_idxset_foreach(m->time_events, time_foreach, &all); + pa_idxset_foreach(m->defer_events, defer_foreach, &all); + + pa_idxset_free(m->io_events, NULL, NULL); + pa_idxset_free(m->time_events, NULL, NULL); + pa_idxset_free(m->defer_events, NULL, NULL); pa_xfree(m->pollfds); pa_xfree(m); @@ -142,23 +333,21 @@ void pa_mainloop_free(struct pa_mainloop* m) { static void scan_dead(struct pa_mainloop *m) { int all = 0; assert(m); - if (m->io_sources_scan_dead) - pa_idxset_foreach(m->io_sources, foreach, &all); - if (m->fixed_sources_scan_dead) - pa_idxset_foreach(m->fixed_sources, foreach, &all); - if (m->idle_sources_scan_dead) - pa_idxset_foreach(m->idle_sources, foreach, &all); - if (m->time_sources_scan_dead) - pa_idxset_foreach(m->time_sources, foreach, &all); + if (m->io_events_scan_dead) + pa_idxset_foreach(m->io_events, io_foreach, &all); + if (m->time_events_scan_dead) + pa_idxset_foreach(m->time_events, time_foreach, &all); + if (m->defer_events_scan_dead) + pa_idxset_foreach(m->defer_events, defer_foreach, &all); } static void rebuild_pollfds(struct pa_mainloop *m) { - struct mainloop_source_io*s; + struct pa_io_event*e; struct pollfd *p; uint32_t index = PA_IDXSET_INVALID; unsigned l; - l = pa_idxset_ncontents(m->io_sources); + l = pa_idxset_ncontents(m->io_events); if (m->max_pollfds < l) { m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l); m->max_pollfds = l; @@ -166,15 +355,19 @@ static void rebuild_pollfds(struct pa_mainloop *m) { m->n_pollfds = 0; p = m->pollfds; - for (s = pa_idxset_first(m->io_sources, &index); s; s = pa_idxset_next(m->io_sources, &index)) { - if (s->header.dead) { - s->pollfd = NULL; + for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) { + if (e->dead) { + e->pollfd = NULL; continue; } - s->pollfd = p; - p->fd = s->fd; - p->events = ((s->events & PA_MAINLOOP_API_IO_EVENT_INPUT) ? POLLIN : 0) | ((s->events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) ? POLLOUT : 0); + e->pollfd = p; + p->fd = e->fd; + p->events = + ((e->events & PA_IO_EVENT_INPUT) ? POLLIN : 0) | + ((e->events & PA_IO_EVENT_OUTPUT) ? POLLOUT : 0) | + POLLHUP | + POLLERR; p->revents = 0; p++; @@ -184,60 +377,62 @@ static void rebuild_pollfds(struct pa_mainloop *m) { static void dispatch_pollfds(struct pa_mainloop *m) { uint32_t index = PA_IDXSET_INVALID; - struct mainloop_source_io *s; + struct pa_io_event *e; - for (s = pa_idxset_first(m->io_sources, &index); s; s = pa_idxset_next(m->io_sources, &index)) { - if (s->header.dead || !s->pollfd || !s->pollfd->revents) + for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) { + if (e->dead || !e->pollfd || !e->pollfd->revents) continue; - assert(s->pollfd->fd == s->fd && s->callback); - s->callback(&m->api, s, s->fd, - ((s->pollfd->revents & POLLHUP) ? PA_MAINLOOP_API_IO_EVENT_HUP : 0) | - ((s->pollfd->revents & POLLIN) ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | - ((s->pollfd->revents & POLLOUT) ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), s->userdata); - s->pollfd->revents = 0; + assert(e->pollfd->fd == e->fd && e->callback); + e->callback(&m->api, e, e->fd, + (e->pollfd->revents & POLLHUP ? PA_IO_EVENT_HANGUP : 0) | + (e->pollfd->revents & POLLIN ? PA_IO_EVENT_INPUT : 0) | + (e->pollfd->revents & POLLOUT ? PA_IO_EVENT_OUTPUT : 0) | + (e->pollfd->revents & POLLERR ? PA_IO_EVENT_ERROR : 0), + e->userdata); + e->pollfd->revents = 0; } } -static void run_fixed_or_idle(struct pa_mainloop *m, struct pa_idxset *i) { - uint32_t index = PA_IDXSET_INVALID; - struct mainloop_source_fixed_or_idle *s; +static void dispatch_defer(struct pa_mainloop *m) { + uint32_t index; + struct pa_defer_event *e; - for (s = pa_idxset_first(i, &index); s; s = pa_idxset_next(i, &index)) { - if (s->header.dead || !s->enabled) + for (e = pa_idxset_first(m->defer_events, &index); e; e = pa_idxset_next(m->defer_events, &index)) { + if (e->dead || !e->enabled) continue; - assert(s->callback); - s->callback(&m->api, s, s->userdata); + assert(e->callback); + e->callback(&m->api, e, e->userdata); } } static int calc_next_timeout(struct pa_mainloop *m) { - uint32_t index = PA_IDXSET_INVALID; - struct mainloop_source_time *s; + uint32_t index; + struct pa_time_event *e; struct timeval now; int t = -1; - if (pa_idxset_isempty(m->time_sources)) + if (pa_idxset_isempty(m->time_events)) return -1; gettimeofday(&now, NULL); - for (s = pa_idxset_first(m->time_sources, &index); s; s = pa_idxset_next(m->time_sources, &index)) { + for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) { int tmp; - if (s->header.dead || !s->enabled) + if (e->dead || !e->enabled) continue; - if (s->timeval.tv_sec < now.tv_sec || (s->timeval.tv_sec == now.tv_sec && s->timeval.tv_usec <= now.tv_usec)) + if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec)) return 0; - tmp = (s->timeval.tv_sec - now.tv_sec)*1000; + tmp = (e->timeval.tv_sec - now.tv_sec)*1000; - if (s->timeval.tv_usec > now.tv_usec) - tmp += (s->timeval.tv_usec - now.tv_usec)/1000; + if (e->timeval.tv_usec > now.tv_usec) + tmp += (e->timeval.tv_usec - now.tv_usec)/1000; else - tmp -= (now.tv_usec - s->timeval.tv_usec)/1000; + tmp -= (now.tv_usec - e->timeval.tv_usec)/1000; if (tmp == 0) return 0; @@ -249,43 +444,31 @@ static int calc_next_timeout(struct pa_mainloop *m) { } static void dispatch_timeout(struct pa_mainloop *m) { - uint32_t index = PA_IDXSET_INVALID; - struct mainloop_source_time *s; + uint32_t index; + struct pa_time_event *e; struct timeval now; assert(m); - if (pa_idxset_isempty(m->time_sources)) + if (pa_idxset_isempty(m->time_events)) return; gettimeofday(&now, NULL); - for (s = pa_idxset_first(m->time_sources, &index); s; s = pa_idxset_next(m->time_sources, &index)) { + for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) { - if (s->header.dead || !s->enabled) + if (e->dead || !e->enabled) continue; - if (s->timeval.tv_sec < now.tv_sec || (s->timeval.tv_sec == now.tv_sec && s->timeval.tv_usec <= now.tv_usec)) { - assert(s->callback); + if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec)) { + assert(e->callback); - s->enabled = 0; - s->callback(&m->api, s, &s->timeval, s->userdata); + e->enabled = 0; + e->callback(&m->api, e, &e->timeval, e->userdata); } } } -static int any_idle_sources(struct pa_mainloop *m) { - struct mainloop_source_fixed_or_idle *s; - uint32_t index; - assert(m); - - for (s = pa_idxset_first(m->idle_sources, &index); s; s = pa_idxset_next(m->idle_sources, &index)) - if (!s->header.dead && s->enabled) - return 1; - - return 0; -} - int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { - int r, idle; + int r; assert(m && !m->running); if(m->quit) { @@ -297,23 +480,16 @@ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { m->running = 1; scan_dead(m); - run_fixed_or_idle(m, m->fixed_sources); + dispatch_defer(m); if (m->rebuild_pollfds) { rebuild_pollfds(m); m->rebuild_pollfds = 0; } - idle = any_idle_sources(m); - do { - int t; - - if (!block || idle) - t = 0; - else - t = calc_next_timeout(m); - + int t = block ? calc_next_timeout(m) : 0; + /*fprintf(stderr, "%u\n", t);*/ r = poll(m->pollfds, m->n_pollfds, t); } while (r < 0 && errno == EINTR); @@ -321,8 +497,6 @@ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { if (r > 0) dispatch_pollfds(m); - else if (r == 0 && idle) - run_fixed_or_idle(m, m->idle_sources); else if (r < 0) fprintf(stderr, "select(): %s\n", strerror(errno)); @@ -341,209 +515,7 @@ void pa_mainloop_quit(struct pa_mainloop *m, int r) { m->quit = r; } -/* IO sources */ -static void* mainloop_source_io(struct pa_mainloop_api*a, int fd, enum pa_mainloop_api_io_events events, void (*callback) (struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata) { - struct pa_mainloop *m; - struct mainloop_source_io *s; - assert(a && a->userdata && fd >= 0 && callback); - m = a->userdata; - assert(a == &m->api); - - s = pa_xmalloc(sizeof(struct mainloop_source_io)); - s->header.mainloop = m; - s->header.dead = 0; - - s->fd = fd; - s->events = events; - s->callback = callback; - s->userdata = userdata; - s->pollfd = NULL; - - pa_idxset_put(m->io_sources, s, NULL); - m->rebuild_pollfds = 1; - return s; -} - -static void mainloop_enable_io(struct pa_mainloop_api*a, void* id, enum pa_mainloop_api_io_events events) { - struct pa_mainloop *m; - struct mainloop_source_io *s = id; - assert(a && a->userdata && s && !s->header.dead); - m = a->userdata; - assert(a == &m->api && s->header.mainloop == m); - - s->events = events; - if (s->pollfd) - s->pollfd->events = ((s->events & PA_MAINLOOP_API_IO_EVENT_INPUT) ? POLLIN : 0) | ((s->events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) ? POLLOUT : 0); -} - -static void mainloop_cancel_io(struct pa_mainloop_api*a, void* id) { - struct pa_mainloop *m; - struct mainloop_source_io *s = id; - assert(a && a->userdata && s && !s->header.dead); - m = a->userdata; - assert(a == &m->api && s->header.mainloop == m); - - s->header.dead = 1; - m->io_sources_scan_dead = 1; - m->rebuild_pollfds = 1; -} - -/* Fixed sources */ -static void* mainloop_source_fixed(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata) { - struct pa_mainloop *m; - struct mainloop_source_fixed_or_idle *s; - assert(a && a->userdata && callback); - m = a->userdata; - assert(a == &m->api); - - s = pa_xmalloc(sizeof(struct mainloop_source_fixed_or_idle)); - s->header.mainloop = m; - s->header.dead = 0; - - s->enabled = 1; - s->callback = callback; - s->userdata = userdata; - - pa_idxset_put(m->fixed_sources, s, NULL); - return s; -} - -static void mainloop_enable_fixed(struct pa_mainloop_api*a, void* id, int b) { - struct pa_mainloop *m; - struct mainloop_source_fixed_or_idle *s = id; - assert(a && a->userdata && s && !s->header.dead); - m = a->userdata; - assert(a == &m->api); - - s->enabled = b; -} - -static void mainloop_cancel_fixed(struct pa_mainloop_api*a, void* id) { - struct pa_mainloop *m; - struct mainloop_source_fixed_or_idle *s = id; - assert(a && a->userdata && s && !s->header.dead); - m = a->userdata; - assert(a == &m->api); - - s->header.dead = 1; - m->fixed_sources_scan_dead = 1; -} - -/* Idle sources */ -static void* mainloop_source_idle(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata) { - struct pa_mainloop *m; - struct mainloop_source_fixed_or_idle *s; - assert(a && a->userdata && callback); - m = a->userdata; - assert(a == &m->api); - - s = pa_xmalloc(sizeof(struct mainloop_source_fixed_or_idle)); - s->header.mainloop = m; - s->header.dead = 0; - - s->enabled = 1; - s->callback = callback; - s->userdata = userdata; - - pa_idxset_put(m->idle_sources, s, NULL); - return s; -} - -static void mainloop_cancel_idle(struct pa_mainloop_api*a, void* id) { - struct pa_mainloop *m; - struct mainloop_source_fixed_or_idle *s = id; - assert(a && a->userdata && s && !s->header.dead); - m = a->userdata; - assert(a == &m->api); - - s->header.dead = 1; - m->idle_sources_scan_dead = 1; -} - -/* Time sources */ -static void* mainloop_source_time(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, void *id, const struct timeval *tv, void *userdata), void *userdata) { - struct pa_mainloop *m; - struct mainloop_source_time *s; - assert(a && a->userdata && callback); - m = a->userdata; - assert(a == &m->api); - - s = pa_xmalloc(sizeof(struct mainloop_source_time)); - s->header.mainloop = m; - s->header.dead = 0; - - s->enabled = !!tv; - if (tv) - s->timeval = *tv; - - s->callback = callback; - s->userdata = userdata; - - pa_idxset_put(m->time_sources, s, NULL); - return s; -} - -static void mainloop_enable_time(struct pa_mainloop_api*a, void *id, const struct timeval *tv) { - struct pa_mainloop *m; - struct mainloop_source_time *s = id; - assert(a && a->userdata && s && !s->header.dead); - m = a->userdata; - assert(a == &m->api); - - if (tv) { - s->enabled = 1; - s->timeval = *tv; - } else - s->enabled = 0; -} - -static void mainloop_cancel_time(struct pa_mainloop_api*a, void* id) { - struct pa_mainloop *m; - struct mainloop_source_time *s = id; - assert(a && a->userdata && s && !s->header.dead); - m = a->userdata; - assert(a == &m->api); - - s->header.dead = 1; - m->time_sources_scan_dead = 1; - -} - -static void mainloop_quit(struct pa_mainloop_api*a, int retval) { - struct pa_mainloop *m; - assert(a && a->userdata); - m = a->userdata; - assert(a == &m->api); - - m->quit = 1; - m->retval = retval; -} - -static void setup_api(struct pa_mainloop *m) { - assert(m); - - m->api.userdata = m; - m->api.source_io = mainloop_source_io; - m->api.enable_io = mainloop_enable_io; - m->api.cancel_io = mainloop_cancel_io; - - m->api.source_fixed = mainloop_source_fixed; - m->api.enable_fixed = mainloop_enable_fixed; - m->api.cancel_fixed = mainloop_cancel_fixed; - - m->api.source_idle = mainloop_source_idle; - m->api.enable_idle = mainloop_enable_fixed; /* (!) */ - m->api.cancel_idle = mainloop_cancel_idle; - - m->api.source_time = mainloop_source_time; - m->api.enable_time = mainloop_enable_time; - m->api.cancel_time = mainloop_cancel_time; - - m->api.quit = mainloop_quit; -} - struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m) { assert(m); return &m->api; } - diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index a0fa52db..5b4a7b73 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -42,8 +42,8 @@ struct userdata { snd_pcm_t *pcm_handle; struct pa_sink *sink; - void **io_sources; - unsigned n_io_sources; + struct pa_io_event **io_events; + unsigned n_io_events; size_t frame_size, fragment_size; struct pa_memchunk memchunk, silence; @@ -128,9 +128,9 @@ static void do_write(struct userdata *u) { } } -static void io_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct userdata *u = userdata; - assert(u && a && id); + assert(u && a && e); if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN) xrun_recovery(u); @@ -207,7 +207,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); - if (pa_create_io_sources(u->pcm_handle, c->mainloop, &u->io_sources, &u->n_io_sources, io_callback, u) < 0) { + if (pa_create_io_events(u->pcm_handle, c->mainloop, &u->io_events, &u->n_io_events, io_callback, u) < 0) { fprintf(stderr, __FILE__": failed to obtain file descriptors\n"); goto fail; } @@ -251,8 +251,8 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { if (u->sink) pa_sink_free(u->sink); - if (u->io_sources) - pa_free_io_sources(c->mainloop, u->io_sources, u->n_io_sources); + if (u->io_events) + pa_free_io_events(c->mainloop, u->io_events, u->n_io_events); if (u->pcm_handle) { snd_pcm_drop(u->pcm_handle); diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 8207d462..df716f73 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -42,8 +42,8 @@ struct userdata { snd_pcm_t *pcm_handle; struct pa_source *source; - void **io_sources; - unsigned n_io_sources; + struct pa_io_event **io_events; + unsigned n_io_events; size_t frame_size, fragment_size; struct pa_memchunk memchunk; @@ -128,9 +128,9 @@ static void do_read(struct userdata *u) { } } -static void io_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct userdata *u = userdata; - assert(u && a && id); + assert(u && a && e); if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN) xrun_recovery(u); @@ -189,7 +189,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); - if (pa_create_io_sources(u->pcm_handle, c->mainloop, &u->io_sources, &u->n_io_sources, io_callback, u) < 0) { + if (pa_create_io_events(u->pcm_handle, c->mainloop, &u->io_events, &u->n_io_events, io_callback, u) < 0) { fprintf(stderr, __FILE__": failed to obtain file descriptors\n"); goto fail; } @@ -230,8 +230,8 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { if (u->source) pa_source_free(u->source); - if (u->io_sources) - pa_free_io_sources(c->mainloop, u->io_sources, u->n_io_sources); + if (u->io_events) + pa_free_io_events(c->mainloop, u->io_events, u->n_io_events); if (u->pcm_handle) { snd_pcm_drop(u->pcm_handle); diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 37710fc5..ea768a98 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -59,7 +59,7 @@ struct userdata { void *in_mmap, *out_mmap; size_t in_mmap_length, out_mmap_length; - void *mainloop_source; + struct pa_io_event *io_event; struct pa_memblock **in_memblocks, **out_memblocks; unsigned out_current, in_current; @@ -195,14 +195,13 @@ static void do_read(struct userdata *u) { in_clear_memblocks(u, u->in_fragments/2); }; -static void io_callback(struct pa_mainloop_api *m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void io_callback(struct pa_mainloop_api *m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct userdata *u = userdata; + assert (u && u->core->mainloop == m && u->io_event == e); - assert (u && u->core->mainloop == m && u->mainloop_source == id); - - if (events & PA_MAINLOOP_API_IO_EVENT_INPUT) + if (f & PA_IO_EVENT_INPUT) do_read(u); - if (events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) + if (f & PA_IO_EVENT_OUTPUT) do_write(u); } @@ -352,8 +351,8 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { assert(u->source || u->sink); - u->mainloop_source = c->mainloop->source_io(c->mainloop, u->fd, (u->source ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | (u->sink ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), io_callback, u); - assert(u->mainloop_source); + u->io_event = c->mainloop->io_new(c->mainloop, u->fd, (u->source ? PA_IO_EVENT_INPUT : 0) | (u->sink ? PA_IO_EVENT_OUTPUT : 0), io_callback, u); + assert(u->io_event); pa_modargs_free(ma); @@ -403,8 +402,8 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { if (u->source) pa_source_free(u->source); - if (u->mainloop_source) - u->core->mainloop->cancel_io(u->core->mainloop, u->mainloop_source); + if (u->io_event) + u->core->mainloop->io_free(u->io_event); if (u->fd >= 0) close(u->fd); diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index dc2bc633..22d9f676 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -50,7 +50,7 @@ struct userdata { struct pa_sink *sink; struct pa_iochannel *io; - void *mainloop_source; + struct pa_defer_event *defer_event; struct pa_memchunk memchunk; struct pa_module *module; @@ -69,7 +69,7 @@ static void do_write(struct userdata *u) { ssize_t r; assert(u); - u->core->mainloop->enable_fixed(u->core->mainloop, u->mainloop_source, 0); + u->core->mainloop->defer_enable(u->defer_event, 0); if (!pa_iochannel_is_writable(u->io)) return; @@ -101,10 +101,10 @@ static void notify_cb(struct pa_sink*s) { assert(s && u); if (pa_iochannel_is_writable(u->io)) - u->core->mainloop->enable_fixed(u->core->mainloop, u->mainloop_source, 1); + u->core->mainloop->defer_enable(u->defer_event, 1); } -static void fixed_callback(struct pa_mainloop_api *m, void *id, void *userdata) { +static void defer_callback(struct pa_mainloop_api *m, struct pa_defer_event*e, void *userdata) { struct userdata *u = userdata; assert(u); do_write(u); @@ -175,9 +175,9 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->memchunk.memblock = NULL; u->memchunk.length = 0; - u->mainloop_source = c->mainloop->source_fixed(c->mainloop, fixed_callback, u); - assert(u->mainloop_source); - c->mainloop->enable_fixed(c->mainloop, u->mainloop_source, 0); + u->defer_event = c->mainloop->defer_new(c->mainloop, defer_callback, u); + assert(u->defer_event); + c->mainloop->defer_enable(u->defer_event, 0); u->module = m; m->userdata = u; @@ -210,7 +210,7 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { pa_sink_free(u->sink); pa_iochannel_free(u->io); - u->core->mainloop->cancel_fixed(u->core->mainloop, u->mainloop_source); + u->core->mainloop->defer_free(u->defer_event); assert(u->filename); unlink(u->filename); diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c index 2cf76099..5449e944 100644 --- a/polyp/module-x11-bell.c +++ b/polyp/module-x11-bell.c @@ -14,7 +14,7 @@ #include "namereg.h" struct x11_source { - void *io_source; + struct pa_io_event *io_event; struct x11_source *next; }; @@ -52,7 +52,7 @@ static int ring_bell(struct userdata *u, int percent) { return 0; } -static void io_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct userdata *u = userdata; assert(u); @@ -77,8 +77,8 @@ static void new_io_source(struct userdata *u, int fd) { struct x11_source *s; s = pa_xmalloc(sizeof(struct x11_source)); - s->io_source = u->core->mainloop->source_io(u->core->mainloop, fd, PA_MAINLOOP_API_IO_EVENT_INPUT, io_callback, u); - assert(s->io_source); + s->io_event = u->core->mainloop->io_new(u->core->mainloop, fd, PA_IO_EVENT_INPUT, io_callback, u); + assert(s->io_event); s->next = u->x11_sources; u->x11_sources = s; } @@ -149,7 +149,7 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { while (u->x11_sources) { struct x11_source *s = u->x11_sources; u->x11_sources = u->x11_sources->next; - c->mainloop->cancel_io(c->mainloop, s->io_source); + c->mainloop->io_free(s->io_event); pa_xfree(s); } diff --git a/polyp/module.c b/polyp/module.c index 8c5e318f..83bfa800 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -35,16 +35,16 @@ #define UNLOAD_POLL_TIME 10 -static void timeout_callback(struct pa_mainloop_api *m, void *id, const struct timeval *tv, void *userdata) { +static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { struct pa_core *c = userdata; struct timeval ntv; - assert(c && c->mainloop == m && c->auto_unload_mainloop_source == id); + assert(c && c->mainloop == m && c->auto_unload_event == e); pa_module_unload_unused(c); gettimeofday(&ntv, NULL); ntv.tv_sec += UNLOAD_POLL_TIME; - m->enable_time(m, id, &ntv); + m->time_restart(e, &ntv); } struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char *argument) { @@ -79,13 +79,13 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char if (!c->modules) c->modules = pa_idxset_new(NULL, NULL); - if (!c->auto_unload_mainloop_source) { + if (!c->auto_unload_event) { struct timeval ntv; gettimeofday(&ntv, NULL); ntv.tv_sec += UNLOAD_POLL_TIME; - c->auto_unload_mainloop_source = c->mainloop->source_time(c->mainloop, &ntv, timeout_callback, c); + c->auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); } - assert(c->auto_unload_mainloop_source); + assert(c->auto_unload_event); assert(c->modules); r = pa_idxset_put(c->modules, m, &m->index); @@ -159,9 +159,9 @@ void pa_module_unload_all(struct pa_core *c) { pa_idxset_free(c->modules, free_callback, NULL); c->modules = NULL; - if (c->auto_unload_mainloop_source) - c->mainloop->cancel_time(c->mainloop, c->auto_unload_mainloop_source); - c->auto_unload_mainloop_source = NULL; + if (c->auto_unload_event) + c->mainloop->time_free(c->auto_unload_event); + c->auto_unload_event = NULL; } static int unused_callback(void *p, uint32_t index, int *del, void *userdata) { @@ -193,7 +193,7 @@ struct once_info { uint32_t index; }; -static void module_unload_once_callback(void *userdata) { +static void module_unload_once_callback(struct pa_mainloop_api *m, void *userdata) { struct once_info *i = userdata; assert(i); pa_module_unload_by_index(i->core, i->index); diff --git a/polyp/module.h b/polyp/module.h index de195a4b..acc08c3e 100644 --- a/polyp/module.h +++ b/polyp/module.h @@ -59,5 +59,4 @@ void pa_module_done(struct pa_core *c, struct pa_module*m); void pa_module_set_used(struct pa_module*m, int used); - #endif diff --git a/polyp/native-common.h b/polyp/native-common.h index dc730e4b..d8a2a5ab 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -48,13 +48,15 @@ enum { PA_COMMAND_PLAY_SAMPLE, PA_COMMAND_REMOVE_SAMPLE, - PA_COMMAND_GET_SINK, - PA_COMMAND_GET_SOURCE, - PA_COMMAND_GET_MODULE, - PA_COMMAND_GET_CLIENT, - PA_COMMAND_GET_SINK_INPUT, - PA_COMMAND_GET_SOURCE_OUTPUT, - PA_COMMAND_GET_SAMPLE, + PA_COMMAND_GET_SINK_INFO, + PA_COMMAND_GET_SINK_INFO_LIST, + PA_COMMAND_GET_SOURCE_INFO, + PA_COMMAND_GET_SOURCE_INFO_LIST, + PA_COMMAND_GET_MODULE_INFO, + PA_COMMAND_GET_CLIENT_INFO, + PA_COMMAND_GET_SINK_INPUT_INFO, + PA_COMMAND_GET_SOURCE_OUTPUT_INFO, + PA_COMMAND_GET_SAMPLE_INFO, PA_COMMAND_SUBSCRIBE, PA_COMMAND_SUBSCRIBE_EVENT, diff --git a/polyp/pacat.c b/polyp/pacat.c index 55a0f6b9..4d8605c7 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -45,7 +45,7 @@ static struct pa_mainloop_api *mainloop_api = NULL; static void *buffer = NULL; static size_t buffer_length = 0, buffer_index = 0; -static void* stdio_source = NULL; +static struct pa_io_event* stdio_event = NULL; static void quit(int ret) { assert(mainloop_api); @@ -89,8 +89,8 @@ static void do_stream_write(size_t length) { static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) { assert(s && length); - if (stdio_source) - mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_INPUT); + if (stdio_event) + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_INPUT); if (!buffer) return; @@ -101,8 +101,8 @@ static void stream_write_callback(struct pa_stream *s, size_t length, void *user static void stream_read_callback(struct pa_stream *s, const void*data, size_t length, void *userdata) { assert(s && data && length); - if (stdio_source) - mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_OUTPUT); + if (stdio_event) + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); if (buffer) { fprintf(stderr, "Buffer overrrun, dropping incoming data\n"); @@ -174,13 +174,13 @@ static void stream_drain_complete(struct pa_stream*s, void *userdata) { fprintf(stderr, "Draining connection to server.\n"); } -static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { size_t l, w = 0; ssize_t r; - assert(a == mainloop_api && id && stdio_source == id); + assert(a == mainloop_api && e && stdio_event == e); if (buffer) { - mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_NULL); + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); return; } @@ -198,8 +198,8 @@ static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_m quit(1); } - mainloop_api->cancel_io(mainloop_api, stdio_source); - stdio_source = NULL; + mainloop_api->io_free(stdio_event); + stdio_event = NULL; return; } @@ -210,12 +210,12 @@ static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_m do_stream_write(w); } -static void stdout_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void stdout_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { ssize_t r; - assert(a == mainloop_api && id && stdio_source == id); + assert(a == mainloop_api && e && stdio_event == e); if (!buffer) { - mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_NULL); + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); return; } @@ -225,8 +225,8 @@ static void stdout_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_ fprintf(stderr, "write() failed: %s\n", strerror(errno)); quit(1); - mainloop_api->cancel_io(mainloop_api, stdio_source); - stdio_source = NULL; + mainloop_api->io_free(stdio_event); + stdio_event = NULL; return; } @@ -240,7 +240,7 @@ static void stdout_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_ } } -static void exit_signal_callback(void *id, int sig, void *userdata) { +static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got SIGINT, exiting.\n"); quit(0); @@ -258,7 +258,7 @@ static void stream_get_latency_callback(struct pa_stream *s, uint32_t latency, v fprintf(stderr, "Current latency is %u usecs.\n", latency); } -static void sigusr1_signal_callback(void *id, int sig, void *userdata) { +static void sigusr1_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { if (mode == PLAYBACK) { fprintf(stderr, "Got SIGUSR1, requesting latency.\n"); pa_stream_get_latency(stream, stream_get_latency_callback, NULL); @@ -289,14 +289,14 @@ int main(int argc, char *argv[]) { r = pa_signal_init(mainloop_api); assert(r == 0); - pa_signal_register(SIGINT, exit_signal_callback, NULL); - pa_signal_register(SIGUSR1, sigusr1_signal_callback, NULL); + pa_signal_new(SIGINT, exit_signal_callback, NULL); + pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); - if (!(stdio_source = mainloop_api->source_io(mainloop_api, - mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, - mode == PLAYBACK ? PA_MAINLOOP_API_IO_EVENT_INPUT : PA_MAINLOOP_API_IO_EVENT_OUTPUT, - mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) { + if (!(stdio_event = mainloop_api->io_new(mainloop_api, + mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, + mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT, + mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) { fprintf(stderr, "source_io() failed.\n"); goto quit; } diff --git a/polyp/pactl.c b/polyp/pactl.c index 28b187b0..2f3a4833 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -205,7 +205,7 @@ fail: quit(1); } -static void exit_signal_callback(void *id, int sig, void *userdata) { +static void exit_signal_callback(struct pa_mainloop_api *m, struct pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got SIGINT, exiting.\n"); quit(0); } @@ -284,7 +284,7 @@ int main(int argc, char *argv[]) { r = pa_signal_init(mainloop_api); assert(r == 0); - pa_signal_register(SIGINT, exit_signal_callback, NULL); + pa_signal_new(SIGINT, exit_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); if (!(context = pa_context_new(mainloop_api, argv[0]))) { diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index c34c6e0a..2d4c4d64 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -69,7 +69,7 @@ struct reply_info { void (*callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); void *userdata; uint32_t tag; - void *mainloop_timeout; + struct pa_time_event *time_event; int callback_is_running; }; @@ -87,7 +87,7 @@ static void reply_info_free(struct reply_info *r) { assert(r && r->pdispatch && r->pdispatch->mainloop); if (r->pdispatch) - r->pdispatch->mainloop->cancel_time(r->pdispatch->mainloop, r->mainloop_timeout); + r->pdispatch->mainloop->time_free(r->time_event); if (r->previous) r->previous->next = r->next; @@ -191,9 +191,9 @@ finish: return ret; } -static void timeout_callback(struct pa_mainloop_api*m, void *id, const struct timeval *tv, void *userdata) { +static void timeout_callback(struct pa_mainloop_api*m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { struct reply_info*r = userdata; - assert (r && r->mainloop_timeout == id && r->pdispatch && r->pdispatch->mainloop == m && r->callback); + assert (r && r->time_event == e && r->pdispatch && r->pdispatch->mainloop == m && r->callback); r->callback(r->pdispatch, PA_COMMAND_TIMEOUT, r->tag, NULL, r->userdata); reply_info_free(r); @@ -217,8 +217,8 @@ void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int time gettimeofday(&tv, NULL); tv.tv_sec += timeout; - r->mainloop_timeout = pd->mainloop->source_time(pd->mainloop, &tv, timeout_callback, r); - assert(r->mainloop_timeout); + r->time_event = pd->mainloop->time_new(pd->mainloop, &tv, timeout_callback, r); + assert(r->time_event); r->previous = NULL; r->next = pd->replies; diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c index 5c448a75..86634407 100644 --- a/polyp/play-memchunk.c +++ b/polyp/play-memchunk.c @@ -30,7 +30,7 @@ static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { return 0; } -static void si_kill(void *i) { +static void si_kill(struct pa_mainloop_api *m, void *i) { sink_input_kill(i); } diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index 0989a78d..71513565 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -18,33 +18,41 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -# Load audio drivers +# Load audio drivers statically + #load module-alsa-sink #load module-alsa-source device=plughw:1,0 -#load module-oss device="/dev/dsp" +#load module-oss device="/dev/dsp" sink_name=output source_name=input #load module-oss-mmap device="/dev/dsp" +# Load audio drivers automatically on access + +#autoload_sink_add output module-oss device="/dev/dsp" sink_name=output source_name=input +#autoload_source_add input module-oss device="/dev/dsp" sink_name=output source_name=input +autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +#autoload_sink_add output module-alsa-sink sink_name=output +#autoload_source_add input module-alsa-source source_name=input + # Load several protocols load module-esound-protocol-tcp load module-simple-protocol-tcp load module-native-protocol-unix load module-cli-protocol-unix -# Load X11 bell module -load module-x11-bell - # Load the CLI module load module-cli -autoload_sink_add oss_output module-oss device="/dev/dsp" sink_name=oss_output source_name=oss_input -autoload_source_add oss_input module-oss device="/dev/dsp" sink_name=oss_output source_name=oss_input - # Make some devices default -sink_default oss_output -source_default oss_input +sink_default output +source_default input .nofail # Load something to the sample cache scache_load /usr/share/sounds/KDE_Notify.wav x11-bell -scache_play x11-bell oss_output +scache_play x11-bell output + +# Load X11 bell module +load module-x11-bell sample=x11-bell sink=output + diff --git a/polyp/polyplib.h b/polyp/polyplib.h index 391cb0c8..08e6a5a5 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -97,4 +97,34 @@ void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +struct pa_sink_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec *sample_spec; + uint32_t owner_module; + uint32_t volume; + uint32_t monitor_source; + const char *monitor_source_name; + uint32_t latency; +}; + +void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, void *userdata), void *userdata); +void pa_context_get_sink_info_by_id(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, void *userdata), void *userdata); +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, void *userdata), void *userdata); + +struct pa_source_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec *sample_spec; + uint32_t owner_module; + uint32_t monitor_of_sink; + const char *monitor_of_sink_name; +}; + +void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, void *userdata), void *userdata); +void pa_context_get_source_info_by_id(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, void *userdata), void *userdata); +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, void *userdata), void *userdata); + #endif diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 5f6f02fa..b11e1992 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -74,7 +74,7 @@ struct connection { struct pa_sink_input *sink_input; struct pa_source_output *source_output; struct pa_memblockq *input_memblockq, *output_memblockq; - void *fixed_source; + struct pa_defer_event *defer_event; struct { struct pa_memblock *current_memblock; size_t memblock_index, fragment_size; @@ -183,8 +183,8 @@ static void connection_free(struct connection *c) { pa_iochannel_free(c->io); - if (c->fixed_source) - c->protocol->core->mainloop->cancel_fixed(c->protocol->core->mainloop, c->fixed_source); + if (c->defer_event) + c->protocol->core->mainloop->defer_free(c->defer_event); if (c->scache_memchunk.memblock) pa_memblock_unref(c->scache_memchunk.memblock); @@ -197,8 +197,8 @@ static void* connection_write(struct connection *c, size_t length) { size_t t, i; assert(c); - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + c->protocol->core->mainloop->defer_enable(c->defer_event, 1); t = c->write_data_length+length; @@ -381,7 +381,7 @@ static int esd_proto_get_latency(struct connection *c, esd_proto_t request, cons int latency, *lag; assert(c && !data && length == 0); - if (!(sink = pa_namereg(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) + if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) latency = 0; else { float usec = pa_sink_get_latency(sink); @@ -845,8 +845,8 @@ static int do_write(struct connection *c) { static void do_work(struct connection *c) { assert(c); - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 0); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + c->protocol->core->mainloop->defer_enable(c->defer_event, 0); if (pa_iochannel_is_hungup(c->io)) goto fail; @@ -872,11 +872,11 @@ static void io_callback(struct pa_iochannel*io, void *userdata) { do_work(c); } -/*** fixed callback ***/ +/*** defer callback ***/ -static void fixed_callback(struct pa_mainloop_api*a, void *id, void *userdata) { +static void defer_callback(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) { struct connection *c = userdata; - assert(a && c && c->fixed_source == id); + assert(a && c && c->defer_event == e); do_work(c); } @@ -901,8 +901,8 @@ static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { pa_memblockq_drop(c->input_memblockq, length); /* do something */ - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + c->protocol->core->mainloop->defer_enable(c->defer_event, 1); } static void sink_input_kill_cb(struct pa_sink_input *i) { @@ -926,8 +926,8 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me pa_memblockq_push(c->output_memblockq, chunk, 0); /* do something */ - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + c->protocol->core->mainloop->defer_enable(c->defer_event, 1); } static void source_output_kill_cb(struct pa_source_output *o) { @@ -981,8 +981,9 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->scache_memchunk.memblock = NULL; c->scache_name = NULL; - c->fixed_source = c->protocol->core->mainloop->source_fixed(c->protocol->core->mainloop, fixed_callback, c); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 0); + c->defer_event = c->protocol->core->mainloop->defer_new(c->protocol->core->mainloop, defer_callback, c); + assert(c->defer_event); + c->protocol->core->mainloop->defer_enable(c->defer_event, 0); pa_idxset_put(c->protocol->connections, c, &c->index); } diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index c0aef180..778677b3 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -127,6 +127,8 @@ static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t comma static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -150,6 +152,10 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_FINISH_UPLOAD_STREAM] = { command_finish_upload_stream }, [PA_COMMAND_PLAY_SAMPLE] = { command_play_sample }, [PA_COMMAND_REMOVE_SAMPLE] = { command_remove_sample }, + [PA_COMMAND_GET_SINK_INFO] = { command_get_info }, + [PA_COMMAND_GET_SOURCE_INFO] = { command_get_info }, + [PA_COMMAND_GET_SINK_INFO_LIST] = { command_get_info_list }, + [PA_COMMAND_GET_SOURCE_INFO_LIST] = { command_get_info_list }, }; /* structure management */ @@ -923,6 +929,122 @@ static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uin pa_pstream_send_simple_ack(c->pstream, tag); } +static void sink_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink *sink) { + assert(t && sink); + pa_tagstruct_putu32(t, sink->index); + pa_tagstruct_puts(t, sink->name); + pa_tagstruct_puts(t, sink->description); + pa_tagstruct_put_sample_spec(t, &sink->sample_spec); + pa_tagstruct_putu32(t, sink->owner ? sink->owner->index : (uint32_t) -1); + pa_tagstruct_putu32(t, sink->volume); + pa_tagstruct_putu32(t, sink->monitor_source->index); + pa_tagstruct_puts(t, sink->monitor_source->name); + pa_tagstruct_putu32(t, pa_sink_get_latency(sink)); +} + +static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *source) { + assert(t && source); + pa_tagstruct_putu32(t, source->index); + pa_tagstruct_puts(t, source->name); + pa_tagstruct_puts(t, source->description); + pa_tagstruct_put_sample_spec(t, &source->sample_spec); + pa_tagstruct_putu32(t, source->owner ? source->owner->index : (uint32_t) -1); + pa_tagstruct_putu32(t, source->monitor_of ? source->monitor_of->index : (uint32_t) -1); + pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : ""); +} + +static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t index; + struct pa_sink *sink = NULL; + struct pa_source *source = NULL; + const char *name; + struct pa_tagstruct *reply; + assert(c && t); + + if (pa_tagstruct_getu32(t, &index) < 0 || + pa_tagstruct_gets(t, &name) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (command == PA_COMMAND_GET_SINK_INFO) { + if (index != (uint32_t) -1) + sink = pa_idxset_get_by_index(c->protocol->core->sinks, index); + else + sink = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SINK, 1); + } else { + assert(command == PA_COMMAND_GET_SOURCE_INFO); + if (index != (uint32_t) -1) + source = pa_idxset_get_by_index(c->protocol->core->sources, index); + else + source = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SOURCE, 1); + } + + if (!sink && !source) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + reply = pa_tagstruct_new(NULL, 0); + assert(reply); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + if (sink) + sink_fill_tagstruct(reply, sink); + else + source_fill_tagstruct(reply, source); + pa_pstream_send_tagstruct(c->pstream, reply); +} + +static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + struct pa_idxset *i; + uint32_t index; + void *p; + struct pa_tagstruct *reply; + assert(c && t); + + if (!pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + reply = pa_tagstruct_new(NULL, 0); + assert(reply); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + + if (command == PA_COMMAND_GET_SINK_INFO_LIST) + i = c->protocol->core->sinks; + else { + assert(command == PA_COMMAND_GET_SOURCE_INFO_LIST); + i = c->protocol->core->sources; + } + + for (p = pa_idxset_first(i, &index); p; p = pa_idxset_next(i, &index)) { + if (command == PA_COMMAND_GET_SINK_INFO_LIST) + sink_fill_tagstruct(reply, p); + else { + assert(command == PA_COMMAND_GET_SOURCE_INFO_LIST); + source_fill_tagstruct(reply, p); + } + } + + pa_pstream_send_tagstruct(c->pstream, reply); +} + /*** pstream callbacks ***/ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index 4b3b1513..a95b356c 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -45,7 +45,7 @@ struct connection { struct pa_source_output *source_output; struct pa_client *client; struct pa_memblockq *input_memblockq, *output_memblockq; - void *fixed_source; + struct pa_defer_event *defer_event; struct { struct pa_memblock *current_memblock; @@ -91,8 +91,8 @@ static void connection_free(struct connection *c) { pa_memblockq_free(c->input_memblockq); if (c->output_memblockq) pa_memblockq_free(c->output_memblockq); - if (c->fixed_source) - c->protocol->core->mainloop->cancel_fixed(c->protocol->core->mainloop, c->fixed_source); + if (c->defer_event) + c->protocol->core->mainloop->defer_free(c->defer_event); pa_xfree(c); } @@ -169,8 +169,8 @@ static int do_write(struct connection *c) { static void do_work(struct connection *c) { assert(c); - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 0); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + c->protocol->core->mainloop->defer_enable(c->defer_event, 0); if (pa_iochannel_is_hungup(c->io)) goto fail; @@ -209,8 +209,8 @@ static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { pa_memblockq_drop(c->input_memblockq, length); /* do something */ - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + c->protocol->core->mainloop->defer_enable(c->defer_event, 1); } static void sink_input_kill_cb(struct pa_sink_input *i) { @@ -234,8 +234,8 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me pa_memblockq_push(c->output_memblockq, chunk, 0); /* do something */ - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + c->protocol->core->mainloop->defer_enable(c->defer_event, 1); } static void source_output_kill_cb(struct pa_source_output *o) { @@ -261,9 +261,9 @@ static void io_callback(struct pa_iochannel*io, void *userdata) { /*** fixed callback ***/ -static void fixed_callback(struct pa_mainloop_api*a, void *id, void *userdata) { +static void defer_callback(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) { struct connection *c = userdata; - assert(a && c && c->fixed_source == id); + assert(a && c && c->defer_event == e); do_work(c); } @@ -280,7 +280,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->io = io; c->sink_input = NULL; c->source_output = NULL; - c->fixed_source = NULL; + c->defer_event = NULL; c->input_memblockq = c->output_memblockq = NULL; c->protocol = p; c->playback.current_memblock = NULL; @@ -353,9 +353,9 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo pa_iochannel_set_callback(c->io, io_callback, c); pa_idxset_put(p->connections, c, NULL); - c->fixed_source = p->core->mainloop->source_fixed(p->core->mainloop, fixed_callback, c); - assert(c->fixed_source); - p->core->mainloop->enable_fixed(p->core->mainloop, c->fixed_source, 0); + c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c); + assert(c->defer_event); + p->core->mainloop->defer_enable(c->defer_event, 0); return; diff --git a/polyp/pstream.c b/polyp/pstream.c index e7441b24..4f071e4a 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -58,7 +58,7 @@ struct item_info { struct pa_pstream { struct pa_mainloop_api *mainloop; - struct mainloop_source *mainloop_source; + struct pa_defer_event *defer_event; struct pa_iochannel *io; struct pa_queue *send_queue; @@ -98,7 +98,7 @@ static void do_read(struct pa_pstream *p); static void do_something(struct pa_pstream *p) { assert(p && !p->shall_free); - p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 0); + p->mainloop->defer_enable(p->defer_event, 0); if (p->dead) return; @@ -139,9 +139,9 @@ static void io_callback(struct pa_iochannel*io, void *userdata) { do_something(p); } -static void fixed_callback(struct pa_mainloop_api *m, void *id, void*userdata) { +static void defer_callback(struct pa_mainloop_api *m, struct pa_defer_event *e, void*userdata) { struct pa_pstream *p = userdata; - assert(p && p->mainloop_source == id && p->mainloop == m); + assert(p && p->defer_event == e && p->mainloop == m); do_something(p); } @@ -159,8 +159,8 @@ struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel p->die_callback_userdata = NULL; p->mainloop = m; - p->mainloop_source = m->source_fixed(m, fixed_callback, p); - m->enable_fixed(m, p->mainloop_source, 0); + p->defer_event = m->defer_new(m, defer_callback, p); + m->defer_enable(p->defer_event, 0); p->send_queue = pa_queue_new(); assert(p->send_queue); @@ -223,7 +223,7 @@ void pa_pstream_free(struct pa_pstream *p) { if (p->read.packet) pa_packet_unref(p->read.packet); - p->mainloop->cancel_fixed(p->mainloop, p->mainloop_source); + p->mainloop->defer_free(p->defer_event); pa_xfree(p); } @@ -236,7 +236,7 @@ void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { i->packet = pa_packet_ref(packet); pa_queue_push(p->send_queue, i); - p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 1); + p->mainloop->defer_enable(p->defer_event, 1); } void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk) { @@ -252,7 +252,7 @@ void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t del pa_memblock_ref(i->chunk.memblock); pa_queue_push(p->send_queue, i); - p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 1); + p->mainloop->defer_enable(p->defer_event, 1); } void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata), void *userdata) { diff --git a/polyp/socket-client.c b/polyp/socket-client.c index c0c355de..e8cb2f92 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -41,8 +41,8 @@ struct pa_socket_client { struct pa_mainloop_api *mainloop; int fd; - - void *io_source, *fixed_source; + struct pa_io_event *io_event; + struct pa_defer_event *defer_event; void (*callback)(struct pa_socket_client*c, struct pa_iochannel *io, void *userdata); void *userdata; }; @@ -54,7 +54,8 @@ static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { c = pa_xmalloc(sizeof(struct pa_socket_client)); c->mainloop = m; c->fd = -1; - c->io_source = c->fixed_source = NULL; + c->io_event = NULL; + c->defer_event = NULL; c->callback = NULL; c->userdata = NULL; return c; @@ -95,19 +96,19 @@ failed: return; } -static void connect_fixed_cb(struct pa_mainloop_api *m, void *id, void *userdata) { +static void connect_fixed_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { struct pa_socket_client *c = userdata; - assert(m && c && c->fixed_source == id); - m->cancel_fixed(m, c->fixed_source); - c->fixed_source = NULL; + assert(m && c && c->defer_event == e); + m->defer_free(c->defer_event); + c->defer_event = NULL; do_call(c); } -static void connect_io_cb(struct pa_mainloop_api*m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void connect_io_cb(struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct pa_socket_client *c = userdata; - assert(m && c && c->io_source == id && fd >= 0); - m->cancel_io(m, c->io_source); - c->io_source = NULL; + assert(m && c && c->io_event == e && fd >= 0); + m->io_free(c->io_event); + c->io_event = NULL; do_call(c); } @@ -123,11 +124,11 @@ static int do_connect(struct pa_socket_client *c, const struct sockaddr *sa, soc return -1; } - c->io_source = c->mainloop->source_io(c->mainloop, c->fd, PA_MAINLOOP_API_IO_EVENT_OUTPUT, connect_io_cb, c); - assert(c->io_source); + c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c); + assert(c->io_event); } else { - c->fixed_source = c->mainloop->source_fixed(c->mainloop, connect_fixed_cb, c); - assert(c->fixed_source); + c->defer_event = c->mainloop->defer_new(c->mainloop, connect_fixed_cb, c); + assert(c->defer_event); } return 0; @@ -220,10 +221,10 @@ fail: void pa_socket_client_free(struct pa_socket_client *c) { assert(c && c->mainloop); - if (c->io_source) - c->mainloop->cancel_io(c->mainloop, c->io_source); - if (c->fixed_source) - c->mainloop->cancel_fixed(c->mainloop, c->fixed_source); + if (c->io_event) + c->mainloop->io_free(c->io_event); + if (c->defer_event) + c->mainloop->defer_free(c->defer_event); if (c->fd >= 0) close(c->fd); pa_xfree(c); diff --git a/polyp/socket-server.c b/polyp/socket-server.c index 5f332f0c..6af2c286 100644 --- a/polyp/socket-server.c +++ b/polyp/socket-server.c @@ -46,16 +46,16 @@ struct pa_socket_server { void (*on_connection)(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata); void *userdata; - void *mainloop_source; + struct pa_io_event *io_event; struct pa_mainloop_api *mainloop; enum { SOCKET_SERVER_GENERIC, SOCKET_SERVER_IPV4, SOCKET_SERVER_UNIX } type; }; -static void callback(struct pa_mainloop_api *mainloop, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void callback(struct pa_mainloop_api *mainloop, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct pa_socket_server *s = userdata; struct pa_iochannel *io; int nfd; - assert(s && s->mainloop == mainloop && s->mainloop_source == id && id && fd >= 0 && fd == s->fd && events == PA_MAINLOOP_API_IO_EVENT_INPUT); + assert(s && s->mainloop == mainloop && s->io_event == e && e && fd >= 0 && fd == s->fd); if ((nfd = accept(fd, NULL, NULL)) < 0) { fprintf(stderr, "accept(): %s\n", strerror(errno)); @@ -89,8 +89,8 @@ struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd) s->userdata = NULL; s->mainloop = m; - s->mainloop_source = m->source_io(m, fd, PA_MAINLOOP_API_IO_EVENT_INPUT, callback, s); - assert(s->mainloop_source); + s->io_event = m->io_new(m, fd, PA_IO_EVENT_INPUT, callback, s); + assert(s->io_event); s->type = SOCKET_SERVER_GENERIC; @@ -193,7 +193,7 @@ void pa_socket_server_free(struct pa_socket_server*s) { pa_xfree(s->filename); } - s->mainloop->cancel_io(s->mainloop, s->mainloop_source); + s->mainloop->io_free(s->io_event); pa_xfree(s); } diff --git a/polyp/xmalloc.h b/polyp/xmalloc.h index 5f58a8ad..45209b05 100644 --- a/polyp/xmalloc.h +++ b/polyp/xmalloc.h @@ -2,6 +2,7 @@ #define foomemoryhfoo #include +#include void* pa_xmalloc(size_t l); void *pa_xmalloc0(size_t l); -- cgit