version 1.3, 2008/08/14 09:39:16 |
version 1.4, 2008/08/14 09:44:15 |
|
|
#include <err.h> |
#include <err.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
|
#include <string.h> |
|
|
#include "conf.h" |
#include "conf.h" |
#include "aproc.h" |
#include "aproc.h" |
|
|
buf->len = len; |
buf->len = len; |
buf->used = 0; |
buf->used = 0; |
buf->start = 0; |
buf->start = 0; |
|
buf->silence = 0; |
|
buf->drop = 0; |
buf->rproc = NULL; |
buf->rproc = NULL; |
buf->wproc = NULL; |
buf->wproc = NULL; |
buf->data = (unsigned char *)buf + sizeof(*buf); |
buf->data = (unsigned char *)buf + sizeof(*buf); |
|
|
} |
} |
|
|
/* |
/* |
|
* flush buffer either by dropping samples or by calling the aproc |
|
* call-back to consume data. Return 0 if blocked, 1 otherwise |
|
*/ |
|
int |
|
abuf_flush_do(struct abuf *buf) |
|
{ |
|
struct aproc *p; |
|
unsigned count; |
|
|
|
if (buf->drop > 0) { |
|
count = buf->drop; |
|
if (count > buf->used) |
|
count = buf->used; |
|
abuf_rdiscard(buf, count); |
|
buf->drop -= count; |
|
DPRINTF("abuf_flush_do: drop = %u\n", buf->drop); |
|
} else { |
|
p = buf->rproc; |
|
if (p == NULL || !p->ops->in(p, buf)) |
|
return 0; |
|
} |
|
return 1; |
|
} |
|
|
|
/* |
* Notify the read end of the buffer that there is input available |
* Notify the read end of the buffer that there is input available |
* and that data can be processed again. |
* and that data can be processed again. |
*/ |
*/ |
void |
void |
abuf_flush(struct abuf *buf) |
abuf_flush(struct abuf *buf) |
{ |
{ |
struct aproc *p = buf->rproc; |
|
|
|
for (;;) { |
for (;;) { |
if (!ABUF_ROK(buf)) |
if (!ABUF_ROK(buf)) |
break; |
break; |
if (p == NULL || !p->ops->in(p, buf)) |
if (!abuf_flush_do(buf)) |
break; |
break; |
} |
} |
} |
} |
|
|
/* |
/* |
|
* fill the buffer either by generating silence or by calling the aproc |
|
* call-back to provide data. Return 0 if blocked, 1 otherwise |
|
*/ |
|
int |
|
abuf_fill_do(struct abuf *buf) |
|
{ |
|
struct aproc *p; |
|
unsigned char *data; |
|
unsigned count; |
|
|
|
if (buf->silence > 0) { |
|
data = abuf_wgetblk(buf, &count, 0); |
|
if (count >= buf->silence) |
|
count = buf->silence; |
|
memset(data, 0, count); |
|
abuf_wcommit(buf, count); |
|
buf->silence -= count; |
|
DPRINTF("abuf_fill_do: silence = %u\n", buf->silence); |
|
} else { |
|
p = buf->wproc; |
|
if (p == NULL || !p->ops->out(p, buf)) |
|
return 0; |
|
} |
|
return 1; |
|
} |
|
|
|
/* |
* Notify the write end of the buffer that there is room and data can be |
* Notify the write end of the buffer that there is room and data can be |
* written again. This routine can only be called from the out() |
* written again. This routine can only be called from the out() |
* call-back of the reader. |
* call-back of the reader. |
|
|
void |
void |
abuf_fill(struct abuf *buf) |
abuf_fill(struct abuf *buf) |
{ |
{ |
struct aproc *p = buf->wproc; |
|
|
|
for (;;) { |
for (;;) { |
if (!ABUF_WOK(buf)) |
if (!ABUF_WOK(buf)) |
break; |
break; |
if (p == NULL || !p->ops->out(p, buf)) |
if (!abuf_fill_do(buf)) |
break; |
break; |
} |
} |
} |
} |
|
|
abuf_del(buf); |
abuf_del(buf); |
return; |
return; |
} |
} |
if (ABUF_WOK(buf) && canfill && buf->wproc) { |
if (ABUF_WOK(buf) && canfill) { |
p = buf->wproc; |
canfill = abuf_fill_do(buf); |
canfill = p->ops->out(p, buf); |
|
} else if (ABUF_ROK(buf) && canflush) { |
} else if (ABUF_ROK(buf) && canflush) { |
p = buf->rproc; |
canflush = abuf_flush_do(buf); |
canflush = p->ops->in(p, buf); |
|
} else |
} else |
break; /* can neither read nor write */ |
break; /* can neither read nor write */ |
} |
} |