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
This commit is contained in:
Lennart Poettering 2004-08-05 19:53:57 +00:00
parent 839f99ffbf
commit 964bdfd1e8
36 changed files with 1312 additions and 628 deletions

View file

@ -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"

View file

@ -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\

View file

@ -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);
}

View file

@ -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

View file

@ -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();

View file

@ -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);

503
polyp/glib-mainloop.c Normal file
View file

@ -0,0 +1,503 @@
#include <assert.h>
#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));
}

14
polyp/glib-mainloop.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef fooglibmainloophfoo
#define fooglibmainloophfoo
#include <glib.h>
#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

View file

@ -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);
}

View file

@ -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);

View file

@ -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);
}

View file

@ -25,41 +25,43 @@
#include <time.h>
#include <sys/time.h>
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);
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));
/* 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);
/* 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

View file

@ -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);
api->cancel_io(api, mainloop_source);
mainloop_source = NULL;
while (signals)
pa_signal_free(signals);
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(s->sig, &s->saved_sigaction, NULL);
pa_xfree(s);
sigaction(e->sig, &e->saved_sigaction, NULL);
if (e->destroy_callback)
e->destroy_callback(api, e, e->userdata);
pa_xfree(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)) {
assert(e);
e->destroy_callback = callback;
}

View file

@ -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

View file

@ -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;
};
struct mainloop_source_fixed_or_idle {
struct mainloop_source_header header;
int enabled;
void (*callback)(struct pa_mainloop_api*a, void *id, void *userdata);
void *userdata;
void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata);
};
struct mainloop_source_time {
struct mainloop_source_header header;
struct pa_time_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_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 pa_defer_event {
struct pa_mainloop *mainloop;
int dead;
int enabled;
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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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

View file

@ -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,

View file

@ -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;
}

View file

@ -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]))) {

View file

@ -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;

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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) {

View file

@ -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;

View file

@ -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) {

View file

@ -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);

View file

@ -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);
}

View file

@ -2,6 +2,7 @@
#define foomemoryhfoo
#include <sys/types.h>
#include <stdlib.h>
void* pa_xmalloc(size_t l);
void *pa_xmalloc0(size_t l);