mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
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:
parent
839f99ffbf
commit
964bdfd1e8
36 changed files with 1312 additions and 628 deletions
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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\
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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
503
polyp/glib-mainloop.c
Normal 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
14
polyp/glib-mainloop.h
Normal 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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
11
polyp/main.c
11
polyp/main.c
|
|
@ -46,13 +46,12 @@
|
|||
|
||||
static struct pa_mainloop *mainloop;
|
||||
|
||||
static void exit_signal_callback(void *id, int sig, void *userdata) {
|
||||
struct pa_mainloop_api* m = pa_mainloop_get_api(mainloop);
|
||||
static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
|
||||
m->quit(m, 1);
|
||||
fprintf(stderr, __FILE__": got signal.\n");
|
||||
}
|
||||
|
||||
static void aux_signal_callback(void *id, int sig, void *userdata) {
|
||||
static void aux_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
|
||||
struct pa_core *c = userdata;
|
||||
assert(c);
|
||||
pa_module_load(c, sig == SIGUSR1 ? "module-cli" : "module-cli-protocol-unix", NULL);
|
||||
|
|
@ -135,14 +134,14 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
r = pa_signal_init(pa_mainloop_get_api(mainloop));
|
||||
assert(r == 0);
|
||||
pa_signal_register(SIGINT, exit_signal_callback, NULL);
|
||||
pa_signal_new(SIGINT, exit_signal_callback, NULL);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
c = pa_core_new(pa_mainloop_get_api(mainloop));
|
||||
assert(c);
|
||||
|
||||
pa_signal_register(SIGUSR1, aux_signal_callback, c);
|
||||
pa_signal_register(SIGUSR2, aux_signal_callback, c);
|
||||
pa_signal_new(SIGUSR1, aux_signal_callback, c);
|
||||
pa_signal_new(SIGUSR2, aux_signal_callback, c);
|
||||
|
||||
buf = pa_strbuf_new();
|
||||
assert(buf);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
620
polyp/mainloop.c
620
polyp/mainloop.c
|
|
@ -38,42 +38,42 @@
|
|||
#include "idxset.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
struct mainloop_source_header {
|
||||
struct pa_base_event {
|
||||
};
|
||||
|
||||
struct pa_io_event {
|
||||
struct pa_mainloop *mainloop;
|
||||
int dead;
|
||||
};
|
||||
|
||||
struct mainloop_source_io {
|
||||
struct mainloop_source_header header;
|
||||
|
||||
int fd;
|
||||
enum pa_mainloop_api_io_events events;
|
||||
void (*callback) (struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata);
|
||||
void *userdata;
|
||||
|
||||
enum pa_io_event_flags events;
|
||||
void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata);
|
||||
struct pollfd *pollfd;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]))) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue