4 This file is part of polypaudio.
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
36 #define BUFFER_LIMIT (64*1024)
37 #define READ_SIZE (1024)
40 struct pa_iochannel *io;
41 struct pa_defer_event *defer_event;
42 struct pa_mainloop_api *mainloop;
47 size_t wbuf_length, wbuf_index, wbuf_valid_length;
50 size_t rbuf_length, rbuf_index, rbuf_valid_length;
52 void (*callback)(struct pa_ioline*io, const char *s, void *userdata);
58 static void io_callback(struct pa_iochannel*io, void *userdata);
59 static void defer_callback(struct pa_mainloop_api*m, struct pa_defer_event*e, void *userdata);
61 struct pa_ioline* pa_ioline_new(struct pa_iochannel *io) {
65 l = pa_xmalloc(sizeof(struct pa_ioline));
70 l->wbuf_length = l->wbuf_index = l->wbuf_valid_length = 0;
73 l->rbuf_length = l->rbuf_index = l->rbuf_valid_length = 0;
79 l->mainloop = pa_iochannel_get_mainloop_api(io);
81 l->defer_event = l->mainloop->defer_new(l->mainloop, defer_callback, l);
82 l->mainloop->defer_enable(l->defer_event, 0);
86 pa_iochannel_set_callback(io, io_callback, l);
91 static void ioline_free(struct pa_ioline *l) {
95 pa_iochannel_free(l->io);
98 l->mainloop->defer_free(l->defer_event);
105 void pa_ioline_unref(struct pa_ioline *l) {
106 assert(l && l->ref >= 1);
112 struct pa_ioline* pa_ioline_ref(struct pa_ioline *l) {
113 assert(l && l->ref >= 1);
119 void pa_ioline_close(struct pa_ioline *l) {
120 assert(l && l->ref >= 1);
124 pa_iochannel_free(l->io);
128 if (l->defer_event) {
129 l->mainloop->defer_free(l->defer_event);
130 l->defer_event = NULL;
134 void pa_ioline_puts(struct pa_ioline *l, const char *c) {
136 assert(l && c && l->ref >= 1 && !l->dead);
141 if (len > BUFFER_LIMIT - l->wbuf_valid_length)
142 len = BUFFER_LIMIT - l->wbuf_valid_length;
145 assert(l->wbuf_length >= l->wbuf_valid_length);
147 /* In case the allocated buffer is too small, enlarge it. */
148 if (l->wbuf_valid_length + len > l->wbuf_length) {
149 size_t n = l->wbuf_valid_length+len;
150 char *new = pa_xmalloc(n);
152 memcpy(new, l->wbuf+l->wbuf_index, l->wbuf_valid_length);
158 } else if (l->wbuf_index + l->wbuf_valid_length + len > l->wbuf_length) {
160 /* In case the allocated buffer fits, but the current index is too far from the start, move it to the front. */
161 memmove(l->wbuf, l->wbuf+l->wbuf_index, l->wbuf_valid_length);
165 assert(l->wbuf_index + l->wbuf_valid_length + len <= l->wbuf_length);
167 /* Append the new string */
168 memcpy(l->wbuf + l->wbuf_index + l->wbuf_valid_length, c, len);
169 l->wbuf_valid_length += len;
171 l->mainloop->defer_enable(l->defer_event, 1);
177 void pa_ioline_set_callback(struct pa_ioline*l, void (*callback)(struct pa_ioline*io, const char *s, void *userdata), void *userdata) {
178 assert(l && l->ref >= 1);
179 l->callback = callback;
180 l->userdata = userdata;
183 static void failure(struct pa_ioline *l) {
184 assert(l && l->ref >= 1 && !l->dead);
189 l->callback(l, NULL, l->userdata);
194 static void scan_for_lines(struct pa_ioline *l, size_t skip) {
195 assert(l && l->ref >= 1 && skip < l->rbuf_valid_length);
197 while (!l->dead && l->rbuf_valid_length > skip) {
201 if (!(e = memchr(l->rbuf + l->rbuf_index + skip, '\n', l->rbuf_valid_length - skip)))
206 p = l->rbuf + l->rbuf_index;
209 l->rbuf_index += m+1;
210 l->rbuf_valid_length -= m+1;
212 /* A shortcut for the next time */
213 if (l->rbuf_valid_length == 0)
217 l->callback(l, p, l->userdata);
222 /* If the buffer became too large and still no newline was found, drop it. */
223 if (l->rbuf_valid_length >= BUFFER_LIMIT)
224 l->rbuf_index = l->rbuf_valid_length = 0;
227 static int do_read(struct pa_ioline *l) {
228 assert(l && l->ref >= 1);
230 while (!l->dead && pa_iochannel_is_readable(l->io)) {
234 len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length;
236 /* Check if we have to enlarge the read buffer */
237 if (len < READ_SIZE) {
238 size_t n = l->rbuf_valid_length+READ_SIZE;
240 if (n >= BUFFER_LIMIT)
243 if (l->rbuf_length >= n) {
244 /* The current buffer is large enough, let's just move the data to the front */
245 if (l->rbuf_valid_length)
246 memmove(l->rbuf, l->rbuf+l->rbuf_index, l->rbuf_valid_length);
248 /* Enlarge the buffer */
249 char *new = pa_xmalloc(n);
250 if (l->rbuf_valid_length)
251 memcpy(new, l->rbuf+l->rbuf_index, l->rbuf_valid_length);
260 len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length;
262 assert(len >= READ_SIZE);
265 r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len);
267 /* Got an EOF, so fake an exit command. */
269 snprintf (l->rbuf, l->rbuf_length, "exit\n");
271 pa_ioline_puts(l, "\nExiting.\n");
274 pa_log(__FILE__": read() failed: %s\n", strerror(errno));
279 l->rbuf_valid_length += r;
281 /* Look if a line has been terminated in the newly read data */
282 scan_for_lines(l, l->rbuf_valid_length - r);
288 /* Try to flush the buffer */
289 static int do_write(struct pa_ioline *l) {
291 assert(l && l->ref >= 1);
293 while (!l->dead && pa_iochannel_is_writable(l->io) && l->wbuf_valid_length) {
295 if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) {
296 pa_log(__FILE__": write() failed: %s\n", r < 0 ? strerror(errno) : "EOF");
302 l->wbuf_valid_length -= r;
304 /* A shortcut for the next time */
305 if (l->wbuf_valid_length == 0)
312 /* Try to flush read/write data */
313 static void do_work(struct pa_ioline *l) {
314 assert(l && l->ref >= 1);
318 l->mainloop->defer_enable(l->defer_event, 0);
326 if (l->defer_close && !l->wbuf_valid_length)
332 static void io_callback(struct pa_iochannel*io, void *userdata) {
333 struct pa_ioline *l = userdata;
334 assert(io && l && l->ref >= 1);
339 static void defer_callback(struct pa_mainloop_api*m, struct pa_defer_event*e, void *userdata) {
340 struct pa_ioline *l = userdata;
341 assert(l && l->ref >= 1 && l->mainloop == m && l->defer_event == e);
346 void pa_ioline_defer_close(struct pa_ioline *l) {
351 if (!l->wbuf_valid_length)
352 l->mainloop->defer_enable(l->defer_event, 1);
355 void pa_ioline_printf(struct pa_ioline *s, const char *format, ...) {
360 va_start(ap, format);
361 t = pa_vsprintf_malloc(format, ap);
364 pa_ioline_puts(s, t);