-/* $Id$ */
-
/***
This file is part of PulseAudio.
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2 of the License,
+ by the Free Software Foundation; either version 2.1 of the License,
or (at your option) any later version.
PulseAudio is distributed in the hope that it will be useful, but
pa_ioline_cb_t callback;
void *userdata;
+ pa_ioline_drain_cb_t drain_callback;
+ void *drain_userdata;
+
pa_bool_t dead:1;
pa_bool_t defer_close:1;
};
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);
/* In case the allocated buffer is too small, enlarge it. */
if (l->wbuf_valid_length + len > l->wbuf_length) {
size_t n = l->wbuf_valid_length+len;
- char *new = pa_xnew(char, n);
+ char *new = pa_xnew(char, (unsigned) n);
if (l->wbuf) {
memcpy(new, l->wbuf+l->wbuf_index, l->wbuf_valid_length);
l->userdata = userdata;
}
+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, pa_bool_t process_leftover) {
pa_assert(l);
pa_assert(PA_REFCNT_VALUE(l) >= 1);
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;
memmove(l->rbuf, l->rbuf+l->rbuf_index, l->rbuf_valid_length);
} else {
/* Enlarge the buffer */
- char *new = pa_xnew(char, n);
+ char *new = pa_xnew(char, (unsigned) n);
if (l->rbuf_valid_length)
memcpy(new, l->rbuf+l->rbuf_index, l->rbuf_valid_length);
pa_xfree(l->rbuf);
return -1;
}
- l->rbuf_valid_length += r;
+ l->rbuf_valid_length += (size_t) r;
/* Look if a line has been terminated in the newly read data */
- scan_for_lines(l, l->rbuf_valid_length - r);
+ scan_for_lines(l, l->rbuf_valid_length - (size_t) r);
}
return 0;
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;
+ break;
if (r < 0 && errno != EPIPE)
pa_log("write(): %s", pa_cstrerror(errno));
return -1;
}
- l->wbuf_index += r;
- l->wbuf_valid_length -= r;
+ l->wbuf_index += (size_t) r;
+ l->wbuf_valid_length -= (size_t) r;
/* A shortcut for the next time */
if (l->wbuf_valid_length == 0)
l->wbuf_index = 0;
}
+ if (l->wbuf_valid_length <= 0 && l->drain_callback)
+ l->drain_callback(l, l->drain_userdata);
+
return 0;
}
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;
+}
+
+pa_bool_t pa_ioline_is_drained(pa_ioline *l) {
+ pa_assert(l);
+
+ return l->wbuf_valid_length <= 0;
+}