]> code.delx.au - pulseaudio/commitdiff
add initial glib mainloop adapter
authorLennart Poettering <lennart@poettering.net>
Thu, 5 Aug 2004 19:53:57 +0000 (19:53 +0000)
committerLennart Poettering <lennart@poettering.net>
Thu, 5 Aug 2004 19:53:57 +0000 (19:53 +0000)
clean up mainloop API

git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@105 fefdeb5f-60dc-0310-8127-8f9354f1896f

36 files changed:
configure.ac
polyp/Makefile.am
polyp/alsa-util.c
polyp/alsa-util.h
polyp/core.c
polyp/core.h
polyp/glib-mainloop.c [new file with mode: 0644]
polyp/glib-mainloop.h [new file with mode: 0644]
polyp/iochannel.c
polyp/main.c
polyp/mainloop-api.c
polyp/mainloop-api.h
polyp/mainloop-signal.c
polyp/mainloop-signal.h
polyp/mainloop.c
polyp/module-alsa-sink.c
polyp/module-alsa-source.c
polyp/module-oss-mmap.c
polyp/module-pipe-sink.c
polyp/module-x11-bell.c
polyp/module.c
polyp/module.h
polyp/native-common.h
polyp/pacat.c
polyp/pactl.c
polyp/pdispatch.c
polyp/play-memchunk.c
polyp/polypaudio.pa
polyp/polyplib.h
polyp/protocol-esound.c
polyp/protocol-native.c
polyp/protocol-simple.c
polyp/pstream.c
polyp/socket-client.c
polyp/socket-server.c
polyp/xmalloc.h

index 9e5352a5edf135d9807788f6103b7664d6f9bb22..3183d1743e2f822974508bcef214aa5751d88214 100644 (file)
@@ -54,6 +54,10 @@ PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ])
 AC_SUBST(ASOUNDLIB_CFLAGS)
 AC_SUBST(ASOUNDLIB_LIBS)
 
+PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ])
+AC_SUBST(GLIB20_CFLAGS)
+AC_SUBST(GLIB20_LIBS)
+
 # If using GCC specifiy some additional parameters
 if test "x$GCC" = "xyes" ; then
    CFLAGS="$CFLAGS -pipe -Wall -W -Wno-unused-parameter"
index 0af99110fab3d39956283c23ee16598ff3e32f23..c0be8ce0818b5dadcf03b880882e50e536aeaf70 100644 (file)
@@ -71,7 +71,8 @@ pkglib_LTLIBRARIES=libiochannel.la \
 lib_LTLIBRARIES=libpolyp.la \
                libpolyp-simple.la \
                libpolyp-error.la \
-               libpolyp-mainloop.la
+               libpolyp-mainloop.la \
+               libpolyp-mainloop-glib.la
 
 polypaudio_SOURCES = idxset.c idxset.h \
                queue.c queue.h \
@@ -307,6 +308,10 @@ parec_simple_SOURCES = parec-simple.c
 parec_simple_LDADD = $(AM_LDADD) libpolyp-simple.la libpolyp-error.la
 parec_simple_CFLAGS = $(AM_CFLAGS)
 
+libpolyp_mainloop_glib_la_SOURCES = glib-mainloop.h glib-mainloop.c
+libpolyp_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS)
+libpolyp_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop.la $(GLIB20_LIBS)
+
 if BUILD_LIBPOLYPCORE
 
 pkginclude_HEADERS+=cli-command.h\
index 43562378da419411712b4f7206f50d15c0e0776d..70e2e0725e18b5415eefa08cb3badab1f38adbd6 100644 (file)
@@ -59,26 +59,26 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint
     return ret;
 }
 
-int pa_create_io_sources(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, void ***io_sources, unsigned *n_io_sources, void (*cb)(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata) {
+int pa_create_io_events(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, struct pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata) {
     unsigned i;
     struct pollfd *pfds, *ppfd;
-    void **ios;
-    assert(pcm_handle && m && io_sources && n_io_sources && cb);
+    struct pa_io_event **ios;
+    assert(pcm_handle && m && io_events && n_io_events && cb);
 
-    *n_io_sources = snd_pcm_poll_descriptors_count(pcm_handle);
+    *n_io_events = snd_pcm_poll_descriptors_count(pcm_handle);
 
-    pfds = pa_xmalloc(sizeof(struct pollfd) * *n_io_sources);
-    if (snd_pcm_poll_descriptors(pcm_handle, pfds, *n_io_sources) < 0) {
+    pfds = pa_xmalloc(sizeof(struct pollfd) * *n_io_events);
+    if (snd_pcm_poll_descriptors(pcm_handle, pfds, *n_io_events) < 0) {
         pa_xfree(pfds);
         return -1;
     }
     
-    *io_sources = pa_xmalloc(sizeof(void*) * *n_io_sources);
+    *io_events = pa_xmalloc(sizeof(void*) * *n_io_events);
 
-    for (i = 0, ios = *io_sources, ppfd = pfds; i < *n_io_sources; i++, ios++, ppfd++) {
-        *ios = m->source_io(m, ppfd->fd,
-                            ((ppfd->events & POLLIN) ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) |
-                            ((ppfd->events & POLLOUT) ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), cb, userdata);
+    for (i = 0, ios = *io_events, ppfd = pfds; i < *n_io_events; i++, ios++, ppfd++) {
+        *ios = m->io_new(m, ppfd->fd,
+                            ((ppfd->events & POLLIN) ? PA_IO_EVENT_INPUT : 0) |
+                            ((ppfd->events & POLLOUT) ? PA_IO_EVENT_OUTPUT : 0), cb, userdata);
         assert(*ios);
     }
 
@@ -86,12 +86,12 @@ int pa_create_io_sources(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, void
     return 0;
 }
 
-void pa_free_io_sources(struct pa_mainloop_api* m, void **io_sources, unsigned n_io_sources) {
+void pa_free_io_events(struct pa_mainloop_api* m, struct pa_io_event **io_events, unsigned n_io_events) {
     unsigned i;
-    void **ios;
-    assert(m && io_sources);
+    struct pa_io_event **ios;
+    assert(m && io_events);
     
-    for (ios = io_sources, i = 0; i < n_io_sources; i++, ios++)
-        m->cancel_io(m, *ios);
-    pa_xfree(io_sources);
+    for (ios = io_events, i = 0; i < n_io_events; i++, ios++)
+        m->io_free(*ios);
+    pa_xfree(io_events);
 }
index 03e427d900233b029dfb09be2efe347197b8f282..2627a75c94ff4aa648f373aeacc7962d6ecacb7f 100644 (file)
@@ -29,7 +29,7 @@
 
 int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *buffer_size);
 
-int pa_create_io_sources(snd_pcm_t *pcm_handle, struct pa_mainloop_api *m, void ***io_sources, unsigned *n_io_sources, void (*cb)(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata);
-void pa_free_io_sources(struct pa_mainloop_api* m, void **io_sources, unsigned n_io_sources);
+int pa_create_io_events(snd_pcm_t *pcm_handle, struct pa_mainloop_api *m, struct pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata);
+void pa_free_io_events(struct pa_mainloop_api* m, struct pa_io_event **io_sources, unsigned n_io_sources);
 
 #endif
index ffc11cec94f3ae233283ce5eadcc43ad7335605c..0444fa9677a22c8215e71e739edc37323dd827f0 100644 (file)
@@ -62,6 +62,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) {
     c->default_sample_spec.channels = 2;
 
     c->auto_unload_time = 20;
+    c->auto_unload_event = NULL;
     
     pa_check_for_sigpipe();
     
index b125083d7dd7586477814033671e9a011674d2db..e1e48cbcb4d215ae7f5f8826aafcf4fed4b104cc 100644 (file)
@@ -38,7 +38,7 @@ struct pa_core {
 
     struct pa_sample_spec default_sample_spec;
     int auto_unload_time;
-    void *auto_unload_mainloop_source;
+    struct pa_time_event *auto_unload_event;
 };
 
 struct pa_core* pa_core_new(struct pa_mainloop_api *m);
diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c
new file mode 100644 (file)
index 0000000..978cad0
--- /dev/null
@@ -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));
+}
diff --git a/polyp/glib-mainloop.h b/polyp/glib-mainloop.h
new file mode 100644 (file)
index 0000000..50fe8b9
--- /dev/null
@@ -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
index 77f8fb0866f2a77437b288f086c449b1c1616d8e..813347d421b76c74b888c93a8e20c9f201252fe6 100644 (file)
@@ -46,50 +46,50 @@ struct pa_iochannel {
     
     int no_close;
 
-    void* input_source, *output_source;
+    struct pa_io_event* input_event, *output_event;
 };
 
 static void enable_mainloop_sources(struct pa_iochannel *io) {
     assert(io);
 
-    if (io->input_source == io->output_source) {
-        enum pa_mainloop_api_io_events e = PA_MAINLOOP_API_IO_EVENT_NULL;
-        assert(io->input_source);
+    if (io->input_event == io->output_event) {
+        enum pa_io_event_flags f = PA_IO_EVENT_NULL;
+        assert(io->input_event);
         
         if (!io->readable)
-            e |= PA_MAINLOOP_API_IO_EVENT_INPUT;
+            f |= PA_IO_EVENT_INPUT;
         if (!io->writable)
-            e |= PA_MAINLOOP_API_IO_EVENT_OUTPUT;
+            f |= PA_IO_EVENT_OUTPUT;
 
-        io->mainloop->enable_io(io->mainloop, io->input_source, e);
+        io->mainloop->io_enable(io->input_event, f);
     } else {
-        if (io->input_source)
-            io->mainloop->enable_io(io->mainloop, io->input_source, io->readable ? PA_MAINLOOP_API_IO_EVENT_NULL : PA_MAINLOOP_API_IO_EVENT_INPUT);
-        if (io->output_source)
-            io->mainloop->enable_io(io->mainloop, io->output_source, io->writable ? PA_MAINLOOP_API_IO_EVENT_NULL : PA_MAINLOOP_API_IO_EVENT_OUTPUT);
+        if (io->input_event)
+            io->mainloop->io_enable(io->input_event, io->readable ? PA_IO_EVENT_NULL : PA_IO_EVENT_INPUT);
+        if (io->output_event)
+            io->mainloop->io_enable(io->output_event, io->writable ? PA_IO_EVENT_NULL : PA_IO_EVENT_OUTPUT);
     }
 }
 
-static void callback(struct pa_mainloop_api* m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) {
+static void callback(struct pa_mainloop_api* m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) {
     struct pa_iochannel *io = userdata;
     int changed = 0;
-    assert(m && fd >= 0 && events && userdata);
+    assert(m && e && fd >= 0 && userdata);
 
-    if ((events & PA_MAINLOOP_API_IO_EVENT_HUP) && !io->hungup) {
+    if ((f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) && !io->hungup) {
         io->hungup = 1;
         changed = 1;
     }
     
-    if ((events & PA_MAINLOOP_API_IO_EVENT_INPUT) && !io->readable) {
+    if ((f & PA_IO_EVENT_INPUT) && !io->readable) {
         io->readable = 1;
         changed = 1;
-        assert(id == io->input_source);
+        assert(e == io->input_event);
     }
     
-    if ((events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) && !io->writable) {
+    if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) {
         io->writable = 1;
         changed = 1;
-        assert(id == io->output_source);
+        assert(e == io->output_event);
     }
 
     if (changed) {
@@ -116,23 +116,23 @@ struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd
     io->hungup = 0;
     io->no_close = 0;
 
+    io->input_event = io->output_event = NULL;
+
     if (ifd == ofd) {
         assert(ifd >= 0);
         pa_make_nonblock_fd(io->ifd);
-        io->input_source = io->output_source = m->source_io(m, ifd, PA_MAINLOOP_API_IO_EVENT_BOTH, callback, io);
+        io->input_event = io->output_event = m->io_new(m, ifd, PA_IO_EVENT_INPUT|PA_IO_EVENT_OUTPUT, callback, io);
     } else {
 
         if (ifd >= 0) {
             pa_make_nonblock_fd(io->ifd);
-            io->input_source = m->source_io(m, ifd, PA_MAINLOOP_API_IO_EVENT_INPUT, callback, io);
-        } else
-            io->input_source = NULL;
+            io->input_event = m->io_new(m, ifd, PA_IO_EVENT_INPUT, callback, io);
+        }
 
         if (ofd >= 0) {
             pa_make_nonblock_fd(io->ofd);
-            io->output_source = m->source_io(m, ofd, PA_MAINLOOP_API_IO_EVENT_OUTPUT, callback, io);
-        } else
-            io->output_source = NULL;
+            io->output_event = m->io_new(m, ofd, PA_IO_EVENT_OUTPUT, callback, io);
+        }
     }
 
     return io;
@@ -141,17 +141,17 @@ struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd
 void pa_iochannel_free(struct pa_iochannel*io) {
     assert(io);
 
+    if (io->input_event)
+        io->mainloop->io_free(io->input_event);
+    if (io->output_event && (io->output_event != io->input_event))
+        io->mainloop->io_free(io->output_event);
+
     if (!io->no_close) {
         if (io->ifd >= 0)
             close(io->ifd);
         if (io->ofd >= 0 && io->ofd != io->ifd)
             close(io->ofd);
     }
-
-    if (io->input_source)
-        io->mainloop->cancel_io(io->mainloop, io->input_source);
-    if (io->output_source && (io->output_source != io->input_source))
-        io->mainloop->cancel_io(io->mainloop, io->output_source);
     
     pa_xfree(io);
 }
index de66f1c88cc4cdaab3a79c0f2300bbc4119ba662..9f3d3406319b47bbd2589fe1e0ff2789d7784269 100644 (file)
 
 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);
index 8b4e09ac51976876667caf8379e05e2741319240..952fce0a175ca8df4116f0d9bd6b37aded025b37 100644 (file)
 #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);
 }
 
index 0228f580cd2dd355471b6d92e4cdec54142c31b1..4c8e379ba58187b086901fb31555cbfc18e56214 100644 (file)
 #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);
-
-    /* Fixed sources */
-    void* (*source_fixed)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata);
-    void  (*enable_fixed)(struct pa_mainloop_api*a, void* id, int b);
-    void  (*cancel_fixed)(struct pa_mainloop_api*a, void* id);
+    struct pa_io_event* (*io_new)(struct pa_mainloop_api*a, int fd, enum pa_io_event_flags events, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event* e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata);
+    void (*io_enable)(struct pa_io_event* e, enum pa_io_event_flags events);
+    void (*io_free)(struct pa_io_event* e);
+    void (*io_set_destroy)(struct pa_io_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata));
 
-    /* Idle sources */
-    void* (*source_idle)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata);
-    void  (*enable_idle)(struct pa_mainloop_api*a, void* id, int b);
-    void  (*cancel_idle)(struct pa_mainloop_api*a, void* id);
-    
     /* Time sources */
-    void* (*source_time)(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, void *id, const struct timeval *tv, void *userdata), void *userdata);
-    void  (*enable_time)(struct pa_mainloop_api*a, void *id, const struct timeval *tv);
-    void  (*cancel_time)(struct pa_mainloop_api*a, void* id);
+    struct pa_time_event* (*time_new)(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event* e, const struct timeval *tv, void *userdata), void *userdata);
+    void (*time_restart)(struct pa_time_event* e, const struct timeval *tv);
+    void (*time_free)(struct pa_time_event* e);
+    void (*time_set_destroy)(struct pa_time_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata));
+
+    /* Deferred sources */
+    struct pa_defer_event* (*defer_new)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event* e, void *userdata), void *userdata);
+    void (*defer_enable)(struct pa_defer_event* e, int b);
+    void (*defer_free)(struct pa_defer_event* e);
+    void (*defer_set_destroy)(struct pa_defer_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata));
 
     /* Exit mainloop */
     void (*quit)(struct pa_mainloop_api*a, int retval);
 };
 
-void pa_mainloop_api_once(struct pa_mainloop_api*m, void (*callback)(void *userdata), void *userdata);
+void pa_mainloop_api_once(struct pa_mainloop_api*m, void (*callback)(struct pa_mainloop_api*m, void *userdata), void *userdata);
 
 #endif
index 6e79767a9566830622e3527b033c62dc17481944..f7ff7e93be257dde000e249bb6fe43091946dec3 100644 (file)
 #include "util.h"
 #include "xmalloc.h"
 
-struct signal_info {
+struct pa_signal_event {
     int sig;
     struct sigaction saved_sigaction;
-    void (*callback) (void *id, int signal, void *userdata);
+    void (*callback) (struct pa_mainloop_api*a, struct pa_signal_event *e, int signal, void *userdata);
     void *userdata;
-    struct signal_info *previous, *next;
+    void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_signal_event*e, void *userdata);
+    struct pa_signal_event *previous, *next;
 };
 
 static struct pa_mainloop_api *api = NULL;
 static int signal_pipe[2] = { -1, -1 };
-static void* mainloop_source = NULL;
-static struct signal_info *signals = NULL;
+static struct pa_io_event* io_event = NULL;
+static struct pa_signal_event *signals = NULL;
 
 static void signal_handler(int sig) {
     write(signal_pipe[1], &sig, sizeof(sig));
 }
 
-static void callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) {
-    assert(a && id && events == PA_MAINLOOP_API_IO_EVENT_INPUT && id == mainloop_source && fd == signal_pipe[0]);
+static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) {
+    assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]);
 
     for (;;) {
         ssize_t r;
         int sig;
-        struct signal_info*s;
+        struct pa_signal_event*s;
         
         if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) {
             if (errno == EAGAIN)
@@ -76,14 +77,15 @@ static void callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloo
         for (s = signals; s; s = s->next) 
             if (s->sig == sig) {
                 assert(s->callback);
-                s->callback(s, sig, s->userdata);
+                s->callback(a, s, sig, s->userdata);
                 break;
             }
     }
 }
 
 int pa_signal_init(struct pa_mainloop_api *a) {
-    assert(a);
+    assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event);
+    
     if (pipe(signal_pipe) < 0) {
         fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
         return -1;
@@ -93,71 +95,80 @@ int pa_signal_init(struct pa_mainloop_api *a) {
     pa_make_nonblock_fd(signal_pipe[1]);
 
     api = a;
-    mainloop_source = api->source_io(api, signal_pipe[0], PA_MAINLOOP_API_IO_EVENT_INPUT, callback, NULL);
-    assert(mainloop_source);
+    io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL);
+    assert(io_event);
     return 0;
 }
 
 void pa_signal_done(void) {
-    assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && mainloop_source);
+    assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && io_event);
+
+    while (signals)
+        pa_signal_free(signals);
 
-    api->cancel_io(api, mainloop_source);
-    mainloop_source = NULL;
+    api->io_free(io_event);
+    io_event = NULL;
 
     close(signal_pipe[0]);
     close(signal_pipe[1]);
     signal_pipe[0] = signal_pipe[1] = -1;
 
-    while (signals)
-        pa_signal_unregister(signals);
-    
     api = NULL;
 }
 
-void* pa_signal_register(int sig, void (*callback) (void *id, int signal, void *userdata), void *userdata) {
-    struct signal_info *s = NULL;
+struct pa_signal_event* pa_signal_new(int sig, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, int sig, void *userdata), void *userdata) {
+    struct pa_signal_event *e = NULL;
     struct sigaction sa;
     assert(sig > 0 && callback);
-
-    for (s = signals; s; s = s->next)
-        if (s->sig == sig)
+    
+    for (e = signals; e; e = e->next)
+        if (e->sig == sig)
             goto fail;
     
-    s = pa_xmalloc(sizeof(struct signal_info));
-    s->sig = sig;
-    s->callback = callback;
-    s->userdata = userdata;
+    e = pa_xmalloc(sizeof(struct pa_signal_event));
+    e->sig = sig;
+    e->callback = callback;
+    e->userdata = userdata;
+    e->destroy_callback = NULL;
 
     memset(&sa, 0, sizeof(sa));
     sa.sa_handler = signal_handler;
     sigemptyset(&sa.sa_mask);
     sa.sa_flags = SA_RESTART;
     
-    if (sigaction(sig, &sa, &s->saved_sigaction) < 0)
+    if (sigaction(sig, &sa, &e->saved_sigaction) < 0)
         goto fail;
 
-    s->previous = NULL;
-    s->next = signals;
-    signals = s;
+    e->previous = NULL;
+    e->next = signals;
+    signals = e;
 
-    return s;
+    return e;
 fail:
-    if (s)
-        pa_xfree(s);
+    if (e)
+        pa_xfree(e);
     return NULL;
 }
 
-void pa_signal_unregister(void *id) {
-    struct signal_info *s = id;
-    assert(s);
+void pa_signal_free(struct pa_signal_event *e) {
+    assert(e);
 
-    if (s->next)
-        s->next->previous = s->previous;
-    if (s->previous)
-        s->previous->next = s->next;
+    if (e->next)
+        e->next->previous = e->previous;
+    if (e->previous)
+        e->previous->next = e->next;
     else
-        signals = s->next;
+        signals = e->next;
+
+    sigaction(e->sig, &e->saved_sigaction, NULL);
+
+    if (e->destroy_callback)
+        e->destroy_callback(api, e, e->userdata);
+    
+    pa_xfree(e);
+}
 
-    sigaction(s->sig, &s->saved_sigaction, NULL);
-    pa_xfree(s);
+void pa_signal_set_destroy(struct pa_signal_event *e, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, void *userdata)) {
+    assert(e);
+    e->destroy_callback = callback;
 }
index 8afe9c8d1cffbe34f8555957e4b4dc15d60da04d..dacbc153438c434418e6c4e7f30a22f48c9aeec6 100644 (file)
 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
index f3d8e781bb49bce2afeddf1d9aeb9a84441046fc..c678537eb5520c353354ecfd6b8f72e6cee99bd7 100644 (file)
 #include "idxset.h"
 #include "xmalloc.h"
 
-struct mainloop_source_header {
+struct pa_base_event {
+};
+
+struct pa_io_event {
     struct pa_mainloop *mainloop;
     int dead;
-};
-    
-struct mainloop_source_io {
-    struct mainloop_source_header header;
-    
     int fd;
-    enum pa_mainloop_api_io_events events;
-    void (*callback) (struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata);
-    void *userdata;
-
+    enum pa_io_event_flags events;
+    void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata);
     struct pollfd *pollfd;
+    void *userdata;
+    void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata);
 };
 
-struct mainloop_source_fixed_or_idle {
-    struct mainloop_source_header header;
+struct pa_time_event {
+    struct pa_mainloop *mainloop;
+    int dead;
     int enabled;
-
-    void (*callback)(struct pa_mainloop_api*a, void *id, void *userdata);
+    struct timeval timeval;
+    void (*callback)(struct pa_mainloop_api*a, struct pa_time_event *e, const struct timeval*tv, void *userdata);
     void *userdata;
+    void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata);
 };
 
-struct mainloop_source_time {
-    struct mainloop_source_header header;
+struct pa_defer_event {
+    struct pa_mainloop *mainloop;
+    int dead;
     int enabled;
-    
-    struct timeval timeval;
-    void (*callback)(struct pa_mainloop_api*a, void *id, const struct timeval*tv, void *userdata);
+    void (*callback)(struct pa_mainloop_api*a, struct pa_defer_event*e, void *userdata);
     void *userdata;
+    void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata);
 };
 
 struct pa_mainloop {
-    struct pa_idxset *io_sources, *fixed_sources, *idle_sources, *time_sources;
-    int io_sources_scan_dead, fixed_sources_scan_dead, idle_sources_scan_dead, time_sources_scan_dead;
+    struct pa_idxset *io_events, *time_events, *defer_events;
+    int io_events_scan_dead, defer_events_scan_dead, time_events_scan_dead;
 
     struct pollfd *pollfds;
     unsigned max_pollfds, n_pollfds;
@@ -83,57 +83,248 @@ struct pa_mainloop {
     struct pa_mainloop_api api;
 };
 
-static void setup_api(struct pa_mainloop *m);
+/* IO events */
+static struct pa_io_event* mainloop_io_new(struct pa_mainloop_api*a, int fd, enum pa_io_event_flags events, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata) {
+    struct pa_mainloop *m;
+    struct pa_io_event *e;
+
+    assert(a && a->userdata && fd >= 0 && callback);
+    m = a->userdata;
+    assert(a == &m->api);
+
+    e = pa_xmalloc(sizeof(struct pa_io_event));
+    e->mainloop = m;
+    e->dead = 0;
+
+    e->fd = fd;
+    e->events = events;
+    e->callback = callback;
+    e->userdata = userdata;
+    e->destroy_callback = NULL;
+    e->pollfd = NULL;
+
+    pa_idxset_put(m->io_events, e, NULL);
+    m->rebuild_pollfds = 1;
+    return e;
+}
+
+static void mainloop_io_enable(struct pa_io_event *e, enum pa_io_event_flags events) {
+    assert(e && e->mainloop);
+
+    e->events = events;
+    if (e->pollfd)
+        e->pollfd->events =
+            (events & PA_IO_EVENT_INPUT ? POLLIN : 0) |
+            (events & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) |
+            POLLHUP |
+            POLLERR;
+}
+
+static void mainloop_io_free(struct pa_io_event *e) {
+    assert(e && e->mainloop);
+    e->dead = e->mainloop->io_events_scan_dead = e->mainloop->rebuild_pollfds = 1;
+}
+
+static void mainloop_io_set_destroy(struct pa_io_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata)) {
+    assert(e);
+    e->destroy_callback = callback;
+}
+
+/* Defer events */
+struct pa_defer_event* mainloop_defer_new(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata), void *userdata) {
+    struct pa_mainloop *m;
+    struct pa_defer_event *e;
+
+    assert(a && a->userdata && callback);
+    m = a->userdata;
+    assert(a == &m->api);
+
+    e = pa_xmalloc(sizeof(struct pa_defer_event));
+    e->mainloop = m;
+    e->dead = 0;
+
+    e->enabled = 1;
+    e->callback = callback;
+    e->userdata = userdata;
+    e->destroy_callback = NULL;
+
+    pa_idxset_put(m->defer_events, e, NULL);
+    return e;
+}
+
+static void mainloop_defer_enable(struct pa_defer_event *e, int b) {
+    assert(e);
+    e->enabled = b;
+}
+
+static void mainloop_defer_free(struct pa_defer_event *e) {
+    assert(e);
+    e->dead = e->mainloop->defer_events_scan_dead = 1;
+}
+
+static void mainloop_defer_set_destroy(struct pa_defer_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata)) {
+    assert(e);
+    e->destroy_callback = callback;
+}
+
+/* Time events */
+static struct pa_time_event* mainloop_time_new(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) {
+    struct pa_mainloop *m;
+    struct pa_time_event *e;
+
+    assert(a && a->userdata && callback);
+    m = a->userdata;
+    assert(a == &m->api);
+
+    e = pa_xmalloc(sizeof(struct pa_time_event));
+    e->mainloop = m;
+    e->dead = 0;
+
+    e->enabled = !!tv;
+    if (tv)
+        e->timeval = *tv;
+
+    e->callback = callback;
+    e->userdata = userdata;
+    e->destroy_callback = NULL;
+
+    pa_idxset_put(m->time_events, e, NULL);
+    return e;
+}
+
+static void mainloop_time_restart(struct pa_time_event *e, const struct timeval *tv) {
+    assert(e);
+
+    if (tv) {
+        e->enabled = 1;
+        e->timeval = *tv;
+    } else
+        e->enabled = 0;
+}
+
+static void mainloop_time_free(struct pa_time_event *e) {
+    assert(e);
+    e->dead = e->mainloop->time_events_scan_dead = 1;
+}
+
+static void mainloop_time_set_destroy(struct pa_time_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata)) {
+    assert(e);
+    e->destroy_callback = callback;
+}
+
+/* quit() */
+
+static void mainloop_quit(struct pa_mainloop_api*a, int retval) {
+    struct pa_mainloop *m;
+    assert(a && a->userdata);
+    m = a->userdata;
+    assert(a == &m->api);
+
+    m->quit = 1;
+    m->retval = retval;
+}
+    
+static const struct pa_mainloop_api vtable = {
+    userdata: NULL,
+
+    io_new: mainloop_io_new,
+    io_enable: mainloop_io_enable,
+    io_free: mainloop_io_free,
+    io_set_destroy: mainloop_io_set_destroy,
+
+    time_new : mainloop_time_new,
+    time_restart : mainloop_time_restart,
+    time_free : mainloop_time_free,
+    time_set_destroy : mainloop_time_set_destroy,
+    
+    defer_new : mainloop_defer_new,
+    defer_enable : mainloop_defer_enable,
+    defer_free : mainloop_defer_free,
+    defer_set_destroy : mainloop_defer_set_destroy,
+    
+    quit : mainloop_quit,
+};
 
 struct pa_mainloop *pa_mainloop_new(void) {
     struct pa_mainloop *m;
 
     m = pa_xmalloc(sizeof(struct pa_mainloop));
 
-    m->io_sources = pa_idxset_new(NULL, NULL);
-    m->fixed_sources = pa_idxset_new(NULL, NULL);
-    m->idle_sources = pa_idxset_new(NULL, NULL);
-    m->time_sources = pa_idxset_new(NULL, NULL);
+    m->io_events = pa_idxset_new(NULL, NULL);
+    m->defer_events = pa_idxset_new(NULL, NULL);
+    m->time_events = pa_idxset_new(NULL, NULL);
 
-    assert(m->io_sources && m->fixed_sources && m->idle_sources && m->time_sources);
+    assert(m->io_events && m->defer_events && m->time_events);
 
-    m->io_sources_scan_dead = m->fixed_sources_scan_dead = m->idle_sources_scan_dead = m->time_sources_scan_dead = 0;
+    m->io_events_scan_dead = m->defer_events_scan_dead = m->time_events_scan_dead = 0;
     
     m->pollfds = NULL;
     m->max_pollfds = m->n_pollfds = m->rebuild_pollfds = 0;
 
     m->quit = m->running = m->retval = 0;
 
-    setup_api(m);
+    m->api = vtable;
+    m->api.userdata = m;
     
     return m;
 }
 
-static int foreach(void *p, uint32_t index, int *del, void*userdata) {
-    struct mainloop_source_header *h = p;
+static int io_foreach(void *p, uint32_t index, int *del, void*userdata) {
+    struct pa_io_event *e = p;
     int *all = userdata;
-    assert(p && del && all);
+    assert(e && del && all);
 
-    if (*all || h->dead) {
-        pa_xfree(h);
-        *del = 1;
-    }
+    if (!*all || !e->dead)
+        return 0;
+    
+    if (e->destroy_callback)
+        e->destroy_callback(&e->mainloop->api, e, e->userdata);
+    pa_xfree(e);
+    *del = 1;
+    return 0;
+};
 
+static int time_foreach(void *p, uint32_t index, int *del, void*userdata) {
+    struct pa_time_event *e = p;
+    int *all = userdata;
+    assert(e && del && all);
+
+    if (!*all || !e->dead)
+        return 0;
+    
+    if (e->destroy_callback)
+        e->destroy_callback(&e->mainloop->api, e, e->userdata);
+    pa_xfree(e);
+    *del = 1;
+    return 0;
+};
+
+static int defer_foreach(void *p, uint32_t index, int *del, void*userdata) {
+    struct pa_defer_event *e = p;
+    int *all = userdata;
+    assert(e && del && all);
+
+    if (!*all || !e->dead)
+        return 0;
+    
+    if (e->destroy_callback)
+        e->destroy_callback(&e->mainloop->api, e, e->userdata);
+    pa_xfree(e);
+    *del = 1;
     return 0;
 };
 
 void pa_mainloop_free(struct pa_mainloop* m) {
     int all = 1;
     assert(m);
-    pa_idxset_foreach(m->io_sources, foreach, &all);
-    pa_idxset_foreach(m->fixed_sources, foreach, &all);
-    pa_idxset_foreach(m->idle_sources, foreach, &all);
-    pa_idxset_foreach(m->time_sources, foreach, &all);
 
-    pa_idxset_free(m->io_sources, NULL, NULL);
-    pa_idxset_free(m->fixed_sources, NULL, NULL);
-    pa_idxset_free(m->idle_sources, NULL, NULL);
-    pa_idxset_free(m->time_sources, NULL, NULL);
+    pa_idxset_foreach(m->io_events, io_foreach, &all);
+    pa_idxset_foreach(m->time_events, time_foreach, &all);
+    pa_idxset_foreach(m->defer_events, defer_foreach, &all);
+
+    pa_idxset_free(m->io_events, NULL, NULL);
+    pa_idxset_free(m->time_events, NULL, NULL);
+    pa_idxset_free(m->defer_events, NULL, NULL);
 
     pa_xfree(m->pollfds);
     pa_xfree(m);
@@ -142,23 +333,21 @@ void pa_mainloop_free(struct pa_mainloop* m) {
 static void scan_dead(struct pa_mainloop *m) {
     int all = 0;
     assert(m);
-    if (m->io_sources_scan_dead)
-        pa_idxset_foreach(m->io_sources, foreach, &all);
-    if (m->fixed_sources_scan_dead)
-        pa_idxset_foreach(m->fixed_sources, foreach, &all);
-    if (m->idle_sources_scan_dead)
-        pa_idxset_foreach(m->idle_sources, foreach, &all);
-    if (m->time_sources_scan_dead)
-        pa_idxset_foreach(m->time_sources, foreach, &all);
+    if (m->io_events_scan_dead)
+        pa_idxset_foreach(m->io_events, io_foreach, &all);
+    if (m->time_events_scan_dead)
+        pa_idxset_foreach(m->time_events, time_foreach, &all);
+    if (m->defer_events_scan_dead)
+        pa_idxset_foreach(m->defer_events, defer_foreach, &all);
 }
 
 static void rebuild_pollfds(struct pa_mainloop *m) {
-    struct mainloop_source_io*s;
+    struct pa_io_event*e;
     struct pollfd *p;
     uint32_t index = PA_IDXSET_INVALID;
     unsigned l;
 
-    l = pa_idxset_ncontents(m->io_sources);
+    l = pa_idxset_ncontents(m->io_events);
     if (m->max_pollfds < l) {
         m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l);
         m->max_pollfds = l;
@@ -166,15 +355,19 @@ static void rebuild_pollfds(struct pa_mainloop *m) {
 
     m->n_pollfds = 0;
     p = m->pollfds;
-    for (s = pa_idxset_first(m->io_sources, &index); s; s = pa_idxset_next(m->io_sources, &index)) {
-        if (s->header.dead) {
-            s->pollfd = NULL;
+    for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) {
+        if (e->dead) {
+            e->pollfd = NULL;
             continue;
         }
 
-        s->pollfd = p;
-        p->fd = s->fd;
-        p->events = ((s->events & PA_MAINLOOP_API_IO_EVENT_INPUT) ? POLLIN : 0) | ((s->events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) ? POLLOUT : 0);
+        e->pollfd = p;
+        p->fd = e->fd;
+        p->events =
+            ((e->events & PA_IO_EVENT_INPUT) ? POLLIN : 0) |
+            ((e->events & PA_IO_EVENT_OUTPUT) ? POLLOUT : 0) |
+            POLLHUP |
+            POLLERR;
         p->revents = 0;
 
         p++;
@@ -184,60 +377,62 @@ static void rebuild_pollfds(struct pa_mainloop *m) {
 
 static void dispatch_pollfds(struct pa_mainloop *m) {
     uint32_t index = PA_IDXSET_INVALID;
-    struct mainloop_source_io *s;
+    struct pa_io_event *e;
 
-    for (s = pa_idxset_first(m->io_sources, &index); s; s = pa_idxset_next(m->io_sources, &index)) {
-        if (s->header.dead || !s->pollfd || !s->pollfd->revents)
+    for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) {
+        if (e->dead || !e->pollfd || !e->pollfd->revents)
             continue;
         
-        assert(s->pollfd->fd == s->fd && s->callback);
-        s->callback(&m->api, s, s->fd,
-                    ((s->pollfd->revents & POLLHUP) ? PA_MAINLOOP_API_IO_EVENT_HUP : 0) |
-                    ((s->pollfd->revents & POLLIN) ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) |
-                    ((s->pollfd->revents & POLLOUT) ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), s->userdata);
-        s->pollfd->revents = 0;
+        assert(e->pollfd->fd == e->fd && e->callback);
+        e->callback(&m->api, e, e->fd,
+                    (e->pollfd->revents & POLLHUP ? PA_IO_EVENT_HANGUP : 0) |
+                    (e->pollfd->revents & POLLIN ? PA_IO_EVENT_INPUT : 0) |
+                    (e->pollfd->revents & POLLOUT ? PA_IO_EVENT_OUTPUT : 0) |
+                    (e->pollfd->revents & POLLERR ? PA_IO_EVENT_ERROR : 0),
+                    e->userdata);
+        e->pollfd->revents = 0;
     }
 }
 
-static void run_fixed_or_idle(struct pa_mainloop *m, struct pa_idxset *i) {
-    uint32_t index = PA_IDXSET_INVALID;
-    struct mainloop_source_fixed_or_idle *s;
+static void dispatch_defer(struct pa_mainloop *m) {
+    uint32_t index;
+    struct pa_defer_event *e;
 
-    for (s = pa_idxset_first(i, &index); s; s = pa_idxset_next(i, &index)) {
-        if (s->header.dead || !s->enabled)
+    for (e = pa_idxset_first(m->defer_events, &index); e; e = pa_idxset_next(m->defer_events, &index)) {
+        if (e->dead || !e->enabled)
             continue;
 
-        assert(s->callback);
-        s->callback(&m->api, s, s->userdata);
+        assert(e->callback);
+        e->callback(&m->api, e, e->userdata);
     }
 }
 
 static int calc_next_timeout(struct pa_mainloop *m) {
-    uint32_t index = PA_IDXSET_INVALID;
-    struct mainloop_source_time *s;
+    uint32_t index;
+    struct pa_time_event *e;
     struct timeval now;
     int t = -1;
 
-    if (pa_idxset_isempty(m->time_sources))
+    if (pa_idxset_isempty(m->time_events))
         return -1;
 
     gettimeofday(&now, NULL);
     
-    for (s = pa_idxset_first(m->time_sources, &index); s; s = pa_idxset_next(m->time_sources, &index)) {
+    for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) {
         int tmp;
         
-        if (s->header.dead || !s->enabled)
+        if (e->dead || !e->enabled)
             continue;
 
-        if (s->timeval.tv_sec < now.tv_sec || (s->timeval.tv_sec == now.tv_sec && s->timeval.tv_usec <= now.tv_usec)) 
+        if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec)) 
             return 0;
 
-        tmp = (s->timeval.tv_sec - now.tv_sec)*1000;
+        tmp = (e->timeval.tv_sec - now.tv_sec)*1000;
             
-        if (s->timeval.tv_usec > now.tv_usec)
-            tmp += (s->timeval.tv_usec - now.tv_usec)/1000;
+        if (e->timeval.tv_usec > now.tv_usec)
+            tmp += (e->timeval.tv_usec - now.tv_usec)/1000;
         else
-            tmp -= (now.tv_usec - s->timeval.tv_usec)/1000;
+            tmp -= (now.tv_usec - e->timeval.tv_usec)/1000;
 
         if (tmp == 0)
             return 0;
@@ -249,43 +444,31 @@ static int calc_next_timeout(struct pa_mainloop *m) {
 }
 
 static void dispatch_timeout(struct pa_mainloop *m) {
-    uint32_t index = PA_IDXSET_INVALID;
-    struct mainloop_source_time *s;
+    uint32_t index;
+    struct pa_time_event *e;
     struct timeval now;
     assert(m);
 
-    if (pa_idxset_isempty(m->time_sources))
+    if (pa_idxset_isempty(m->time_events))
         return;
 
     gettimeofday(&now, NULL);
-    for (s = pa_idxset_first(m->time_sources, &index); s; s = pa_idxset_next(m->time_sources, &index)) {
+    for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) {
         
-        if (s->header.dead || !s->enabled)
+        if (e->dead || !e->enabled)
             continue;
 
-        if (s->timeval.tv_sec < now.tv_sec || (s->timeval.tv_sec == now.tv_sec && s->timeval.tv_usec <= now.tv_usec)) {
-            assert(s->callback);
+        if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec)) {
+            assert(e->callback);
 
-            s->enabled = 0;
-            s->callback(&m->api, s, &s->timeval, s->userdata);
+            e->enabled = 0;
+            e->callback(&m->api, e, &e->timeval, e->userdata);
         }
     }
 }
 
-static int any_idle_sources(struct pa_mainloop *m) {
-    struct mainloop_source_fixed_or_idle *s;
-    uint32_t index;
-    assert(m);
-    
-    for (s = pa_idxset_first(m->idle_sources, &index); s; s = pa_idxset_next(m->idle_sources, &index))
-        if (!s->header.dead && s->enabled)
-            return 1;
-
-    return 0;
-}
-
 int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) {
-    int r, idle;
+    int r;
     assert(m && !m->running);
     
     if(m->quit) {
@@ -297,23 +480,16 @@ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) {
     m->running = 1;
 
     scan_dead(m);
-    run_fixed_or_idle(m, m->fixed_sources);
+    dispatch_defer(m);
 
     if (m->rebuild_pollfds) {
         rebuild_pollfds(m);
         m->rebuild_pollfds = 0;
     }
 
-    idle = any_idle_sources(m);
-
     do {
-        int t;
-
-        if (!block || idle)
-            t = 0;
-        else 
-            t = calc_next_timeout(m);
-            
+        int t = block ? calc_next_timeout(m) : 0;
+        /*fprintf(stderr, "%u\n", t);*/
         r = poll(m->pollfds, m->n_pollfds, t);
     } while (r < 0 && errno == EINTR);
 
@@ -321,8 +497,6 @@ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) {
     
     if (r > 0)
         dispatch_pollfds(m);
-    else if (r == 0 && idle)
-        run_fixed_or_idle(m, m->idle_sources);
     else if (r < 0)
         fprintf(stderr, "select(): %s\n", strerror(errno));
     
@@ -341,209 +515,7 @@ void pa_mainloop_quit(struct pa_mainloop *m, int r) {
     m->quit = r;
 }
 
-/* IO sources */
-static void* mainloop_source_io(struct pa_mainloop_api*a, int fd, enum pa_mainloop_api_io_events events, void (*callback) (struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata) {
-    struct pa_mainloop *m;
-    struct mainloop_source_io *s;
-    assert(a && a->userdata && fd >= 0 && callback);
-    m = a->userdata;
-    assert(a == &m->api);
-
-    s = pa_xmalloc(sizeof(struct mainloop_source_io));
-    s->header.mainloop = m;
-    s->header.dead = 0;
-
-    s->fd = fd;
-    s->events = events;
-    s->callback = callback;
-    s->userdata = userdata;
-    s->pollfd = NULL;
-
-    pa_idxset_put(m->io_sources, s, NULL);
-    m->rebuild_pollfds = 1;
-    return s;
-}
-
-static void mainloop_enable_io(struct pa_mainloop_api*a, void* id, enum pa_mainloop_api_io_events events) {
-    struct pa_mainloop *m;
-    struct mainloop_source_io *s = id;
-    assert(a && a->userdata && s && !s->header.dead);
-    m = a->userdata;
-    assert(a == &m->api && s->header.mainloop == m);
-
-    s->events = events;
-    if (s->pollfd)
-        s->pollfd->events = ((s->events & PA_MAINLOOP_API_IO_EVENT_INPUT) ? POLLIN : 0) | ((s->events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) ? POLLOUT : 0);
-}
-
-static void mainloop_cancel_io(struct pa_mainloop_api*a, void* id) {
-    struct pa_mainloop *m;
-    struct mainloop_source_io *s = id;
-    assert(a && a->userdata && s && !s->header.dead);
-    m = a->userdata;
-    assert(a == &m->api && s->header.mainloop == m);
-
-    s->header.dead = 1;
-    m->io_sources_scan_dead = 1;
-    m->rebuild_pollfds = 1;
-}
-
-/* Fixed sources */
-static void* mainloop_source_fixed(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata) {
-    struct pa_mainloop *m;
-    struct mainloop_source_fixed_or_idle *s;
-    assert(a && a->userdata && callback);
-    m = a->userdata;
-    assert(a == &m->api);
-
-    s = pa_xmalloc(sizeof(struct mainloop_source_fixed_or_idle));
-    s->header.mainloop = m;
-    s->header.dead = 0;
-
-    s->enabled = 1;
-    s->callback = callback;
-    s->userdata = userdata;
-
-    pa_idxset_put(m->fixed_sources, s, NULL);
-    return s;
-}
-
-static void mainloop_enable_fixed(struct pa_mainloop_api*a, void* id, int b) {
-    struct pa_mainloop *m;
-    struct mainloop_source_fixed_or_idle *s = id;
-    assert(a && a->userdata && s && !s->header.dead);
-    m = a->userdata;
-    assert(a == &m->api);
-
-    s->enabled = b;
-}
-
-static void mainloop_cancel_fixed(struct pa_mainloop_api*a, void* id) {
-    struct pa_mainloop *m;
-    struct mainloop_source_fixed_or_idle *s = id;
-    assert(a && a->userdata && s && !s->header.dead);
-    m = a->userdata;
-    assert(a == &m->api);
-
-    s->header.dead = 1;
-    m->fixed_sources_scan_dead = 1;
-}
-
-/* Idle sources */
-static void* mainloop_source_idle(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata) {
-    struct pa_mainloop *m;
-    struct mainloop_source_fixed_or_idle *s;
-    assert(a && a->userdata && callback);
-    m = a->userdata;
-    assert(a == &m->api);
-
-    s = pa_xmalloc(sizeof(struct mainloop_source_fixed_or_idle));
-    s->header.mainloop = m;
-    s->header.dead = 0;
-
-    s->enabled = 1;
-    s->callback = callback;
-    s->userdata = userdata;
-
-    pa_idxset_put(m->idle_sources, s, NULL);
-    return s;
-}
-
-static void mainloop_cancel_idle(struct pa_mainloop_api*a, void* id) {
-    struct pa_mainloop *m;
-    struct mainloop_source_fixed_or_idle *s = id;
-    assert(a && a->userdata && s && !s->header.dead);
-    m = a->userdata;
-    assert(a == &m->api);
-
-    s->header.dead = 1;
-    m->idle_sources_scan_dead = 1;
-}
-
-/* Time sources */
-static void* mainloop_source_time(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, void *id, const struct timeval *tv, void *userdata), void *userdata) {
-    struct pa_mainloop *m;
-    struct mainloop_source_time *s;
-    assert(a && a->userdata && callback);
-    m = a->userdata;
-    assert(a == &m->api);
-
-    s = pa_xmalloc(sizeof(struct mainloop_source_time));
-    s->header.mainloop = m;
-    s->header.dead = 0;
-
-    s->enabled = !!tv;
-    if (tv)
-        s->timeval = *tv;
-
-    s->callback = callback;
-    s->userdata = userdata;
-
-    pa_idxset_put(m->time_sources, s, NULL);
-    return s;
-}
-
-static void mainloop_enable_time(struct pa_mainloop_api*a, void *id, const struct timeval *tv) {
-    struct pa_mainloop *m;
-    struct mainloop_source_time *s = id;
-    assert(a && a->userdata && s && !s->header.dead);
-    m = a->userdata;
-    assert(a == &m->api);
-
-    if (tv) {
-        s->enabled = 1;
-        s->timeval = *tv;
-    } else
-        s->enabled = 0;
-}
-
-static void mainloop_cancel_time(struct pa_mainloop_api*a, void* id) {
-    struct pa_mainloop *m;
-    struct mainloop_source_time *s = id;
-    assert(a && a->userdata && s && !s->header.dead);
-    m = a->userdata;
-    assert(a == &m->api);
-
-    s->header.dead = 1;
-    m->time_sources_scan_dead = 1;
-
-}
-
-static void mainloop_quit(struct pa_mainloop_api*a, int retval) {
-    struct pa_mainloop *m;
-    assert(a && a->userdata);
-    m = a->userdata;
-    assert(a == &m->api);
-
-    m->quit = 1;
-    m->retval = retval;
-}
-    
-static void setup_api(struct pa_mainloop *m) {
-    assert(m);
-    
-    m->api.userdata = m;
-    m->api.source_io = mainloop_source_io;
-    m->api.enable_io = mainloop_enable_io;
-    m->api.cancel_io = mainloop_cancel_io;
-
-    m->api.source_fixed = mainloop_source_fixed;
-    m->api.enable_fixed = mainloop_enable_fixed;
-    m->api.cancel_fixed = mainloop_cancel_fixed;
-
-    m->api.source_idle = mainloop_source_idle;
-    m->api.enable_idle = mainloop_enable_fixed; /* (!) */
-    m->api.cancel_idle = mainloop_cancel_idle;
-    
-    m->api.source_time = mainloop_source_time;
-    m->api.enable_time = mainloop_enable_time;
-    m->api.cancel_time = mainloop_cancel_time;
-
-    m->api.quit = mainloop_quit;
-}
-
 struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m) {
     assert(m);
     return &m->api;
 }
-        
index a0fa52db1215675d99093ae58540a1d1f86eb073..5b4a7b73254bf9f52a99c89128898355e45d01ce 100644 (file)
@@ -42,8 +42,8 @@
 struct userdata {
     snd_pcm_t *pcm_handle;
     struct pa_sink *sink;
-    void **io_sources;
-    unsigned n_io_sources;
+    struct pa_io_event **io_events;
+    unsigned n_io_events;
 
     size_t frame_size, fragment_size;
     struct pa_memchunk memchunk, silence;
@@ -128,9 +128,9 @@ static void do_write(struct userdata *u) {
     }
 }
 
-static void io_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) {
+static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) {
     struct userdata *u = userdata;
-    assert(u && a && id);
+    assert(u && a && e);
 
     if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN)
         xrun_recovery(u);
@@ -207,7 +207,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) {
     pa_sink_set_owner(u->sink, m);
     u->sink->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev);
 
-    if (pa_create_io_sources(u->pcm_handle, c->mainloop, &u->io_sources, &u->n_io_sources, io_callback, u) < 0) {
+    if (pa_create_io_events(u->pcm_handle, c->mainloop, &u->io_events, &u->n_io_events, io_callback, u) < 0) {
         fprintf(stderr, __FILE__": failed to obtain file descriptors\n");
         goto fail;
     }
@@ -251,8 +251,8 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) {
     if (u->sink)
         pa_sink_free(u->sink);
     
-    if (u->io_sources)
-        pa_free_io_sources(c->mainloop, u->io_sources, u->n_io_sources);
+    if (u->io_events)
+        pa_free_io_events(c->mainloop, u->io_events, u->n_io_events);
     
     if (u->pcm_handle) {
         snd_pcm_drop(u->pcm_handle);
index 8207d462a9f4a984aa4b671b483b8ed17baf2516..df716f737dde581635dab504b0873c73764d9496 100644 (file)
@@ -42,8 +42,8 @@
 struct userdata {
     snd_pcm_t *pcm_handle;
     struct pa_source *source;
-    void **io_sources;
-    unsigned n_io_sources;
+    struct pa_io_event **io_events;
+    unsigned n_io_events;
 
     size_t frame_size, fragment_size;
     struct pa_memchunk memchunk;
@@ -128,9 +128,9 @@ static void do_read(struct userdata *u) {
     }
 }
 
-static void io_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) {
+static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) {
     struct userdata *u = userdata;
-    assert(u && a && id);
+    assert(u && a && e);
 
     if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN)
         xrun_recovery(u);
@@ -189,7 +189,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) {
     pa_source_set_owner(u->source, m);
     u->source->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev);
 
-    if (pa_create_io_sources(u->pcm_handle, c->mainloop, &u->io_sources, &u->n_io_sources, io_callback, u) < 0) {
+    if (pa_create_io_events(u->pcm_handle, c->mainloop, &u->io_events, &u->n_io_events, io_callback, u) < 0) {
         fprintf(stderr, __FILE__": failed to obtain file descriptors\n");
         goto fail;
     }
@@ -230,8 +230,8 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) {
     if (u->source)
         pa_source_free(u->source);
     
-    if (u->io_sources)
-        pa_free_io_sources(c->mainloop, u->io_sources, u->n_io_sources);
+    if (u->io_events)
+        pa_free_io_events(c->mainloop, u->io_events, u->n_io_events);
     
     if (u->pcm_handle) {
         snd_pcm_drop(u->pcm_handle);
index 37710fc56c759e026d2b865b9d56f2cd534c7f64..ea768a98736df1184614346d74897d9631eda854 100644 (file)
@@ -59,7 +59,7 @@ struct userdata {
     void *in_mmap, *out_mmap;
     size_t in_mmap_length, out_mmap_length;
 
-    void *mainloop_source;
+    struct pa_io_event *io_event;
 
     struct pa_memblock **in_memblocks, **out_memblocks;
     unsigned out_current, in_current;
@@ -195,14 +195,13 @@ static void do_read(struct userdata *u) {
     in_clear_memblocks(u, u->in_fragments/2);
 };
 
-static void io_callback(struct pa_mainloop_api *m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) {
+static void io_callback(struct pa_mainloop_api *m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) {
     struct userdata *u = userdata;
+    assert (u && u->core->mainloop == m && u->io_event == e);
 
-    assert (u && u->core->mainloop == m && u->mainloop_source == id);
-
-    if (events & PA_MAINLOOP_API_IO_EVENT_INPUT)
+    if (f & PA_IO_EVENT_INPUT)
         do_read(u);
-    if (events & PA_MAINLOOP_API_IO_EVENT_OUTPUT)
+    if (f & PA_IO_EVENT_OUTPUT)
         do_write(u);
 }
 
@@ -352,8 +351,8 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) {
         
     assert(u->source || u->sink);
 
-    u->mainloop_source = c->mainloop->source_io(c->mainloop, u->fd, (u->source ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | (u->sink ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), io_callback, u);
-    assert(u->mainloop_source);
+    u->io_event = c->mainloop->io_new(c->mainloop, u->fd, (u->source ? PA_IO_EVENT_INPUT : 0) | (u->sink ? PA_IO_EVENT_OUTPUT : 0), io_callback, u);
+    assert(u->io_event);
 
     pa_modargs_free(ma);
     
@@ -403,8 +402,8 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) {
     if (u->source)
         pa_source_free(u->source);
 
-    if (u->mainloop_source)
-        u->core->mainloop->cancel_io(u->core->mainloop, u->mainloop_source);
+    if (u->io_event)
+        u->core->mainloop->io_free(u->io_event);
 
     if (u->fd >= 0)
         close(u->fd);
index dc2bc633d4eff8013173bcd9babf88f1cb2747b6..22d9f67680ea9198c8b4a982d0bc2503d45a4879 100644 (file)
@@ -50,7 +50,7 @@ struct userdata {
     
     struct pa_sink *sink;
     struct pa_iochannel *io;
-    void *mainloop_source;
+    struct pa_defer_event *defer_event;
 
     struct pa_memchunk memchunk;
     struct pa_module *module;
@@ -69,7 +69,7 @@ static void do_write(struct userdata *u) {
     ssize_t r;
     assert(u);
 
-    u->core->mainloop->enable_fixed(u->core->mainloop, u->mainloop_source, 0);
+    u->core->mainloop->defer_enable(u->defer_event, 0);
         
     if (!pa_iochannel_is_writable(u->io))
         return;
@@ -101,10 +101,10 @@ static void notify_cb(struct pa_sink*s) {
     assert(s && u);
 
     if (pa_iochannel_is_writable(u->io))
-        u->core->mainloop->enable_fixed(u->core->mainloop, u->mainloop_source, 1);
+        u->core->mainloop->defer_enable(u->defer_event, 1);
 }
 
-static void fixed_callback(struct pa_mainloop_api *m, void *id, void *userdata) {
+static void defer_callback(struct pa_mainloop_api *m, struct pa_defer_event*e, void *userdata) {
     struct userdata *u = userdata;
     assert(u);
     do_write(u);
@@ -175,9 +175,9 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) {
     u->memchunk.memblock = NULL;
     u->memchunk.length = 0;
 
-    u->mainloop_source = c->mainloop->source_fixed(c->mainloop, fixed_callback, u);
-    assert(u->mainloop_source);
-    c->mainloop->enable_fixed(c->mainloop, u->mainloop_source, 0);
+    u->defer_event = c->mainloop->defer_new(c->mainloop, defer_callback, u);
+    assert(u->defer_event);
+    c->mainloop->defer_enable(u->defer_event, 0);
 
     u->module = m;
     m->userdata = u;
@@ -210,7 +210,7 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) {
         
     pa_sink_free(u->sink);
     pa_iochannel_free(u->io);
-    u->core->mainloop->cancel_fixed(u->core->mainloop, u->mainloop_source);
+    u->core->mainloop->defer_free(u->defer_event);
 
     assert(u->filename);
     unlink(u->filename);
index 2cf760998fa9200daec7ef68bd58766d77b0a8f5..5449e944dee65b0e3be912450d63f2f8c0c6609b 100644 (file)
@@ -14,7 +14,7 @@
 #include "namereg.h"
 
 struct x11_source {
-    void *io_source;
+    struct pa_io_event *io_event;
     struct x11_source *next;
 };
 
@@ -52,7 +52,7 @@ static int ring_bell(struct userdata *u, int percent) {
     return 0;
 }
 
-static void io_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) {
+static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) {
     struct userdata *u = userdata;
     assert(u);
     
@@ -77,8 +77,8 @@ static void new_io_source(struct userdata *u, int fd) {
     struct x11_source *s;
 
     s = pa_xmalloc(sizeof(struct x11_source));
-    s->io_source = u->core->mainloop->source_io(u->core->mainloop, fd, PA_MAINLOOP_API_IO_EVENT_INPUT, io_callback, u);
-    assert(s->io_source);
+    s->io_event = u->core->mainloop->io_new(u->core->mainloop, fd, PA_IO_EVENT_INPUT, io_callback, u);
+    assert(s->io_event);
     s->next = u->x11_sources;
     u->x11_sources = s;
 }
@@ -149,7 +149,7 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) {
     while (u->x11_sources) {
         struct x11_source *s = u->x11_sources;
         u->x11_sources = u->x11_sources->next;
-        c->mainloop->cancel_io(c->mainloop, s->io_source);
+        c->mainloop->io_free(s->io_event);
         pa_xfree(s);
     }
 
index 8c5e318f1939c83dddf9299783664d676b4e5322..83bfa800778db29552c6f9d8e9288e32deca8058 100644 (file)
 
 #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);
index de195a4b24de10793c3f7c11f763f3071656f58e..acc08c3e074827146e0036145160947924b10e69 100644 (file)
@@ -59,5 +59,4 @@ void pa_module_done(struct pa_core *c, struct pa_module*m);
 
 void pa_module_set_used(struct pa_module*m, int used);
 
-
 #endif
index dc730e4b0f8531650723b4543d2d417e2ff8101c..d8a2a5ab13e8aec8c6eb198950b5f7ab29b73f87 100644 (file)
@@ -48,13 +48,15 @@ enum {
     PA_COMMAND_PLAY_SAMPLE,
     PA_COMMAND_REMOVE_SAMPLE,
     
-    PA_COMMAND_GET_SINK,
-    PA_COMMAND_GET_SOURCE,
-    PA_COMMAND_GET_MODULE,
-    PA_COMMAND_GET_CLIENT,
-    PA_COMMAND_GET_SINK_INPUT,
-    PA_COMMAND_GET_SOURCE_OUTPUT,
-    PA_COMMAND_GET_SAMPLE,
+    PA_COMMAND_GET_SINK_INFO,
+    PA_COMMAND_GET_SINK_INFO_LIST,
+    PA_COMMAND_GET_SOURCE_INFO,
+    PA_COMMAND_GET_SOURCE_INFO_LIST,
+    PA_COMMAND_GET_MODULE_INFO,
+    PA_COMMAND_GET_CLIENT_INFO,
+    PA_COMMAND_GET_SINK_INPUT_INFO,
+    PA_COMMAND_GET_SOURCE_OUTPUT_INFO,
+    PA_COMMAND_GET_SAMPLE_INFO,
 
     PA_COMMAND_SUBSCRIBE,
     PA_COMMAND_SUBSCRIBE_EVENT,
index 55a0f6b94227bb323520e07aa6a24e1616b96306..4d8605c7a06e501dcc17a7ecb6abe798d13f3279 100644 (file)
@@ -45,7 +45,7 @@ static struct pa_mainloop_api *mainloop_api = NULL;
 static void *buffer = NULL;
 static size_t buffer_length = 0, buffer_index = 0;
 
-static void* stdio_source = NULL;
+static struct pa_io_event* stdio_event = NULL;
 
 static void quit(int ret) {
     assert(mainloop_api);
@@ -89,8 +89,8 @@ static void do_stream_write(size_t length) {
 static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) {
     assert(s && length);
 
-    if (stdio_source)
-        mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_INPUT);
+    if (stdio_event)
+        mainloop_api->io_enable(stdio_event, PA_IO_EVENT_INPUT);
 
     if (!buffer)
         return;
@@ -101,8 +101,8 @@ static void stream_write_callback(struct pa_stream *s, size_t length, void *user
 static void stream_read_callback(struct pa_stream *s, const void*data, size_t length, void *userdata) {
     assert(s && data && length);
 
-    if (stdio_source)
-        mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_OUTPUT);
+    if (stdio_event)
+        mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT);
 
     if (buffer) {
         fprintf(stderr, "Buffer overrrun, dropping incoming data\n");
@@ -174,13 +174,13 @@ static void stream_drain_complete(struct pa_stream*s, void *userdata) {
         fprintf(stderr, "Draining connection to server.\n");
 }
 
-static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) {
+static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) {
     size_t l, w = 0;
     ssize_t r;
-    assert(a == mainloop_api && id && stdio_source == id);
+    assert(a == mainloop_api && e && stdio_event == e);
 
     if (buffer) {
-        mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_NULL);
+        mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL);
         return;
     }
 
@@ -198,8 +198,8 @@ static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_m
             quit(1);
         }
 
-        mainloop_api->cancel_io(mainloop_api, stdio_source);
-        stdio_source = NULL;
+        mainloop_api->io_free(stdio_event);
+        stdio_event = NULL;
         return;
     }
 
@@ -210,12 +210,12 @@ static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_m
         do_stream_write(w);
 }
 
-static void stdout_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) {
+static void stdout_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) {
     ssize_t r;
-    assert(a == mainloop_api && id && stdio_source == id);
+    assert(a == mainloop_api && e && stdio_event == e);
 
     if (!buffer) {
-        mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_NULL);
+        mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL);
         return;
     }
 
@@ -225,8 +225,8 @@ static void stdout_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_
         fprintf(stderr, "write() failed: %s\n", strerror(errno));
         quit(1);
 
-        mainloop_api->cancel_io(mainloop_api, stdio_source);
-        stdio_source = NULL;
+        mainloop_api->io_free(stdio_event);
+        stdio_event = NULL;
         return;
     }
 
@@ -240,7 +240,7 @@ static void stdout_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_
     }
 }
 
-static void exit_signal_callback(void *id, int sig, void *userdata) {
+static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
     fprintf(stderr, "Got SIGINT, exiting.\n");
     quit(0);
     
@@ -258,7 +258,7 @@ static void stream_get_latency_callback(struct pa_stream *s, uint32_t latency, v
     fprintf(stderr, "Current latency is %u usecs.\n", latency);
 }
 
-static void sigusr1_signal_callback(void *id, int sig, void *userdata) {
+static void sigusr1_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
     if (mode == PLAYBACK) {
         fprintf(stderr, "Got SIGUSR1, requesting latency.\n");
         pa_stream_get_latency(stream, stream_get_latency_callback, NULL);
@@ -289,14 +289,14 @@ int main(int argc, char *argv[]) {
 
     r = pa_signal_init(mainloop_api);
     assert(r == 0);
-    pa_signal_register(SIGINT, exit_signal_callback, NULL);
-    pa_signal_register(SIGUSR1, sigusr1_signal_callback, NULL);
+    pa_signal_new(SIGINT, exit_signal_callback, NULL);
+    pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL);
     signal(SIGPIPE, SIG_IGN);
     
-    if (!(stdio_source = mainloop_api->source_io(mainloop_api,
-                                                 mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO,
-                                                 mode == PLAYBACK ? PA_MAINLOOP_API_IO_EVENT_INPUT : PA_MAINLOOP_API_IO_EVENT_OUTPUT,
-                                                 mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) {
+    if (!(stdio_event = mainloop_api->io_new(mainloop_api,
+                                             mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO,
+                                             mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT,
+                                             mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) {
         fprintf(stderr, "source_io() failed.\n");
         goto quit;
     }
index 28b187b044cef55675b34a9a4244de70fdf18818..2f3a48331e2f2c9ecfa17237a8c07a590cd93bae 100644 (file)
@@ -205,7 +205,7 @@ fail:
     quit(1);
 }
 
-static void exit_signal_callback(void *id, int sig, void *userdata) {
+static void exit_signal_callback(struct pa_mainloop_api *m, struct pa_signal_event *e, int sig, void *userdata) {
     fprintf(stderr, "Got SIGINT, exiting.\n");
     quit(0);
 }
@@ -284,7 +284,7 @@ int main(int argc, char *argv[]) {
 
     r = pa_signal_init(mainloop_api);
     assert(r == 0);
-    pa_signal_register(SIGINT, exit_signal_callback, NULL);
+    pa_signal_new(SIGINT, exit_signal_callback, NULL);
     signal(SIGPIPE, SIG_IGN);
     
     if (!(context = pa_context_new(mainloop_api, argv[0]))) {
index c34c6e0adfd6b9f9ab1d7dd85526298c7ce423a5..2d4c4d641ae991b9ed7768e02e5a22db6d222ba1 100644 (file)
@@ -69,7 +69,7 @@ struct reply_info {
     void (*callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
     void *userdata;
     uint32_t tag;
-    void *mainloop_timeout;
+    struct pa_time_event *time_event;
     int callback_is_running;
 };
 
@@ -87,7 +87,7 @@ static void reply_info_free(struct reply_info *r) {
     assert(r && r->pdispatch && r->pdispatch->mainloop);
 
     if (r->pdispatch)
-        r->pdispatch->mainloop->cancel_time(r->pdispatch->mainloop, r->mainloop_timeout);
+        r->pdispatch->mainloop->time_free(r->time_event);
 
     if (r->previous)
         r->previous->next = r->next;
@@ -191,9 +191,9 @@ finish:
     return ret;
 }
 
-static void timeout_callback(struct pa_mainloop_api*m, void *id, const struct timeval *tv, void *userdata) {
+static void timeout_callback(struct pa_mainloop_api*m, struct pa_time_event*e, const struct timeval *tv, void *userdata) {
     struct reply_info*r = userdata;
-    assert (r && r->mainloop_timeout == id && r->pdispatch && r->pdispatch->mainloop == m && r->callback);
+    assert (r && r->time_event == e && r->pdispatch && r->pdispatch->mainloop == m && r->callback);
 
     r->callback(r->pdispatch, PA_COMMAND_TIMEOUT, r->tag, NULL, r->userdata);
     reply_info_free(r);
@@ -217,8 +217,8 @@ void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int time
     gettimeofday(&tv, NULL);
     tv.tv_sec += timeout;
 
-    r->mainloop_timeout = pd->mainloop->source_time(pd->mainloop, &tv, timeout_callback, r);
-    assert(r->mainloop_timeout);
+    r->time_event = pd->mainloop->time_new(pd->mainloop, &tv, timeout_callback, r);
+    assert(r->time_event);
 
     r->previous = NULL;
     r->next = pd->replies;
index 5c448a7548d3bf93181f95424d39a963c57cf693..866344070942ecb09c65c7d93a0d5f16c657dab5 100644 (file)
@@ -30,7 +30,7 @@ static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) {
     return 0;
 }
 
-static void si_kill(void *i) {
+static void si_kill(struct pa_mainloop_api *m, void *i) {
     sink_input_kill(i);
 }
 
index 0989a78d28e4f75b0bf40b27f8aeaa60bb587cb9..71513565741c60b93336a752e07f7d8285a658b7 100755 (executable)
 # 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
+
index 391cb0c868219495424092efddaecb909f1d0849..08e6a5a5a7ea3d92874e40cd45f90130663439b6 100644 (file)
@@ -97,4 +97,34 @@ void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s,
 void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
 void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
 
+struct pa_sink_info {
+    const char *name;
+    uint32_t index;
+    const char *description;
+    struct pa_sample_spec *sample_spec;
+    uint32_t owner_module;
+    uint32_t volume;
+    uint32_t monitor_source;
+    const char *monitor_source_name;
+    uint32_t latency;
+};
+
+void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, void *userdata), void *userdata);
+void pa_context_get_sink_info_by_id(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, void *userdata), void *userdata);
+void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, void *userdata), void *userdata);
+
+struct pa_source_info {
+    const char *name;
+    uint32_t index;
+    const char *description;
+    struct pa_sample_spec *sample_spec;
+    uint32_t owner_module;
+    uint32_t monitor_of_sink;
+    const char *monitor_of_sink_name;
+};
+
+void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, void *userdata), void *userdata);
+void pa_context_get_source_info_by_id(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, void *userdata), void *userdata);
+void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, void *userdata), void *userdata);
+
 #endif
index 5f6f02fa869b36e3476a9a2a6370dc81ad552690..b11e19923ed6af109408a12c406804525853796e 100644 (file)
@@ -74,7 +74,7 @@ struct connection {
     struct pa_sink_input *sink_input;
     struct pa_source_output *source_output;
     struct pa_memblockq *input_memblockq, *output_memblockq;
-    void *fixed_source;
+    struct pa_defer_event *defer_event;
     struct {
         struct pa_memblock *current_memblock;
         size_t memblock_index, fragment_size;
@@ -183,8 +183,8 @@ static void connection_free(struct connection *c) {
     
     pa_iochannel_free(c->io);
     
-    if (c->fixed_source)
-        c->protocol->core->mainloop->cancel_fixed(c->protocol->core->mainloop, c->fixed_source);
+    if (c->defer_event)
+        c->protocol->core->mainloop->defer_free(c->defer_event);
 
     if (c->scache_memchunk.memblock)
         pa_memblock_unref(c->scache_memchunk.memblock);
@@ -197,8 +197,8 @@ static void* connection_write(struct connection *c, size_t length) {
     size_t t, i;
     assert(c);
 
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed);
-    c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1);
+    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
+    c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
 
     t = c->write_data_length+length;
     
@@ -381,7 +381,7 @@ static int esd_proto_get_latency(struct connection *c, esd_proto_t request, cons
     int latency, *lag;
     assert(c && !data && length == 0);
 
-    if (!(sink = pa_namereg(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1)))
+    if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1)))
         latency = 0;
     else {
         float usec = pa_sink_get_latency(sink);
@@ -845,8 +845,8 @@ static int do_write(struct connection *c) {
 static void do_work(struct connection *c) {
     assert(c);
 
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed);
-    c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 0);
+    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
+    c->protocol->core->mainloop->defer_enable(c->defer_event, 0);
 
     if (pa_iochannel_is_hungup(c->io))
         goto fail;
@@ -872,11 +872,11 @@ static void io_callback(struct pa_iochannel*io, void *userdata) {
     do_work(c);
 }
 
-/*** fixed callback ***/
+/*** defer callback ***/
 
-static void fixed_callback(struct pa_mainloop_api*a, void *id, void *userdata) {
+static void defer_callback(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) {
     struct connection *c = userdata;
-    assert(a && c && c->fixed_source == id);
+    assert(a && c && c->defer_event == e);
 
     do_work(c);
 }
@@ -901,8 +901,8 @@ static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) {
     pa_memblockq_drop(c->input_memblockq, length);
 
     /* do something */
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed);
-    c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1);
+    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
+    c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
 }
 
 static void sink_input_kill_cb(struct pa_sink_input *i) {
@@ -926,8 +926,8 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me
     pa_memblockq_push(c->output_memblockq, chunk, 0);
 
     /* do something */
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed);
-    c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1);
+    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
+    c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
 }
 
 static void source_output_kill_cb(struct pa_source_output *o) {
@@ -981,8 +981,9 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo
     c->scache_memchunk.memblock = NULL;
     c->scache_name = NULL;
     
-    c->fixed_source = c->protocol->core->mainloop->source_fixed(c->protocol->core->mainloop, fixed_callback, c);
-    c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 0);
+    c->defer_event = c->protocol->core->mainloop->defer_new(c->protocol->core->mainloop, defer_callback, c);
+    assert(c->defer_event);
+    c->protocol->core->mainloop->defer_enable(c->defer_event, 0);
 
     pa_idxset_put(c->protocol->connections, c, &c->index);
 }
index c0aef180e953bc1f202eeb473212bf37c03fb9ad..778677b31d3ee69fdbcc7f9724de98c648911e7e 100644 (file)
@@ -127,6 +127,8 @@ static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t comma
 static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
 static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
 static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
+static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
+static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
 
 static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
     [PA_COMMAND_ERROR] = { NULL },
@@ -150,6 +152,10 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
     [PA_COMMAND_FINISH_UPLOAD_STREAM] = { command_finish_upload_stream },
     [PA_COMMAND_PLAY_SAMPLE] = { command_play_sample },
     [PA_COMMAND_REMOVE_SAMPLE] = { command_remove_sample },
+    [PA_COMMAND_GET_SINK_INFO] = { command_get_info },
+    [PA_COMMAND_GET_SOURCE_INFO] = { command_get_info },
+    [PA_COMMAND_GET_SINK_INFO_LIST] = { command_get_info_list },
+    [PA_COMMAND_GET_SOURCE_INFO_LIST] = { command_get_info_list },
 };
 
 /* structure management */
@@ -923,6 +929,122 @@ static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uin
     pa_pstream_send_simple_ack(c->pstream, tag);
 }
 
+static void sink_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink *sink) {
+    assert(t && sink);
+    pa_tagstruct_putu32(t, sink->index);
+    pa_tagstruct_puts(t, sink->name);
+    pa_tagstruct_puts(t, sink->description);
+    pa_tagstruct_put_sample_spec(t, &sink->sample_spec);
+    pa_tagstruct_putu32(t, sink->owner ? sink->owner->index : (uint32_t) -1);
+    pa_tagstruct_putu32(t, sink->volume);
+    pa_tagstruct_putu32(t, sink->monitor_source->index);
+    pa_tagstruct_puts(t, sink->monitor_source->name);
+    pa_tagstruct_putu32(t, pa_sink_get_latency(sink));
+}
+
+static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *source) {
+    assert(t && source);
+    pa_tagstruct_putu32(t, source->index);
+    pa_tagstruct_puts(t, source->name);
+    pa_tagstruct_puts(t, source->description);
+    pa_tagstruct_put_sample_spec(t, &source->sample_spec);
+    pa_tagstruct_putu32(t, source->owner ? source->owner->index : (uint32_t) -1);
+    pa_tagstruct_putu32(t, source->monitor_of ? source->monitor_of->index : (uint32_t) -1);
+    pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : "");
+}
+
+static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+    struct connection *c = userdata;
+    uint32_t index;
+    struct pa_sink *sink = NULL;
+    struct pa_source *source = NULL;
+    const char *name;
+    struct pa_tagstruct *reply;
+    assert(c && t);
+
+    if (pa_tagstruct_getu32(t, &index) < 0 ||
+        pa_tagstruct_gets(t, &name) < 0 ||
+        !pa_tagstruct_eof(t)) {
+        protocol_error(c);
+        return;
+    }
+    
+    if (!c->authorized) {
+        pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
+        return;
+    }
+
+    if (command == PA_COMMAND_GET_SINK_INFO) {
+        if (index != (uint32_t) -1)
+            sink = pa_idxset_get_by_index(c->protocol->core->sinks, index);
+        else
+            sink = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SINK, 1);
+    } else {
+        assert(command == PA_COMMAND_GET_SOURCE_INFO);
+        if (index != (uint32_t) -1)
+            source = pa_idxset_get_by_index(c->protocol->core->sources, index);
+        else
+            source = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SOURCE, 1);
+    }
+
+    if (!sink && !source) {
+        pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
+        return;
+    }
+
+    reply = pa_tagstruct_new(NULL, 0);
+    assert(reply);
+    pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
+    pa_tagstruct_putu32(reply, tag); 
+    if (sink)
+        sink_fill_tagstruct(reply, sink);
+    else
+        source_fill_tagstruct(reply, source);
+    pa_pstream_send_tagstruct(c->pstream, reply);
+}
+
+static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+    struct connection *c = userdata;
+    struct pa_idxset *i;
+    uint32_t index;
+    void *p;
+    struct pa_tagstruct *reply;
+    assert(c && t);
+
+    if (!pa_tagstruct_eof(t)) {
+        protocol_error(c);
+        return;
+    }
+    
+    if (!c->authorized) {
+        pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
+        return;
+    }
+
+    reply = pa_tagstruct_new(NULL, 0);
+    assert(reply);
+    pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
+    pa_tagstruct_putu32(reply, tag);
+
+    if (command == PA_COMMAND_GET_SINK_INFO_LIST)
+        i = c->protocol->core->sinks;
+    else {
+        assert(command == PA_COMMAND_GET_SOURCE_INFO_LIST);
+        i = c->protocol->core->sources;
+    }
+
+    for (p = pa_idxset_first(i, &index); p; p = pa_idxset_next(i, &index)) {
+        if (command == PA_COMMAND_GET_SINK_INFO_LIST)
+            sink_fill_tagstruct(reply, p);
+        else {
+            assert(command == PA_COMMAND_GET_SOURCE_INFO_LIST);
+            source_fill_tagstruct(reply, p);
+        }
+    } 
+    
+    pa_pstream_send_tagstruct(c->pstream, reply);
+}
+
 /*** pstream callbacks ***/
 
 static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
index 4b3b1513c9a941114ed7b578b7635ca56f67d7cb..a95b356c14c18c912d9a175bca44f653af5ff5bf 100644 (file)
@@ -45,7 +45,7 @@ struct connection {
     struct pa_source_output *source_output;
     struct pa_client *client;
     struct pa_memblockq *input_memblockq, *output_memblockq;
-    void *fixed_source;
+    struct pa_defer_event *defer_event;
 
     struct {
         struct pa_memblock *current_memblock;
@@ -91,8 +91,8 @@ static void connection_free(struct connection *c) {
         pa_memblockq_free(c->input_memblockq);
     if (c->output_memblockq)
         pa_memblockq_free(c->output_memblockq);
-    if (c->fixed_source)
-        c->protocol->core->mainloop->cancel_fixed(c->protocol->core->mainloop, c->fixed_source);
+    if (c->defer_event)
+        c->protocol->core->mainloop->defer_free(c->defer_event);
     pa_xfree(c);
 }
 
@@ -169,8 +169,8 @@ static int do_write(struct connection *c) {
 static void do_work(struct connection *c) {
     assert(c);
 
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed);
-    c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 0);
+    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
+    c->protocol->core->mainloop->defer_enable(c->defer_event, 0);
 
     if (pa_iochannel_is_hungup(c->io))
         goto fail;
@@ -209,8 +209,8 @@ static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) {
     pa_memblockq_drop(c->input_memblockq, length);
 
     /* do something */
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed);
-    c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1);
+    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
+    c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
 }
 
 static void sink_input_kill_cb(struct pa_sink_input *i) {
@@ -234,8 +234,8 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me
     pa_memblockq_push(c->output_memblockq, chunk, 0);
 
     /* do something */
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed);
-    c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1);
+    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
+    c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
 }
 
 static void source_output_kill_cb(struct pa_source_output *o) {
@@ -261,9 +261,9 @@ static void io_callback(struct pa_iochannel*io, void *userdata) {
 
 /*** fixed callback ***/
 
-static void fixed_callback(struct pa_mainloop_api*a, void *id, void *userdata) {
+static void defer_callback(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) {
     struct connection *c = userdata;
-    assert(a && c && c->fixed_source == id);
+    assert(a && c && c->defer_event == e);
 
     do_work(c);
 }
@@ -280,7 +280,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo
     c->io = io;
     c->sink_input = NULL;
     c->source_output = NULL;
-    c->fixed_source = NULL;
+    c->defer_event = NULL;
     c->input_memblockq = c->output_memblockq = NULL;
     c->protocol = p;
     c->playback.current_memblock = NULL;
@@ -353,9 +353,9 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo
     pa_iochannel_set_callback(c->io, io_callback, c);
     pa_idxset_put(p->connections, c, NULL);
 
-    c->fixed_source = p->core->mainloop->source_fixed(p->core->mainloop, fixed_callback, c);
-    assert(c->fixed_source);
-    p->core->mainloop->enable_fixed(p->core->mainloop, c->fixed_source, 0);
+    c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c);
+    assert(c->defer_event);
+    p->core->mainloop->defer_enable(c->defer_event, 0);
     
     return;
     
index e7441b24bcaebefbd7a03b3576fdb62a5cffe0b0..4f071e4ae41dac6b933476f1ecf3ff24a2dc0a42 100644 (file)
@@ -58,7 +58,7 @@ struct item_info {
 
 struct pa_pstream {
     struct pa_mainloop_api *mainloop;
-    struct mainloop_source *mainloop_source;
+    struct pa_defer_event *defer_event;
     struct pa_iochannel *io;
     struct pa_queue *send_queue;
 
@@ -98,7 +98,7 @@ static void do_read(struct pa_pstream *p);
 
 static void do_something(struct pa_pstream *p) {
     assert(p && !p->shall_free);
-    p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 0);
+    p->mainloop->defer_enable(p->defer_event, 0);
 
     if (p->dead)
         return;
@@ -139,9 +139,9 @@ static void io_callback(struct pa_iochannel*io, void *userdata) {
     do_something(p);
 }
 
-static void fixed_callback(struct pa_mainloop_api *m, void *id, void*userdata) {
+static void defer_callback(struct pa_mainloop_api *m, struct pa_defer_event *e, void*userdata) {
     struct pa_pstream *p = userdata;
-    assert(p && p->mainloop_source == id && p->mainloop == m);
+    assert(p && p->defer_event == e && p->mainloop == m);
     do_something(p);
 }
 
@@ -159,8 +159,8 @@ struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel
     p->die_callback_userdata = NULL;
 
     p->mainloop = m;
-    p->mainloop_source = m->source_fixed(m, fixed_callback, p);
-    m->enable_fixed(m, p->mainloop_source, 0);
+    p->defer_event = m->defer_new(m, defer_callback, p);
+    m->defer_enable(p->defer_event, 0);
     
     p->send_queue = pa_queue_new();
     assert(p->send_queue);
@@ -223,7 +223,7 @@ void pa_pstream_free(struct pa_pstream *p) {
     if (p->read.packet)
         pa_packet_unref(p->read.packet);
 
-    p->mainloop->cancel_fixed(p->mainloop, p->mainloop_source);
+    p->mainloop->defer_free(p->defer_event);
     pa_xfree(p);
 }
 
@@ -236,7 +236,7 @@ void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) {
     i->packet = pa_packet_ref(packet);
 
     pa_queue_push(p->send_queue, i);
-    p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 1);
+    p->mainloop->defer_enable(p->defer_event, 1);
 }
 
 void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk) {
@@ -252,7 +252,7 @@ void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t del
     pa_memblock_ref(i->chunk.memblock);
 
     pa_queue_push(p->send_queue, i);
-    p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 1);
+    p->mainloop->defer_enable(p->defer_event, 1);
 }
 
 void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata), void *userdata) {
index c0c355de0374d2885ffdf18d578f3d27ad6e584a..e8cb2f92a8349db242d4c3715e51018cf254a05f 100644 (file)
@@ -41,8 +41,8 @@
 struct pa_socket_client {
     struct pa_mainloop_api *mainloop;
     int fd;
-
-    void *io_source, *fixed_source;
+    struct pa_io_event *io_event;
+    struct pa_defer_event *defer_event;
     void (*callback)(struct pa_socket_client*c, struct pa_iochannel *io, void *userdata);
     void *userdata;
 };
@@ -54,7 +54,8 @@ static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) {
     c = pa_xmalloc(sizeof(struct pa_socket_client));
     c->mainloop = m;
     c->fd = -1;
-    c->io_source = c->fixed_source = NULL;
+    c->io_event = NULL;
+    c->defer_event = NULL;
     c->callback = NULL;
     c->userdata = NULL;
     return c;
@@ -95,19 +96,19 @@ failed:
     return;
 }
 
-static void connect_fixed_cb(struct pa_mainloop_api *m, void *id, void *userdata) {
+static void connect_fixed_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) {
     struct pa_socket_client *c = userdata;
-    assert(m && c && c->fixed_source == id);
-    m->cancel_fixed(m, c->fixed_source);
-    c->fixed_source = NULL;
+    assert(m && c && c->defer_event == e);
+    m->defer_free(c->defer_event);
+    c->defer_event = NULL;
     do_call(c);
 }
 
-static void connect_io_cb(struct pa_mainloop_api*m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) {
+static void connect_io_cb(struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) {
     struct pa_socket_client *c = userdata;
-    assert(m && c && c->io_source == id && fd >= 0);
-    m->cancel_io(m, c->io_source);
-    c->io_source = NULL;
+    assert(m && c && c->io_event == e && fd >= 0);
+    m->io_free(c->io_event);
+    c->io_event = NULL;
     do_call(c);
 }
 
@@ -123,11 +124,11 @@ static int do_connect(struct pa_socket_client *c, const struct sockaddr *sa, soc
             return -1;
         }
 
-        c->io_source = c->mainloop->source_io(c->mainloop, c->fd, PA_MAINLOOP_API_IO_EVENT_OUTPUT, connect_io_cb, c);
-        assert(c->io_source);
+        c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c);
+        assert(c->io_event);
     } else {
-        c->fixed_source = c->mainloop->source_fixed(c->mainloop, connect_fixed_cb, c);
-        assert(c->fixed_source);
+        c->defer_event = c->mainloop->defer_new(c->mainloop, connect_fixed_cb, c);
+        assert(c->defer_event);
     }
 
     return 0;
@@ -220,10 +221,10 @@ fail:
 
 void pa_socket_client_free(struct pa_socket_client *c) {
     assert(c && c->mainloop);
-    if (c->io_source)
-        c->mainloop->cancel_io(c->mainloop, c->io_source);
-    if (c->fixed_source)
-        c->mainloop->cancel_fixed(c->mainloop, c->fixed_source);
+    if (c->io_event)
+        c->mainloop->io_free(c->io_event);
+    if (c->defer_event)
+        c->mainloop->defer_free(c->defer_event);
     if (c->fd >= 0)
         close(c->fd);
     pa_xfree(c);
index 5f332f0c1d64f6e680cd44a707405a26e377c924..6af2c2865688c572ef72bb153cbc5a828f6d4735 100644 (file)
@@ -46,16 +46,16 @@ struct pa_socket_server {
     void (*on_connection)(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata);
     void *userdata;
 
-    void *mainloop_source;
+    struct pa_io_event *io_event;
     struct pa_mainloop_api *mainloop;
     enum { SOCKET_SERVER_GENERIC, SOCKET_SERVER_IPV4, SOCKET_SERVER_UNIX } type;
 };
 
-static void callback(struct pa_mainloop_api *mainloop, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) {
+static void callback(struct pa_mainloop_api *mainloop, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) {
     struct pa_socket_server *s = userdata;
     struct pa_iochannel *io;
     int nfd;
-    assert(s && s->mainloop == mainloop && s->mainloop_source == id && id && fd >= 0 && fd == s->fd && events == PA_MAINLOOP_API_IO_EVENT_INPUT);
+    assert(s && s->mainloop == mainloop && s->io_event == e && e && fd >= 0 && fd == s->fd);
 
     if ((nfd = accept(fd, NULL, NULL)) < 0) {
         fprintf(stderr, "accept(): %s\n", strerror(errno));
@@ -89,8 +89,8 @@ struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd)
     s->userdata = NULL;
 
     s->mainloop = m;
-    s->mainloop_source = m->source_io(m, fd, PA_MAINLOOP_API_IO_EVENT_INPUT, callback, s);
-    assert(s->mainloop_source);
+    s->io_event = m->io_new(m, fd, PA_IO_EVENT_INPUT, callback, s);
+    assert(s->io_event);
 
     s->type = SOCKET_SERVER_GENERIC;
     
@@ -193,7 +193,7 @@ void pa_socket_server_free(struct pa_socket_server*s) {
         pa_xfree(s->filename);
     }
 
-    s->mainloop->cancel_io(s->mainloop, s->mainloop_source);
+    s->mainloop->io_free(s->io_event);
     pa_xfree(s);
 }
 
index 5f58a8adf0099860755ae6012f1c18c23db2700d..45209b05efc01805af4072616f667b582b792c5a 100644 (file)
@@ -2,6 +2,7 @@
 #define foomemoryhfoo
 
 #include <sys/types.h>
+#include <stdlib.h>
 
 void* pa_xmalloc(size_t l);
 void *pa_xmalloc0(size_t l);