#include <pulse/xmalloc.h>
-#include <pulsecore/winsock.h>
+#include <pulsecore/socket.h>
#include <pulsecore/core-error.h>
+#include <pulsecore/core-util.h>
#include <pulsecore/log.h>
#include <pulsecore/macro.h>
#include <pulsecore/refcnt.h>
pa_ioline_cb_t callback;
void *userdata;
- pa_bool_t dead:1;
- pa_bool_t defer_close:1;
+ pa_ioline_drain_cb_t drain_callback;
+ void *drain_userdata;
+
+ bool dead:1;
+ bool defer_close:1;
};
static void io_callback(pa_iochannel*io, void *userdata);
l->callback = NULL;
l->userdata = NULL;
+ l->drain_callback = NULL;
+ l->drain_userdata = NULL;
+
l->mainloop = pa_iochannel_get_mainloop_api(io);
l->defer_event = l->mainloop->defer_new(l->mainloop, defer_callback, l);
l->mainloop->defer_enable(l->defer_event, 0);
- l->dead = FALSE;
- l->defer_close = FALSE;
+ l->dead = false;
+ l->defer_close = false;
pa_iochannel_set_callback(io, io_callback, l);
pa_assert(l);
pa_assert(PA_REFCNT_VALUE(l) >= 1);
- l->dead = TRUE;
+ l->dead = true;
if (l->io) {
pa_iochannel_free(l->io);
l->userdata = userdata;
}
-static void failure(pa_ioline *l, pa_bool_t process_leftover) {
+void pa_ioline_set_drain_callback(pa_ioline*l, pa_ioline_drain_cb_t callback, void *userdata) {
+ pa_assert(l);
+ pa_assert(PA_REFCNT_VALUE(l) >= 1);
+
+ if (l->dead)
+ return;
+
+ l->drain_callback = callback;
+ l->drain_userdata = userdata;
+}
+
+static void failure(pa_ioline *l, bool process_leftover) {
pa_assert(l);
pa_assert(PA_REFCNT_VALUE(l) >= 1);
pa_assert(!l->dead);
pa_assert(l);
pa_assert(PA_REFCNT_VALUE(l) >= 1);
- while (!l->dead && pa_iochannel_is_readable(l->io)) {
+ while (l->io && !l->dead && pa_iochannel_is_readable(l->io)) {
ssize_t r;
size_t len;
if (r < 0 && errno != ECONNRESET) {
pa_log("read(): %s", pa_cstrerror(errno));
- failure(l, FALSE);
+ failure(l, false);
} else
- failure(l, TRUE);
+ failure(l, true);
return -1;
}
pa_assert(l);
pa_assert(PA_REFCNT_VALUE(l) >= 1);
- while (!l->dead && pa_iochannel_is_writable(l->io) && l->wbuf_valid_length) {
+ while (l->io && !l->dead && pa_iochannel_is_writable(l->io) && l->wbuf_valid_length > 0) {
- if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) <= 0) {
-
- if (r < 0 && errno == EAGAIN)
- return 0;
+ if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) {
- if (r < 0 && errno != EPIPE)
+ if (errno != EPIPE)
pa_log("write(): %s", pa_cstrerror(errno));
- failure(l, FALSE);
+ failure(l, false);
return -1;
}
l->wbuf_index = 0;
}
+ if (l->wbuf_valid_length <= 0 && l->drain_callback)
+ l->drain_callback(l, l->drain_userdata);
+
return 0;
}
do_write(l);
if (l->defer_close && !l->wbuf_valid_length)
- failure(l, TRUE);
+ failure(l, true);
pa_ioline_unref(l);
}
pa_assert(l);
pa_assert(PA_REFCNT_VALUE(l) >= 1);
- l->defer_close = TRUE;
+ l->defer_close = true;
if (!l->wbuf_valid_length)
l->mainloop->defer_enable(l->defer_event, 1);
pa_ioline_puts(l, t);
pa_xfree(t);
}
+
+pa_iochannel* pa_ioline_detach_iochannel(pa_ioline *l) {
+ pa_iochannel *r;
+
+ pa_assert(l);
+
+ if (!l->io)
+ return NULL;
+
+ r = l->io;
+ l->io = NULL;
+
+ pa_iochannel_set_callback(r, NULL, NULL);
+
+ return r;
+}
+
+bool pa_ioline_is_drained(pa_ioline *l) {
+ pa_assert(l);
+
+ return l->wbuf_valid_length <= 0;
+}