summaryrefslogtreecommitdiff
path: root/usr.bin/aucat
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2008-06-02 17:06:37 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2008-06-02 17:06:37 +0000
commitccd1e262894f7acabd967326df8b448735c875c1 (patch)
treeddc9ade3a695e6db3506d8f691005fa0194bf699 /usr.bin/aucat
parent4f92cff25e1dfa784687da8cbd132f619aadefd0 (diff)
allow the user to choose the aucat behaviour when underruns/overruns
occur on a per-stream basis, using -Xx flags. There are 3 possible policies: - ignore : ignores underruns/overruns, for instance, this mode could be used for creating simple pipes with utilities; like in your last cdio diff. - sync : insert/discard samples in order to keep all streams in sync, useful for multi-tracker-like apps and/or to sync midi/video/whatever on audio streams (this was the previous behaviour) - error : if overruns/underruns occur, consider it as fatal error and kill the corresponding stream (without disturbing others). Useful, for reliable recordings (and/or debugging aucat itself:). ok jakemsr
Diffstat (limited to 'usr.bin/aucat')
-rw-r--r--usr.bin/aucat/abuf.h13
-rw-r--r--usr.bin/aucat/aproc.c48
-rw-r--r--usr.bin/aucat/aproc.h10
-rw-r--r--usr.bin/aucat/aucat.c47
4 files changed, 93 insertions, 25 deletions
diff --git a/usr.bin/aucat/abuf.h b/usr.bin/aucat/abuf.h
index 67f8a70830a..66dd1ac3154 100644
--- a/usr.bin/aucat/abuf.h
+++ b/usr.bin/aucat/abuf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: abuf.h,v 1.3 2008/06/02 17:03:25 ratchov Exp $ */
+/* $OpenBSD: abuf.h,v 1.4 2008/06/02 17:06:36 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -24,7 +24,12 @@ struct aproc;
struct abuf {
/*
- * misc aproc-specific per-buffer parameters
+ * Misc aproc-specific per-buffer parameters.
+ * since the buffer can connect any pair of aproc structure,
+ * each aproc must have it's own specific data. Thus we cannot
+ * use an union. The only exception is the xrun field, because
+ * there can be only one aproc that absorbs xruns in any
+ * intput->output path.
*/
int mixvol; /* input gain */
unsigned mixdone; /* input of mixer */
@@ -32,6 +37,10 @@ struct abuf {
unsigned mixdrop; /* frames mix_in() will discard */
unsigned subdone; /* output if sub */
unsigned subdrop; /* silence frames sub_out() will insert */
+#define XRUN_IGNORE 0 /* on xrun silently insert/discard samples */
+#define XRUN_SYNC 1 /* catchup to sync to the mix/sub */
+#define XRUN_ERROR 2 /* xruns are errors, eof/hup buffer */
+ unsigned xrun; /* common to mix and sub */
LIST_ENTRY(abuf) ient; /* for mix inputs list */
LIST_ENTRY(abuf) oent; /* for sub outputs list */
diff --git a/usr.bin/aucat/aproc.c b/usr.bin/aucat/aproc.c
index b1131acdd57..ab9e7ede8a4 100644
--- a/usr.bin/aucat/aproc.c
+++ b/usr.bin/aucat/aproc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aproc.c,v 1.4 2008/06/02 17:05:12 ratchov Exp $ */
+/* $OpenBSD: aproc.c,v 1.5 2008/06/02 17:06:36 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -388,11 +388,20 @@ mix_out(struct aproc *p, struct abuf *obuf)
ocount = obuf->mixtodo;
for (i = LIST_FIRST(&p->ibuflist); i != LIST_END(&p->ibuflist); i = inext) {
inext = LIST_NEXT(i, ient);
- if (!ABUF_ROK(i) && i->mixdone == 0) {
- drop = obuf->mixtodo;
- i->mixdone += drop;
- i->mixdrop += drop;
- DPRINTF("mix_out: xrun, drop = %u\n", i->mixdrop);
+ if (!ABUF_ROK(i)) {
+ if ((p->u.mix.flags & MIX_DROP) && i->mixdone == 0) {
+ if (i->xrun == XRUN_ERROR) {
+ mix_rm(p, i);
+ abuf_hup(i);
+ continue;
+ }
+ drop = obuf->mixtodo;
+ i->mixdone += drop;
+ if (i->xrun == XRUN_SYNC)
+ i->mixdrop += drop;
+ DPRINTF("mix_out: xrun, drop = %u\n",
+ i->mixdrop);
+ }
} else
mix_badd(i, obuf);
if (ocount > i->mixdone)
@@ -455,6 +464,7 @@ mix_newin(struct aproc *p, struct abuf *ibuf)
ibuf->mixdone = 0;
ibuf->mixdrop = 0;
ibuf->mixvol = ADATA_UNIT;
+ ibuf->xrun = XRUN_IGNORE;
}
void
@@ -474,6 +484,7 @@ mix_new(void)
struct aproc *p;
p = aproc_new(&mix_ops, "softmix");
+ p->u.mix.flags = 0;
return p;
}
@@ -523,19 +534,26 @@ sub_in(struct aproc *p, struct abuf *ibuf)
done = ibuf->used;
for (i = LIST_FIRST(&p->obuflist); i != LIST_END(&p->obuflist); i = inext) {
inext = LIST_NEXT(i, oent);
- if (!ABUF_WOK(i) && i->subdone == 0) {
- drop = ibuf->used;
- i->subdrop += drop;
- i->subdone += drop;
- DPRINTF("sub_in: xrun, drop = %u\n", i->subdrop);
+ if (!ABUF_WOK(i)) {
+ if ((p->u.sub.flags & SUB_DROP) && i->subdone == 0) {
+ if (i->xrun == XRUN_ERROR) {
+ sub_rm(p, i);
+ abuf_eof(i);
+ continue;
+ }
+ drop = ibuf->used;
+ if (i->xrun == XRUN_SYNC)
+ i->subdrop += drop;
+ i->subdone += drop;
+ DPRINTF("sub_in: xrun, drop = %u\n",
+ i->subdrop);
+ }
} else {
sub_bcopy(ibuf, i);
abuf_flush(i);
}
-#ifdef sub_xrun_disabled
if (!ABUF_WOK(i))
again = 0;
-#endif
if (done > i->subdone)
done = i->subdone;
}
@@ -570,7 +588,7 @@ sub_out(struct aproc *p, struct abuf *obuf)
memset(odata, 0, ocount);
obuf->used += ocount;
obuf->subdrop -= ocount;
- DPRINTF("sub_out: catched, drop = %u\n", obuf->subdrop);
+ DPRINTF("sub_out: catch, drop = %u\n", obuf->subdrop);
}
if (obuf->subdone >= ibuf->used)
@@ -646,6 +664,7 @@ sub_newout(struct aproc *p, struct abuf *obuf)
{
obuf->subdone = 0;
obuf->subdrop = 0;
+ obuf->xrun = XRUN_IGNORE;
}
struct aproc_ops sub_ops = {
@@ -658,6 +677,7 @@ sub_new(void)
struct aproc *p;
p = aproc_new(&sub_ops, "copy");
+ p->u.sub.flags = 0;
return p;
}
diff --git a/usr.bin/aucat/aproc.h b/usr.bin/aucat/aproc.h
index 7973418918a..dc4c1a5eb7a 100644
--- a/usr.bin/aucat/aproc.h
+++ b/usr.bin/aucat/aproc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: aproc.h,v 1.1 2008/05/23 07:15:46 ratchov Exp $ */
+/* $OpenBSD: aproc.h,v 1.2 2008/06/02 17:06:36 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -129,6 +129,14 @@ struct aproc {
struct {
struct aconv ist, ost;
} conv;
+ struct {
+#define MIX_DROP 1
+ unsigned flags;
+ } mix;
+ struct {
+#define SUB_DROP 1
+ unsigned flags;
+ } sub;
} u;
};
diff --git a/usr.bin/aucat/aucat.c b/usr.bin/aucat/aucat.c
index 3c96eef7f3c..93cedcf5560 100644
--- a/usr.bin/aucat/aucat.c
+++ b/usr.bin/aucat/aucat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aucat.c,v 1.21 2008/06/02 17:05:45 ratchov Exp $ */
+/* $OpenBSD: aucat.c,v 1.22 2008/06/02 17:06:36 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -81,6 +81,7 @@
int debug_level = 0;
volatile int quit_flag = 0;
+
/*
* List of allowed encodings and their names.
*/
@@ -189,6 +190,18 @@ opt_hdr(void)
err(1, "%s: bad header specification", optarg);
}
+int
+opt_xrun(void)
+{
+ if (strcmp("ignore", optarg) == 0)
+ return XRUN_IGNORE;
+ if (strcmp("sync", optarg) == 0)
+ return XRUN_SYNC;
+ if (strcmp("error", optarg) == 0)
+ return XRUN_ERROR;
+ errx(1, "%s: onderrun/overrun policy", optarg);
+}
+
/*
* Arguments of -i and -o opations are stored in a list.
*/
@@ -198,6 +211,7 @@ struct farg {
unsigned vol; /* last requested volume */
char *name; /* optarg pointer (no need to copy it */
int hdr; /* header format */
+ int xrun; /* overrun/underrun policy */
int fd; /* file descriptor for I/O */
struct aproc *proc; /* rpipe_xxx our wpipe_xxx */
struct abuf *buf;
@@ -211,7 +225,7 @@ SLIST_HEAD(farglist, farg);
*/
void
opt_file(struct farglist *list,
- struct aparams *par, unsigned vol, int hdr, char *optarg)
+ struct aparams *par, unsigned vol, int hdr, int xrun, char *optarg)
{
struct farg *fa;
size_t namelen;
@@ -232,6 +246,7 @@ opt_file(struct farglist *list,
}
} else
fa->hdr = hdr;
+ fa->xrun = xrun;
fa->par = *par;
fa->vol = vol;
fa->name = optarg;
@@ -345,7 +360,7 @@ int
main(int argc, char **argv)
{
struct sigaction sa;
- int c, u_flag, quiet_flag, ohdr, ihdr;
+ int c, u_flag, quiet_flag, ohdr, ihdr, ixrun, oxrun;
struct farg *fa;
struct farglist ifiles, ofiles;
struct aparams ipar, opar, dipar, dopar, cipar, copar;
@@ -374,9 +389,11 @@ main(int argc, char **argv)
SLIST_INIT(&ifiles);
SLIST_INIT(&ofiles);
ihdr = ohdr = HDR_AUTO;
+ ixrun = oxrun = XRUN_IGNORE;
ivol = ovol = MIDI_TO_ADATA(127);
- while ((c = getopt(argc, argv, "c:C:e:E:r:R:h:H:i:o:f:qu")) != -1) {
+ while ((c = getopt(argc, argv, "c:C:e:E:r:R:h:H:x:X:i:o:f:qu"))
+ != -1) {
switch (c) {
case 'h':
ihdr = opt_hdr();
@@ -384,6 +401,12 @@ main(int argc, char **argv)
case 'H':
ohdr = opt_hdr();
break;
+ case 'x':
+ ixrun = opt_xrun();
+ break;
+ case 'X':
+ oxrun = opt_xrun();
+ break;
case 'c':
opt_ch(&ipar);
break;
@@ -403,10 +426,10 @@ main(int argc, char **argv)
opt_rate(&opar);
break;
case 'i':
- opt_file(&ifiles, &ipar, 127, ihdr, optarg);
+ opt_file(&ifiles, &ipar, 127, ihdr, ixrun, optarg);
break;
case 'o':
- opt_file(&ofiles, &opar, 127, ohdr, optarg);
+ opt_file(&ofiles, &opar, 127, ohdr, oxrun, optarg);
break;
case 'f':
if (devpath)
@@ -557,8 +580,10 @@ main(int argc, char **argv)
*/
SLIST_FOREACH(fa, &ifiles, entry) {
newinput(fa, &cipar, cinfr, quiet_flag);
- if (mix)
+ if (mix) {
aproc_setin(mix, fa->buf);
+ fa->buf->xrun = fa->xrun;
+ }
if (!quiet_flag) {
fprintf(stderr, "%s: reading ", fa->name);
aparams_print(&fa->par);
@@ -567,8 +592,10 @@ main(int argc, char **argv)
}
SLIST_FOREACH(fa, &ofiles, entry) {
newoutput(fa, &copar, confr, quiet_flag);
- if (sub)
+ if (sub) {
aproc_setout(sub, fa->buf);
+ fa->buf->xrun = fa->xrun;
+ }
if (!quiet_flag) {
fprintf(stderr, "%s: writing ", fa->name);
aparams_print(&fa->par);
@@ -645,6 +672,10 @@ main(int argc, char **argv)
if (!quiet_flag)
fprintf(stderr, "starting device...\n");
dev_start(dev->fd);
+ if (mix)
+ mix->u.mix.flags |= MIX_DROP;
+ if (sub)
+ sub->u.sub.flags |= SUB_DROP;
while (!quit_flag) {
if (!file_poll())
break;