diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2008-06-02 17:06:37 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2008-06-02 17:06:37 +0000 |
commit | ccd1e262894f7acabd967326df8b448735c875c1 (patch) | |
tree | ddc9ade3a695e6db3506d8f691005fa0194bf699 /usr.bin/aucat | |
parent | 4f92cff25e1dfa784687da8cbd132f619aadefd0 (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.h | 13 | ||||
-rw-r--r-- | usr.bin/aucat/aproc.c | 48 | ||||
-rw-r--r-- | usr.bin/aucat/aproc.h | 10 | ||||
-rw-r--r-- | usr.bin/aucat/aucat.c | 47 |
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; |