summaryrefslogtreecommitdiff
path: root/usr.bin/aucat
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2010-06-04 06:15:29 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2010-06-04 06:15:29 +0000
commit2f26a15fe85a93502fda187db3aa3d3b3af985bb (patch)
treef0058377c8c72be142aaa0d4fe60b0492a2b8bb4 /usr.bin/aucat
parentf0d36a131a1ee4ee7ed9a0c5937c9dab18f7090c (diff)
Allow the audio device to be opened only while it's actually used.
This is necessary for uaudio devices, for instance to start aucat before the device is plugged. Or to unplug a device whithout having to restart aucat when another device is plugged. This is controlled with the new -a option. Allow multiple audio devices to be used concurently, i.e. multiple ``-f devname'' options to be used; -f options must follow per-device options, which is what we do for other options.
Diffstat (limited to 'usr.bin/aucat')
-rw-r--r--usr.bin/aucat/Makefile4
-rw-r--r--usr.bin/aucat/abuf.c14
-rw-r--r--usr.bin/aucat/aproc.h4
-rw-r--r--usr.bin/aucat/aucat.121
-rw-r--r--usr.bin/aucat/aucat.c782
-rw-r--r--usr.bin/aucat/dev.c750
-rw-r--r--usr.bin/aucat/dev.h72
-rw-r--r--usr.bin/aucat/midi.c25
-rw-r--r--usr.bin/aucat/midi.h6
-rw-r--r--usr.bin/aucat/miofile.c8
-rw-r--r--usr.bin/aucat/opt.c11
-rw-r--r--usr.bin/aucat/opt.h9
-rw-r--r--usr.bin/aucat/siofile.c12
-rw-r--r--usr.bin/aucat/sock.c132
-rw-r--r--usr.bin/aucat/sock.h3
-rw-r--r--usr.bin/aucat/wav.c95
-rw-r--r--usr.bin/aucat/wav.h13
17 files changed, 1104 insertions, 857 deletions
diff --git a/usr.bin/aucat/Makefile b/usr.bin/aucat/Makefile
index 7f7771526fa..2d6b5ed88c2 100644
--- a/usr.bin/aucat/Makefile
+++ b/usr.bin/aucat/Makefile
@@ -1,10 +1,10 @@
-# $OpenBSD: Makefile,v 1.12 2010/01/13 10:02:52 ratchov Exp $
+# $OpenBSD: Makefile,v 1.13 2010/06/04 06:15:28 ratchov Exp $
PROG= aucat
SRCS= aucat.c abuf.c aparams.c aproc.c dev.c midi.c file.c headers.c \
siofile.c miofile.c sock.c pipe.c listen.c opt.c wav.c legacy.c dbg.c
MAN= aucat.1 midicat.1
LINKS= ${BINDIR}/aucat ${BINDIR}/midicat
-CFLAGS+= -Wall -Wstrict-prototypes -Wundef
+CFLAGS+= -Wall -Wstrict-prototypes -Wundef -DDEBUG
LDADD+= -lsndio
.include <bsd.prog.mk>
diff --git a/usr.bin/aucat/abuf.c b/usr.bin/aucat/abuf.c
index b1efba206fe..5e565bc0dab 100644
--- a/usr.bin/aucat/abuf.c
+++ b/usr.bin/aucat/abuf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: abuf.c,v 1.21 2010/04/06 20:07:01 ratchov Exp $ */
+/* $OpenBSD: abuf.c,v 1.22 2010/06/04 06:15:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -202,6 +202,12 @@ abuf_rdiscard(struct abuf *buf, unsigned count)
dbg_puts("\n");
dbg_panic();
}
+ if (debug_level >= 4) {
+ abuf_dbg(buf);
+ dbg_puts(": discard(");
+ dbg_putu(count);
+ dbg_puts(")\n");
+ }
#endif
buf->used -= count;
buf->start += count;
@@ -223,6 +229,12 @@ abuf_wcommit(struct abuf *buf, unsigned count)
dbg_puts("\n");
dbg_panic();
}
+ if (debug_level >= 4) {
+ abuf_dbg(buf);
+ dbg_puts(": commit(");
+ dbg_putu(count);
+ dbg_puts(")\n");
+ }
#endif
buf->used += count;
}
diff --git a/usr.bin/aucat/aproc.h b/usr.bin/aucat/aproc.h
index ff5b4584d62..16b6e48dbfe 100644
--- a/usr.bin/aucat/aproc.h
+++ b/usr.bin/aucat/aproc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: aproc.h,v 1.36 2010/05/02 11:12:31 ratchov Exp $ */
+/* $OpenBSD: aproc.h,v 1.37 2010/06/04 06:15:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -175,6 +175,7 @@ struct aproc {
struct timo timo; /* timout for throtteling */
} thru;
struct {
+ struct dev *dev; /* controlled device */
#define CTL_NSLOT 8
#define CTL_NAMEMAX 8
unsigned serial;
@@ -201,6 +202,7 @@ struct aproc {
void (*start)(void *);
void (*stop)(void *);
void (*loc)(void *, unsigned);
+ void (*quit)(void *);
} *ops;
void *arg;
unsigned unit;
diff --git a/usr.bin/aucat/aucat.1 b/usr.bin/aucat/aucat.1
index dfb35e0467e..a94cb907027 100644
--- a/usr.bin/aucat/aucat.1
+++ b/usr.bin/aucat/aucat.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: aucat.1,v 1.69 2010/04/22 17:43:30 ratchov Exp $
+.\" $OpenBSD: aucat.1,v 1.70 2010/06/04 06:15:28 ratchov Exp $
.\"
.\" Copyright (c) 2006 Alexandre Ratchov <alex@caoua.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: April 22 2010 $
+.Dd $Mdocdate: June 4 2010 $
.Dt AUCAT 1
.Os
.Sh NAME
@@ -24,6 +24,7 @@
.Nm aucat
.Bk -words
.Op Fl dlnu
+.Op Fl a Ar flag
.Op Fl b Ar nframes
.Op Fl C Ar min : Ns Ar max
.Op Fl c Ar min : Ns Ar max
@@ -58,6 +59,20 @@ which does not convert on the fly and supports playback of .au files.
.Pp
The options are as follows:
.Bl -tag -width Ds
+.It Fl a Ar flag
+Control whether
+.Nm
+opens the device only when needed or keeps it open all the time.
+If the flag is
+.Va on
+then the device is kept open all the time, ensuring no other program can
+steal it.
+If the flag is
+.Va off ,
+then it's automatically closed, allowing other programs to have direct
+access to the device, or the device to be disconnected.
+The default is
+.Va on .
.It Fl b Ar nframes
The buffer size of the audio device in frames.
A frame consists of one sample for each channel in the stream.
@@ -553,7 +568,7 @@ connected to the
.Va midithru:0
MIDI device:
.Bd -literal -offset indent
-$ aucat -f aucat:0.mmc -t slave -q midithru:0 -i file.wav
+$ aucat -t slave -q midithru:0 -i file.wav -f aucat:0.mmc
.Ed
.Pp
At this stage,
diff --git a/usr.bin/aucat/aucat.c b/usr.bin/aucat/aucat.c
index dbd4de36cc3..97933ab5993 100644
--- a/usr.bin/aucat/aucat.c
+++ b/usr.bin/aucat/aucat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aucat.c,v 1.91 2010/05/08 15:35:45 ratchov Exp $ */
+/* $OpenBSD: aucat.c,v 1.92 2010/06/04 06:15:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -108,13 +108,9 @@ opt_ch(struct aparams *par)
cmin = strtol(optarg, &next, 10);
if (next == optarg || *next != ':')
goto failed;
- if (errno == ERANGE && (cmin == LONG_MIN || cmin == LONG_MAX))
- goto failed;
cmax = strtol(++next, &end, 10);
if (end == next || *end != '\0')
goto failed;
- if (errno == ERANGE && (cmax == LONG_MIN || cmax == LONG_MAX))
- goto failed;
if (cmin < 0 || cmax < cmin || cmax > NCHAN_MAX)
goto failed;
par->cmin = cmin;
@@ -208,59 +204,113 @@ opt_mode(void)
}
/*
- * Arguments of -i, -o and -s options are stored in a list.
+ * stream configuration
+ */
+struct cfstr {
+ SLIST_ENTRY(cfstr) entry;
+ unsigned mode; /* bitmap of MODE_XXX */
+ struct aparams ipar; /* input (read) parameters */
+ struct aparams opar; /* output (write) parameters */
+ unsigned vol; /* last requested volume */
+ int hdr; /* header format */
+ int xrun; /* overrun/underrun policy */
+ int mmc; /* MMC mode */
+ int join; /* join/expand enabled */
+ char *path; /* static path (no need to copy it) */
+};
+
+SLIST_HEAD(cfstrlist, cfstr);
+
+/*
+ * midi device (control stream)
*/
-struct farg {
- SLIST_ENTRY(farg) entry;
- struct aparams ipar; /* input (read) parameters */
- struct aparams opar; /* output (write) parameters */
- unsigned vol; /* last requested volume */
- char *name; /* optarg pointer (no need to copy it */
- int hdr; /* header format */
- int xrun; /* overrun/underrun policy */
- int mmc; /* MMC mode */
- int join; /* join/expand enabled */
- unsigned mode;
+struct cfmid {
+ SLIST_ENTRY(cfmid) entry;
+ char *path; /* static path (no need to copy it) */
};
-SLIST_HEAD(farglist, farg);
+SLIST_HEAD(cfmidlist, cfmid);
/*
- * Add a farg entry to the given list, corresponding
- * to the given file name.
+ * audio device configuration
*/
+struct cfdev {
+ SLIST_ENTRY(cfdev) entry;
+ struct cfstrlist ins; /* files to play */
+ struct cfstrlist outs; /* files to record */
+ struct cfstrlist opts; /* subdevices to expose */
+ struct cfmidlist mids; /* midi ports to subscribe */
+ struct aparams ipar; /* input (read) parameters */
+ struct aparams opar; /* output (write) parameters */
+ unsigned hold; /* open immediately */
+ unsigned bufsz; /* par.bufsz for sio device */
+ unsigned round; /* par.round for sio device */
+ unsigned mode; /* bitmap of MODE_XXX */
+ char *path; /* static path (no need to copy it) */
+};
+
+SLIST_HEAD(cfdevlist, cfdev);
+
void
-farg_add(struct farglist *list,
- struct aparams *ipar, struct aparams *opar, unsigned vol,
- int hdr, int xrun, int mmc, int join, unsigned mode, char *name)
+cfdev_add(struct cfdevlist *list, struct cfdev *templ, char *path)
{
- struct farg *fa;
- size_t namelen;
+ struct cfdev *cd;
- fa = malloc(sizeof(struct farg));
- if (fa == NULL)
- err(1, "%s", name);
+ cd = malloc(sizeof(struct cfdev));
+ if (cd == NULL) {
+ perror("malloc");
+ abort();
+ }
+ *cd = *templ;
+ cd->path = path;
+ SLIST_INSERT_HEAD(list, cd, entry);
+ SLIST_INIT(&templ->ins);
+ SLIST_INIT(&templ->outs);
+ SLIST_INIT(&templ->opts);
+ SLIST_INIT(&templ->mids);
+}
- if (hdr == HDR_AUTO) {
- if (name != NULL && (namelen = strlen(name)) >= 4 &&
- strcasecmp(name + namelen - 4, ".wav") == 0) {
- fa->hdr = HDR_WAV;
- } else {
- fa->hdr = HDR_RAW;
- }
+void
+cfstr_add(struct cfstrlist *list, struct cfstr *templ, char *path)
+{
+ size_t len;
+ struct cfstr *cs;
+ unsigned hdr;
+
+ if (strcmp(path, "-") == 0) {
+ path = NULL;
+ hdr = HDR_RAW;
+ } else if (templ->hdr == HDR_AUTO) {
+ len = strlen(path);
+ if (len >= 4 && strcasecmp(path + len - 4, ".wav") == 0)
+ hdr = HDR_WAV;
+ else
+ hdr = HDR_RAW;
} else
- fa->hdr = hdr;
- if (mmc && xrun == XRUN_IGNORE)
- xrun = XRUN_SYNC;
- fa->xrun = xrun;
- fa->ipar = *ipar;
- fa->opar = *opar;
- fa->vol = vol;
- fa->name = name;
- fa->mmc = mmc;
- fa->join = join;
- fa->mode = mode;
- SLIST_INSERT_HEAD(list, fa, entry);
+ hdr = templ->hdr;
+ cs = malloc(sizeof(struct cfstr));
+ if (cs == NULL) {
+ perror("malloc");
+ abort();
+ }
+ *cs = *templ;
+ cs->path = path;
+ cs->hdr = hdr;
+ SLIST_INSERT_HEAD(list, cs, entry);
+}
+
+void
+cfmid_add(struct cfmidlist *list, char *path)
+{
+ struct cfmid *cm;
+
+ cm = malloc(sizeof(struct cfmid));
+ if (cm == NULL) {
+ perror("malloc");
+ abort();
+ }
+ cm->path = path;
+ SLIST_INSERT_HEAD(list, cm, entry);
}
void
@@ -356,51 +406,9 @@ privdrop(void)
}
void
-stopall(void)
-{
- struct file *f;
-
- restart:
- LIST_FOREACH(f, &file_list, entry) {
- /*
- * skip connected streams (handled by dev_close())
- */
- if (APROC_OK(dev_mix)) {
- if (f->rproc && aproc_depend(dev_mix, f->rproc))
- continue;
- if (f->wproc && aproc_depend(f->wproc, dev_mix))
- continue;
- }
- if (APROC_OK(dev_sub)) {
- if (f->rproc && aproc_depend(dev_sub, f->rproc))
- continue;
- if (f->wproc && aproc_depend(f->wproc, dev_sub))
- continue;
- }
- if (APROC_OK(dev_submon)) {
- if (f->rproc && aproc_depend(dev_submon, f->rproc))
- continue;
- if (f->wproc && aproc_depend(f->wproc, dev_submon))
- continue;
- }
- if (APROC_OK(dev_midi)) {
- if (f->rproc && aproc_depend(dev_midi, f->rproc))
- continue;
- if (f->wproc && aproc_depend(f->wproc, dev_midi))
- continue;
- }
- /*
- * kill anything else
- */
- file_close(f);
- goto restart;
- }
-}
-
-void
aucat_usage(void)
{
- (void)fputs("usage: " PROG_AUCAT " [-dlnu] [-b nframes] "
+ (void)fputs("usage: " PROG_AUCAT " [-dlnu] [-a flag] [-b nframes] "
"[-C min:max] [-c min:max] [-e enc]\n\t"
"[-f device] [-h fmt] [-i file] [-j flag] [-m mode]"
"[-o file] [-q device]\n\t"
@@ -413,40 +421,69 @@ aucat_usage(void)
int
aucat_main(int argc, char **argv)
{
- int c, u_flag, d_flag, l_flag, n_flag, hdr, xrun, unit;
- struct farg *fa;
- struct farglist ifiles, ofiles, sfiles, qfiles;
- struct aparams ipar, opar, dipar, dopar;
- char base[PATH_MAX], path[PATH_MAX], *file;
- unsigned bufsz, round, mode;
- char *devpath;
+ struct cfdevlist cfdevs;
+ struct cfmid *cm;
+ struct cfstr *cs;
+ struct cfdev *cd;
+ struct listen *listen = NULL;
+ int c, u_flag, d_flag, l_flag, n_flag, unit;
+ char base[PATH_MAX], path[PATH_MAX];
+ unsigned mode, rate;
const char *str;
- unsigned volctl;
- int mmc, autostart, join;
+ char *legacy_path;
+ int autostart, legacy;
+ struct dev *d, *dnext;
+ unsigned active;
- aparams_init(&ipar, 0, 1, 44100);
- aparams_init(&opar, 0, 1, 44100);
+ /*
+ * global options defaults
+ */
+ unit = -1;
u_flag = 0;
d_flag = 0;
l_flag = 0;
n_flag = 0;
- unit = -1;
- mmc = 0;
- devpath = NULL;
- SLIST_INIT(&ifiles);
- SLIST_INIT(&ofiles);
- SLIST_INIT(&sfiles);
- SLIST_INIT(&qfiles);
- hdr = HDR_AUTO;
- xrun = XRUN_IGNORE;
- volctl = MIDI_MAXCTL;
- mode = MODE_PLAY | MODE_REC;
- bufsz = 0;
- round = 0;
- autostart = 1;
- join = 1;
-
- while ((c = getopt(argc, argv, "dnb:c:C:e:r:h:x:v:i:o:f:m:luq:s:U:t:j:z:")) != -1) {
+ legacy = 1;
+ legacy_path = NULL;
+ SLIST_INIT(&cfdevs);
+
+ /*
+ * default stream params
+ */
+ cs = malloc(sizeof(struct cfstr));
+ if (cs == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ aparams_init(&cs->ipar, 0, 1, 44100);
+ aparams_init(&cs->opar, 0, 1, 44100);
+ cs->mmc = 0;
+ cs->hdr = HDR_AUTO;
+ cs->xrun = XRUN_IGNORE;
+ cs->vol = MIDI_MAXCTL;
+ cs->mode = MODE_PLAY | MODE_REC;
+ cs->join = 1;
+
+ /*
+ * default device
+ */
+ cd = malloc(sizeof(struct cfdev));
+ if (cd == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ aparams_init(&cd->ipar, 0, 1, 44100);
+ aparams_init(&cd->opar, 0, 1, 44100);
+ SLIST_INIT(&cd->ins);
+ SLIST_INIT(&cd->outs);
+ SLIST_INIT(&cd->opts);
+ SLIST_INIT(&cd->mids);
+ cd->path = NULL;
+ cd->bufsz = 0;
+ cd->round = 0;
+ cd->hold = 1;
+
+ while ((c = getopt(argc, argv, "a:dnb:c:C:e:r:h:x:v:i:o:f:m:luq:s:U:t:j:z:")) != -1) {
switch (c) {
case 'd':
#ifdef DEBUG
@@ -456,97 +493,113 @@ aucat_main(int argc, char **argv)
d_flag = 1;
break;
case 'n':
+ legacy = 0;
n_flag = 1;
break;
+ case 'u':
+ legacy = 0;
+ u_flag = 1;
+ break;
+ case 'U':
+ legacy = 0;
+ unit = strtonum(optarg, 0, MIDI_MAXCTL, &str);
+ if (str)
+ errx(1, "%s: unit number is %s", optarg, str);
+ break;
case 'm':
- mode = opt_mode();
+ legacy = 0;
+ cs->mode = opt_mode();
+ cd->mode = cs->mode;
break;
case 'h':
- hdr = opt_hdr();
+ legacy = 0;
+ cs->hdr = opt_hdr();
break;
case 'x':
- xrun = opt_xrun();
+ legacy = 0;
+ cs->xrun = opt_xrun();
break;
case 'j':
- join = opt_onoff();
+ legacy = 0;
+ cs->join = opt_onoff();
break;
case 't':
- mmc = opt_mmc();
- if (mmc)
- autostart = 0;
+ legacy = 0;
+ cs->mmc = opt_mmc();
break;
case 'c':
- opt_ch(&ipar);
+ legacy = 0;
+ opt_ch(&cs->ipar);
+ cd->opar.cmin = cs->ipar.cmin;
+ cd->opar.cmax = cs->ipar.cmax;
break;
case 'C':
- opt_ch(&opar);
+ legacy = 0;
+ opt_ch(&cs->opar);
+ cd->ipar.cmin = cs->opar.cmin;
+ cd->ipar.cmax = cs->opar.cmax;
break;
case 'e':
- opt_enc(&ipar);
- aparams_copyenc(&opar, &ipar);
+ legacy = 0;
+ opt_enc(&cs->ipar);
+ aparams_copyenc(&cs->opar, &cs->ipar);
break;
case 'r':
- ipar.rate = strtonum(optarg, RATE_MIN, RATE_MAX, &str);
+ legacy = 0;
+ rate = strtonum(optarg, RATE_MIN, RATE_MAX, &str);
if (str)
errx(1, "%s: rate is %s", optarg, str);
- opar.rate = ipar.rate;
+ cs->opar.rate = cs->ipar.rate = rate;
+ cd->ipar.rate = cd->opar.rate = rate;
break;
case 'v':
- volctl = strtonum(optarg, 0, MIDI_MAXCTL, &str);
+ legacy = 0;
+ cs->vol = strtonum(optarg, 0, MIDI_MAXCTL, &str);
if (str)
errx(1, "%s: volume is %s", optarg, str);
break;
case 'i':
- file = optarg;
- if (strcmp(file, "-") == 0)
- file = NULL;
- farg_add(&ifiles, &ipar, &opar, volctl,
- hdr, xrun, mmc, join, mode & MODE_PLAY, file);
+ legacy = 0;
+ cfstr_add(&cd->ins, cs, optarg);
break;
case 'o':
- file = optarg;
- if (strcmp(file, "-") == 0)
- file = NULL;
- farg_add(&ofiles, &ipar, &opar, volctl,
- hdr, xrun, mmc, join, mode & MODE_RECMASK, file);
+ legacy = 0;
+ cfstr_add(&cd->outs, cs, optarg);
break;
case 's':
- farg_add(&sfiles, &ipar, &opar, volctl,
- hdr, xrun, mmc, join, mode, optarg);
+ legacy = 0;
+ cfstr_add(&cd->opts, cs, optarg);
break;
- case 'q':
- farg_add(&qfiles, &aparams_none, &aparams_none,
- 0, HDR_RAW, 0, 0, 0, 0, optarg);
+ case 'a':
+ legacy = 0;
+ cd->hold = opt_onoff();
break;
- case 'f':
- if (devpath)
- err(1, "only one -f allowed");
- devpath = optarg;
- dipar = opar;
- dopar = ipar;
- break;
- case 'l':
- l_flag = 1;
- autostart = 0;
- break;
- case 'u':
- u_flag = 1;
+ case 'q':
+ legacy = 0;
+ cfmid_add(&cd->mids, optarg);
break;
case 'b':
- bufsz = strtonum(optarg, 1, RATE_MAX * 5, &str);
+ legacy = 0;
+ cd->bufsz = strtonum(optarg, 1, RATE_MAX * 5, &str);
if (str)
errx(1, "%s: buffer size is %s", optarg, str);
break;
- case 'U':
- unit = strtonum(optarg, 0, MIDI_MAXCTL, &str);
- if (str)
- errx(1, "%s: device number is %s", optarg, str);
- break;
case 'z':
- round = strtonum(optarg, 1, SHRT_MAX, &str);
+ legacy = 0;
+ cd->round = strtonum(optarg, 1, SHRT_MAX, &str);
if (str)
errx(1, "%s: block size is %s", optarg, str);
break;
+ case 'f':
+ legacy = 0;
+ legacy_path = optarg;
+ cfdev_add(&cfdevs, cd, optarg);
+ break;
+ case 'l':
+ legacy = 0;
+ l_flag = 1;
+ autostart = 0;
+ break;
default:
aucat_usage();
exit(1);
@@ -555,46 +608,51 @@ aucat_main(int argc, char **argv)
argc -= optind;
argv += optind;
- if (!devpath) {
- dopar = ipar;
- dipar = opar;
- }
- if (!l_flag && SLIST_EMPTY(&ifiles) && SLIST_EMPTY(&ofiles)) {
- if (argc > 0) {
- /*
- * Legacy mode: if no -i or -o options are provided, and
- * there are arguments then assume the arguments are files
- * to play.
- */
- for (c = 0; c < argc; c++)
- if (legacy_play(devpath, argv[c]) != 0) {
- errx(1, "%s: could not play\n", argv[c]);
- }
- exit(0);
- } else {
+#ifdef DEBUG
+ if (debug_level == 0)
+ debug_level = 1;
+#endif
+ if (argc > 0) {
+ if (!legacy) {
aucat_usage();
exit(1);
}
+ for (c = 0; c < argc; c++)
+ if (legacy_play(legacy_path, argv[c]) != 0) {
+ errx(1, "%s: could not play\n", argv[c]);
+ }
+ exit(0);
}
- if (!l_flag && (!SLIST_EMPTY(&sfiles) || unit >= 0))
- errx(1, "can't use -s or -U without -l");
- if (l_flag && (!SLIST_EMPTY(&ofiles) || !SLIST_EMPTY(&ifiles)))
- errx(1, "can't use -l, and -s with -o or -i");
+ if (!l_flag && unit >= 0)
+ errx(1, "can't use -U without -l");
if (n_flag) {
- if (devpath != NULL || !SLIST_EMPTY(&qfiles) ||
- l_flag || !autostart)
- errx(1, "can't use -n with -f, -q, -t or -l");
- if (SLIST_EMPTY(&ifiles) || SLIST_EMPTY(&ofiles))
+ if (!SLIST_EMPTY(&cfdevs) || l_flag ||
+ !SLIST_EMPTY(&cd->opts) || !SLIST_EMPTY(&cd->mids))
+ errx(1, "can't use -n with -l, -f, -q or -s");
+ if (SLIST_EMPTY(&cd->ins) || SLIST_EMPTY(&cd->outs))
errx(1, "both -i and -o are required with -n");
}
/*
+ * if no device is given, add the default one
+ */
+ if (SLIST_EMPTY(&cfdevs)) {
+ if (!cd->hold)
+ errx(1, "-a not compatible with default device");
+ cfdev_add(&cfdevs, cd, "default");
+ }
+
+ /*
* If there are no sockets paths provided use the default.
*/
- if (l_flag && SLIST_EMPTY(&sfiles)) {
- farg_add(&sfiles, &ipar, &opar,
- volctl, HDR_RAW, XRUN_IGNORE, mmc, join, mode, DEFAULT_OPT);
+ if (l_flag) {
+ SLIST_FOREACH(cd, &cfdevs, entry) {
+ if (!SLIST_EMPTY(&cd->opts))
+ continue;
+ cfstr_add(&cd->opts, cs, DEFAULT_OPT);
+ break;
+ }
}
/*
@@ -602,40 +660,49 @@ aucat_main(int argc, char **argv)
* inputs and outputs and find the maximum sample rate and channel
* number.
*/
- mode = 0;
- aparams_init(&dipar, dipar.cmin, dipar.cmax, dipar.rate);
- aparams_init(&dopar, dopar.cmin, dopar.cmax, dopar.rate);
- SLIST_FOREACH(fa, &ifiles, entry) {
- if (fa->mode == 0)
- errx(1, "%s: not in play mode", fa->name);
- mode |= fa->mode;
- if (!u_flag)
- aparams_grow(&dopar, &fa->ipar);
- }
- SLIST_FOREACH(fa, &ofiles, entry) {
- if (fa->mode == 0)
- errx(1, "%s: not in rec/mon mode", fa->name);
- if ((fa->mode & MODE_REC) && (fa->mode & MODE_MON))
- errx(1, "%s: can't record and monitor", fa->name);
- mode |= fa->mode;
- if (!u_flag)
- aparams_grow(&dipar, &fa->opar);
- }
- SLIST_FOREACH(fa, &sfiles, entry) {
- if ((fa->mode & MODE_REC) && (fa->mode & MODE_MON))
- errx(1, "%s: can't record and monitor", fa->name);
- mode |= fa->mode;
- if (!u_flag) {
- aparams_grow(&dopar, &fa->ipar);
- aparams_grow(&dipar, &fa->opar);
+ SLIST_FOREACH(cd, &cfdevs, entry) {
+ mode = 0;
+ SLIST_FOREACH(cs, &cd->ins, entry) {
+ if (cs->mode == 0)
+ errx(1, "%s: not in play mode", cs->path);
+ mode |= (cs->mode & MODE_PLAY);
+ if (!u_flag)
+ aparams_grow(&cd->opar, &cs->ipar);
+ }
+ SLIST_FOREACH(cs, &cd->outs, entry) {
+ if (cs->mode == 0)
+ errx(1, "%s: not in rec/mon mode", cs->path);
+ if ((cs->mode & MODE_REC) && (cs->mode & MODE_MON))
+ errx(1, "%s: can't rec and mon", cs->path);
+ mode |= (cs->mode & MODE_RECMASK);
+ if (!u_flag)
+ aparams_grow(&cd->ipar, &cs->opar);
+ }
+ SLIST_FOREACH(cs, &cd->opts, entry) {
+ if ((cs->mode & MODE_REC) && (cs->mode & MODE_MON))
+ errx(1, "%s: can't rec and mon", cs->path);
+ mode |= (cs->mode & (MODE_RECMASK | MODE_PLAY));
+ if (!u_flag) {
+ aparams_grow(&cd->opar, &cs->ipar);
+ aparams_grow(&cd->ipar, &cs->opar);
+ }
}
+ if (l_flag && SLIST_EMPTY(&cd->opts))
+ errx(1, "%s: no subdevs for this device", cd->path);
+ if (!l_flag && SLIST_EMPTY(&cd->ins) && SLIST_EMPTY(&cd->outs))
+ errx(1, "%s: no files for this device", cd->path);
+ if (n_flag && (mode & MODE_MON))
+ errx(1, "monitoring not allowed in loopback mode");
+ if ((mode & MODE_MON) && !(mode & MODE_PLAY))
+ errx(1, "no playback stream to monitor");
+ rate = (mode & MODE_REC) ? cd->ipar.rate : cd->opar.rate;
+ if (!cd->round)
+ cd->round = rate / 15;
+ if (!cd->bufsz)
+ cd->bufsz = rate / 15 * 4;
+ cd->mode = mode;
}
- if (!round)
- round = ((mode & MODE_REC) ? dipar.rate : dopar.rate) / 15;
- if (!bufsz)
- bufsz = ((mode & MODE_REC) ? dipar.rate : dopar.rate) * 4 / 15;
-
if (l_flag) {
getbasepath(base, sizeof(base));
if (unit < 0)
@@ -645,73 +712,86 @@ aucat_main(int argc, char **argv)
filelist_init();
/*
- * Open the device
+ * Open devices
*/
- if (n_flag) {
- if (mode & MODE_MON)
- errx(1, "monitoring not allowed in loopback mode");
- dev_init_loop(&dipar, &dopar, bufsz);
- } else {
- if (l_flag)
- dev_reqprime = 1;
- if ((mode & MODE_MON) && !(mode & MODE_PLAY))
- errx(1, "no playback stream to monitor");
- dev_init_sio(devpath, mode, &dipar, &dopar, bufsz, round);
- }
- if (!dev_ref()) {
- errx(1, "%s: can't open device",
- devpath ? devpath : "<default>");
- }
+ while (!SLIST_EMPTY(&cfdevs)) {
+ cd = SLIST_FIRST(&cfdevs);
+ SLIST_REMOVE_HEAD(&cfdevs, entry);
- /*
- * Create buffers for all input and output pipes.
- */
- while (!SLIST_EMPTY(&qfiles)) {
- fa = SLIST_FIRST(&qfiles);
- SLIST_REMOVE_HEAD(&qfiles, entry);
- if (!dev_thruadd(fa->name, 1, 1))
- errx(1, "%s: can't open device", fa->name);
- free(fa);
- }
- while (!SLIST_EMPTY(&ifiles)) {
- fa = SLIST_FIRST(&ifiles);
- SLIST_REMOVE_HEAD(&ifiles, entry);
- if (!wav_new_in(&wav_ops, fa->mode, fa->name,
- fa->hdr, &fa->ipar, fa->xrun, fa->vol, fa->mmc,
- fa->join))
- exit(1);
- free(fa);
- }
- while (!SLIST_EMPTY(&ofiles)) {
- fa = SLIST_FIRST(&ofiles);
- SLIST_REMOVE_HEAD(&ofiles, entry);
- if (!wav_new_out(&wav_ops, fa->mode, fa->name,
- fa->hdr, &fa->opar, fa->xrun, fa->mmc,
- fa->join))
- free(fa);
- }
- while (!SLIST_EMPTY(&sfiles)) {
- fa = SLIST_FIRST(&sfiles);
- SLIST_REMOVE_HEAD(&sfiles, entry);
- opt_new(fa->name, &fa->opar, &fa->ipar,
- MIDI_TO_ADATA(fa->vol), fa->mmc, fa->join, fa->mode);
- free(fa);
+ if (n_flag) {
+ d = dev_new_loop(&cd->ipar, &cd->opar, cd->bufsz);
+ } else {
+ d = dev_new_sio(cd->path, cd->mode,
+ &cd->ipar, &cd->opar, cd->bufsz, cd->round,
+ cd->hold, l_flag);
+ }
+ if (d == NULL)
+ errx(1, "%s: can't open device", cd->path);
+
+ /*
+ * register midi devices
+ */
+ while (!SLIST_EMPTY(&cd->mids)) {
+ cm = SLIST_FIRST(&cd->mids);
+ SLIST_REMOVE_HEAD(&cd->mids, entry);
+ if (!dev_thruadd(d, cm->path, 1, 1))
+ errx(1, "%s: can't open device", cm->path);
+ free(cm);
+ }
+
+ /*
+ * register files
+ */
+ autostart = 0;
+ while (!SLIST_EMPTY(&cd->ins)) {
+ cs = SLIST_FIRST(&cd->ins);
+ SLIST_REMOVE_HEAD(&cd->ins, entry);
+ if (!cs->mmc)
+ autostart = 1;
+ if (!wav_new_in(&wav_ops, d, cs->mode & MODE_PLAY,
+ cs->path, cs->hdr, &cs->ipar, cs->xrun,
+ cs->vol, cs->mmc, cs->join))
+ exit(1);
+ free(cs);
+ }
+ while (!SLIST_EMPTY(&cd->outs)) {
+ cs = SLIST_FIRST(&cd->outs);
+ SLIST_REMOVE_HEAD(&cd->outs, entry);
+ if (!cs->mmc)
+ autostart = 1;
+ if (!wav_new_out(&wav_ops, d, cs->mode & MODE_RECMASK,
+ cs->path, cs->hdr, &cs->opar, cs->xrun,
+ cs->mmc, cs->join))
+ exit(1);
+ free(cs);
+ }
+ while (!SLIST_EMPTY(&cd->opts)) {
+ cs = SLIST_FIRST(&cd->opts);
+ SLIST_REMOVE_HEAD(&cd->opts, entry);
+ opt_new(cs->path, d, &cs->opar, &cs->ipar,
+ MIDI_TO_ADATA(cs->vol), cs->mmc,
+ cs->join, cs->mode);
+ free(cs);
+ }
+ free(cd);
+ if (autostart) {
+ /*
+ * inject artificial mmc start
+ */
+ ctl_start(d->midi);
+ }
}
if (l_flag) {
snprintf(path, sizeof(path), "%s/%s%u", base,
DEFAULT_SOFTAUDIO, unit);
- listen_new(&listen_ops, path);
+ listen = listen_new(&listen_ops, path);
+ if (listen == 0)
+ exit(1);
if (geteuid() == 0)
privdrop();
if (!d_flag && daemon(0, 0) < 0)
err(1, "daemon");
}
- if (autostart) {
- /*
- * inject artificial mmc start
- */
- ctl_start(dev_midi);
- }
/*
* Loop, start audio.
@@ -719,16 +799,27 @@ aucat_main(int argc, char **argv)
for (;;) {
if (quit_flag)
break;
- if (!dev_run())
+ active = 0;
+ for (d = dev_list; d != NULL; d = dnext) {
+ dnext = d->next;
+ if (!dev_run(d))
+ goto fatal;
+ if (!ctl_idle(d->midi))
+ active = 1;
+ }
+ if (dev_list == NULL)
break;
- if (!l_flag && ctl_idle(dev_midi))
+ if (!l_flag && !active)
break;
if (!file_poll())
break;
}
- dev_unref();
- stopall();
- dev_done();
+ fatal:
+ if (l_flag)
+ file_close(&listen->file);
+ while (dev_list)
+ dev_del(dev_list);
+
/*
* give a chance to drain
*/
@@ -750,24 +841,30 @@ midicat_usage(void)
"[-i file] [-o file] [-q device] [-U unit]\n",
stderr);
}
+
int
midicat_main(int argc, char **argv)
{
+ struct cfmidlist mids, ins, outs;
+ struct cfmid *cm;
+ struct listen *listen = NULL;
int c, d_flag, l_flag, unit, fd;
- struct farglist dfiles, ifiles, ofiles;
char base[PATH_MAX], path[PATH_MAX];
- struct farg *fa;
struct file *stdx;
struct aproc *p;
struct abuf *buf;
const char *str;
+ struct dev *d;
+ /*
+ * global options defaults
+ */
+ unit = -1;
d_flag = 0;
l_flag = 0;
- unit = -1;
- SLIST_INIT(&dfiles);
- SLIST_INIT(&ifiles);
- SLIST_INIT(&ofiles);
+ SLIST_INIT(&mids);
+ SLIST_INIT(&ins);
+ SLIST_INIT(&outs);
while ((c = getopt(argc, argv, "di:o:lf:q:U:")) != -1) {
switch (c) {
@@ -779,18 +876,15 @@ midicat_main(int argc, char **argv)
d_flag = 1;
break;
case 'i':
- farg_add(&ifiles, &aparams_none, &aparams_none,
- 0, HDR_RAW, 0, 0, 0, 0, optarg);
+ cfmid_add(&ins, optarg);
break;
case 'o':
- farg_add(&ofiles, &aparams_none, &aparams_none,
- 0, HDR_RAW, 0, 0, 0, 0, optarg);
+ cfmid_add(&outs, optarg);
break;
/* XXX: backward compat, remove this */
case 'f':
case 'q':
- farg_add(&dfiles, &aparams_none, &aparams_none,
- 0, HDR_RAW, 0, 0, 0, 0, optarg);
+ cfmid_add(&mids, optarg);
break;
case 'l':
l_flag = 1;
@@ -798,7 +892,7 @@ midicat_main(int argc, char **argv)
case 'U':
unit = strtonum(optarg, 0, MIDI_MAXCTL, &str);
if (str)
- errx(1, "%s: device number is %s", optarg, str);
+ errx(1, "%s: unit number is %s", optarg, str);
break;
default:
midicat_usage();
@@ -808,15 +902,14 @@ midicat_main(int argc, char **argv)
argc -= optind;
argv += optind;
- if (argc > 0 || (SLIST_EMPTY(&ifiles) && SLIST_EMPTY(&ofiles) &&
- !l_flag)) {
+ if (argc > 0 || (SLIST_EMPTY(&ins) && SLIST_EMPTY(&outs) && !l_flag)) {
midicat_usage();
exit(1);
}
if (!l_flag && unit >= 0)
errx(1, "can't use -U without -l");
if (l_flag) {
- if (!SLIST_EMPTY(&ifiles) || !SLIST_EMPTY(&ofiles))
+ if (!SLIST_EMPTY(&ins) || !SLIST_EMPTY(&outs))
errx(1, "can't use -i or -o with -l");
getbasepath(base, sizeof(path));
if (unit < 0)
@@ -825,74 +918,72 @@ midicat_main(int argc, char **argv)
setsig();
filelist_init();
- dev_init_thru();
- if (0 && !dev_ref())
- errx(1, "couldn't opem midi thru box");
- if (!l_flag && APROC_OK(dev_midi))
- dev_midi->flags |= APROC_QUIT;
- if ((!SLIST_EMPTY(&ifiles) || !SLIST_EMPTY(&ofiles)) &&
- SLIST_EMPTY(&dfiles)) {
- farg_add(&dfiles, &aparams_none, &aparams_none,
- 0, HDR_RAW, 0, 0, 0, 0, NULL);
+ d = dev_new_thru();
+ if (!dev_ref(d))
+ errx(1, "couldn't open midi thru box");
+ if (!l_flag && APROC_OK(d->midi))
+ d->midi->flags |= APROC_QUIT;
+ if ((!SLIST_EMPTY(&ins) || !SLIST_EMPTY(&outs)) && SLIST_EMPTY(&mids)) {
+ cfmid_add(&mids, "default");
}
- while (!SLIST_EMPTY(&dfiles)) {
- fa = SLIST_FIRST(&dfiles);
- SLIST_REMOVE_HEAD(&dfiles, entry);
- if (!dev_thruadd(fa->name,
- !SLIST_EMPTY(&ofiles) || l_flag,
- !SLIST_EMPTY(&ifiles) || l_flag)) {
- errx(1, "%s: can't open device",
- fa->name ? fa->name : "<default>");
+ while (!SLIST_EMPTY(&mids)) {
+ cm = SLIST_FIRST(&mids);
+ SLIST_REMOVE_HEAD(&mids, entry);
+ if (!dev_thruadd(d, cm->path,
+ !SLIST_EMPTY(&ins) || l_flag,
+ !SLIST_EMPTY(&outs) || l_flag)) {
+ errx(1, "%s: can't open device", cm->path);
}
- free(fa);
+ free(cm);
}
if (l_flag) {
+ opt_new(DEFAULT_OPT, d, NULL, NULL, 0, 0, 0, 0);
snprintf(path, sizeof(path), "%s/%s%u", base,
DEFAULT_MIDITHRU, unit);
- listen_new(&listen_ops, path);
+ listen = listen_new(&listen_ops, path);
if (geteuid() == 0)
privdrop();
if (!d_flag && daemon(0, 0) < 0)
err(1, "daemon");
}
- while (!SLIST_EMPTY(&ifiles)) {
- fa = SLIST_FIRST(&ifiles);
- SLIST_REMOVE_HEAD(&ifiles, entry);
- if (strcmp(fa->name, "-") == 0) {
+ while (!SLIST_EMPTY(&ins)) {
+ cm = SLIST_FIRST(&ins);
+ SLIST_REMOVE_HEAD(&ins, entry);
+ if (strcmp(cm->path, "-") == 0) {
fd = STDIN_FILENO;
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
warn("stdin");
} else {
- fd = open(fa->name, O_RDONLY | O_NONBLOCK, 0666);
+ fd = open(cm->path, O_RDONLY | O_NONBLOCK, 0666);
if (fd < 0)
- err(1, "%s", fa->name);
+ err(1, "%s", cm->path);
}
- stdx = (struct file *)pipe_new(&pipe_ops, fd, fa->name);
+ stdx = (struct file *)pipe_new(&pipe_ops, fd, cm->path);
p = rfile_new(stdx);
buf = abuf_new(MIDI_BUFSZ, &aparams_none);
aproc_setout(p, buf);
- dev_midiattach(buf, NULL);
- free(fa);
+ dev_midiattach(d, buf, NULL);
+ free(cm);
}
- while (!SLIST_EMPTY(&ofiles)) {
- fa = SLIST_FIRST(&ofiles);
- SLIST_REMOVE_HEAD(&ofiles, entry);
- if (strcmp(fa->name, "-") == 0) {
+ while (!SLIST_EMPTY(&outs)) {
+ cm = SLIST_FIRST(&outs);
+ SLIST_REMOVE_HEAD(&outs, entry);
+ if (strcmp(cm->path, "-") == 0) {
fd = STDOUT_FILENO;
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
warn("stdout");
} else {
- fd = open(fa->name,
+ fd = open(cm->path,
O_WRONLY | O_TRUNC | O_CREAT | O_NONBLOCK, 0666);
if (fd < 0)
- err(1, "%s", fa->name);
+ err(1, "%s", cm->path);
}
- stdx = (struct file *)pipe_new(&pipe_ops, fd, fa->name);
+ stdx = (struct file *)pipe_new(&pipe_ops, fd, cm->path);
p = wfile_new(stdx);
buf = abuf_new(MIDI_BUFSZ, &aparams_none);
aproc_setin(p, buf);
- dev_midiattach(NULL, buf);
- free(fa);
+ dev_midiattach(d, NULL, buf);
+ free(cm);
}
/*
* loop, start processing
@@ -900,15 +991,15 @@ midicat_main(int argc, char **argv)
for (;;) {
if (quit_flag)
break;
- if (!dev_run())
+ if (!dev_run(d))
break;
if (!file_poll())
break;
}
- stopall();
- if (0)
- dev_unref();
- dev_done();
+ if (l_flag)
+ file_close(&listen->file);
+ dev_unref(d);
+ dev_del(d);
/*
* drain
*/
@@ -923,7 +1014,6 @@ midicat_main(int argc, char **argv)
return 0;
}
-
int
main(int argc, char **argv)
{
diff --git a/usr.bin/aucat/dev.c b/usr.bin/aucat/dev.c
index 3f76b0cba9a..19b73b08f70 100644
--- a/usr.bin/aucat/dev.c
+++ b/usr.bin/aucat/dev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.c,v 1.56 2010/05/08 15:35:45 ratchov Exp $ */
+/* $OpenBSD: dev.c,v 1.57 2010/06/04 06:15:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -25,9 +25,9 @@
*
* From the main loop, the device is used as follows:
*
- * 1. create the device using dev_init_xxx()
+ * 1. create the device using dev_new_xxx()
* 2. call dev_run() in the event loop
- * 3. destroy the device using dev_done()
+ * 3. destroy the device using dev_del()
* 4. continue running the event loop to drain
*
* The device is used as follows from aproc context:
@@ -100,89 +100,103 @@
#include "dbg.h"
#endif
-/*
- * state of the device
- */
-#define DEV_CLOSED 0 /* closed */
-#define DEV_INIT 1 /* stopped */
-#define DEV_START 2 /* ready to start */
-#define DEV_RUN 3 /* started */
-
-/*
- * desired parameters
- */
-unsigned dev_reqmode; /* mode */
-struct aparams dev_reqipar, dev_reqopar; /* parameters */
-unsigned dev_reqbufsz; /* buffer size */
-unsigned dev_reqround; /* block size */
-unsigned dev_reqprime; /* prime play buffer? */
-
-/*
- * actual parameters and runtime state
- */
-char *dev_path; /* sio path */
-unsigned dev_refcnt = 0; /* number of openers */
-unsigned dev_pstate; /* on of DEV_xxx */
-unsigned dev_mode; /* bitmap of MODE_xxx */
-unsigned dev_bufsz, dev_round, dev_rate;
-struct aparams dev_ipar, dev_opar;
-struct aproc *dev_mix, *dev_sub, *dev_rec, *dev_play, *dev_submon, *dev_mon;
-struct aproc *dev_midi;
+int dev_open(struct dev *);
+void dev_close(struct dev *);
+void dev_start(struct dev *);
+void dev_stop(struct dev *);
+void dev_clear(struct dev *);
+void dev_prime(struct dev *);
-void dev_start(void);
-void dev_stop(void);
-void dev_clear(void);
-void dev_prime(void);
+struct dev *dev_list = NULL;
/*
* Create a sndio device
*/
-void
-dev_init_sio(char *path, unsigned mode,
- struct aparams *dipar, struct aparams *dopar,
- unsigned bufsz, unsigned round)
+struct dev *
+dev_new_sio(char *path,
+ unsigned mode, struct aparams *dipar, struct aparams *dopar,
+ unsigned bufsz, unsigned round, unsigned hold, unsigned prime)
{
- dev_path = path;
- dev_reqmode = mode;
+ struct dev *d;
+
+ d = malloc(sizeof(struct dev));
+ if (d == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ d->path = path;
+ d->reqmode = mode;
if (mode & MODE_PLAY)
- dev_reqopar = *dopar;
+ d->reqopar = *dopar;
if (mode & MODE_RECMASK)
- dev_reqipar = *dipar;
- dev_reqbufsz = bufsz;
- dev_reqround = round;
- dev_pstate = DEV_CLOSED;
+ d->reqipar = *dipar;
+ d->reqbufsz = bufsz;
+ d->reqround = round;
+ d->prime = prime;
+ d->hold = hold;
+ d->pstate = DEV_CLOSED;
+ d->next = dev_list;
+ dev_list = d;
+ if (d->hold && !dev_open(d)) {
+ dev_del(d);
+ return NULL;
+ }
+ return d;
}
/*
* Create a loopback synchronous device
*/
-void
-dev_init_loop(struct aparams *dipar, struct aparams *dopar, unsigned bufsz)
+struct dev *
+dev_new_loop(struct aparams *dipar, struct aparams *dopar, unsigned bufsz)
{
struct aparams par;
unsigned cmin, cmax, rate;
+ struct dev *d;
+ d = malloc(sizeof(struct dev));
+ if (d == NULL) {
+ perror("malloc");
+ exit(1);
+ }
cmin = (dipar->cmin < dopar->cmin) ? dipar->cmin : dopar->cmin;
cmax = (dipar->cmax > dopar->cmax) ? dipar->cmax : dopar->cmax;
rate = (dipar->rate > dopar->rate) ? dipar->rate : dopar->rate;
aparams_init(&par, cmin, cmax, rate);
- dev_reqipar = par;
- dev_reqopar = par;
- dev_rate = rate;
- dev_reqround = (bufsz + 1) / 2;
- dev_reqbufsz = dev_reqround * 2;
- dev_reqmode = MODE_PLAY | MODE_REC | MODE_LOOP;
- dev_pstate = DEV_CLOSED;
+ d->reqipar = par;
+ d->reqopar = par;
+ d->rate = rate;
+ d->reqround = (bufsz + 1) / 2;
+ d->reqbufsz = d->reqround * 2;
+ d->reqmode = MODE_PLAY | MODE_REC | MODE_LOOP;
+ d->pstate = DEV_CLOSED;
+ d->hold = 0;
+ d->prime = 0;
+ d->next = dev_list;
+ dev_list = d;
+ return d;
}
/*
* Create a MIDI thru box device
*/
-void
-dev_init_thru(void)
+struct dev *
+dev_new_thru(void)
{
- dev_reqmode = 0;
- dev_pstate = DEV_CLOSED;
+ struct dev *d;
+
+ d = malloc(sizeof(struct dev));
+ if (d == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ d->reqmode = 0;
+ d->pstate = DEV_CLOSED;
+ d->hold = 0;
+ d->prime = 0;
+ d->next = dev_list;
+ dev_list = d;
+ return d;
}
/*
@@ -190,7 +204,7 @@ dev_init_thru(void)
* monitor, midi control, and any necessary conversions.
*/
int
-dev_open(void)
+dev_open(struct dev *d)
{
struct file *f;
struct aparams par;
@@ -198,73 +212,73 @@ dev_open(void)
struct abuf *buf;
unsigned siomode;
- dev_mode = dev_reqmode;
- dev_round = dev_reqround;
- dev_bufsz = dev_reqbufsz;
- dev_ipar = dev_reqipar;
- dev_opar = dev_reqopar;
- dev_rec = NULL;
- dev_play = NULL;
- dev_mon = NULL;
- dev_submon = NULL;
- dev_rate = 0;
+ d->mode = d->reqmode;
+ d->round = d->reqround;
+ d->bufsz = d->reqbufsz;
+ d->ipar = d->reqipar;
+ d->opar = d->reqopar;
+ d->rec = NULL;
+ d->play = NULL;
+ d->mon = NULL;
+ d->submon = NULL;
+ d->rate = 0;
/*
* If needed, open the device (ie create dev_rec and dev_play)
*/
- if ((dev_mode & (MODE_PLAY | MODE_REC)) && !(dev_mode & MODE_LOOP)) {
- siomode = dev_mode & (MODE_PLAY | MODE_REC);
+ if ((d->mode & (MODE_PLAY | MODE_REC)) && !(d->mode & MODE_LOOP)) {
+ siomode = d->mode & (MODE_PLAY | MODE_REC);
f = (struct file *)siofile_new(&siofile_ops,
- dev_path,
+ d->path,
&siomode,
- &dev_ipar,
- &dev_opar,
- &dev_bufsz,
- &dev_round);
+ &d->ipar,
+ &d->opar,
+ &d->bufsz,
+ &d->round);
if (f == NULL) {
#ifdef DEBUG
if (debug_level >= 1) {
- dbg_puts(dev_path ? dev_path : "default");
+ dbg_puts(d->path ? d->path : "default");
dbg_puts(": failed to open audio device\n");
}
#endif
return 0;
}
if (!(siomode & MODE_PLAY))
- dev_mode &= ~(MODE_PLAY | MODE_MON);
+ d->mode &= ~(MODE_PLAY | MODE_MON);
if (!(siomode & MODE_REC))
- dev_mode &= ~MODE_REC;
- if ((dev_mode & (MODE_PLAY | MODE_REC)) == 0) {
+ d->mode &= ~MODE_REC;
+ if ((d->mode & (MODE_PLAY | MODE_REC)) == 0) {
#ifdef DEBUG
if (debug_level >= 1) {
- dbg_puts(dev_path ? dev_path : "default");
+ dbg_puts(d->path ? d->path : "default");
dbg_puts(": mode not supported by device\n");
}
#endif
return 0;
}
- dev_rate = dev_mode & MODE_REC ? dev_ipar.rate : dev_opar.rate;
+ d->rate = d->mode & MODE_REC ? d->ipar.rate : d->opar.rate;
#ifdef DEBUG
if (debug_level >= 2) {
- if (dev_mode & MODE_REC) {
+ if (d->mode & MODE_REC) {
dbg_puts("hw recording ");
- aparams_dbg(&dev_ipar);
+ aparams_dbg(&d->ipar);
dbg_puts("\n");
}
- if (dev_mode & MODE_PLAY) {
+ if (d->mode & MODE_PLAY) {
dbg_puts("hw playing ");
- aparams_dbg(&dev_opar);
+ aparams_dbg(&d->opar);
dbg_puts("\n");
}
}
#endif
- if (dev_mode & MODE_REC) {
- dev_rec = rsio_new(f);
- dev_rec->refs++;
+ if (d->mode & MODE_REC) {
+ d->rec = rsio_new(f);
+ d->rec->refs++;
}
- if (dev_mode & MODE_PLAY) {
- dev_play = wsio_new(f);
- dev_play->refs++;
+ if (d->mode & MODE_PLAY) {
+ d->play = wsio_new(f);
+ d->play->refs++;
}
}
@@ -272,113 +286,113 @@ dev_open(void)
* Create the midi control end, or a simple thru box
* if there's no device
*/
- dev_midi = (dev_mode == 0) ? thru_new("thru") : ctl_new("ctl");
- dev_midi->refs++;
+ d->midi = (d->mode == 0) ? thru_new("thru") : ctl_new("ctl", d);
+ d->midi->refs++;
/*
* Create mixer, demuxer and monitor
*/
- if (dev_mode & MODE_PLAY) {
- dev_mix = mix_new("play", dev_bufsz, dev_round);
- dev_mix->refs++;
- dev_mix->u.mix.ctl = dev_midi;
+ if (d->mode & MODE_PLAY) {
+ d->mix = mix_new("play", d->bufsz, d->round);
+ d->mix->refs++;
+ d->mix->u.mix.ctl = d->midi;
}
- if (dev_mode & MODE_REC) {
- dev_sub = sub_new("rec", dev_bufsz, dev_round);
- dev_sub->refs++;
+ if (d->mode & MODE_REC) {
+ d->sub = sub_new("rec", d->bufsz, d->round);
+ d->sub->refs++;
/*
* If not playing, use the record end as clock source
*/
- if (!(dev_mode & MODE_PLAY))
- dev_sub->u.sub.ctl = dev_midi;
+ if (!(d->mode & MODE_PLAY))
+ d->sub->u.sub.ctl = d->midi;
}
- if (dev_mode & MODE_LOOP) {
+ if (d->mode & MODE_LOOP) {
/*
* connect mixer out to demuxer in
*/
- buf = abuf_new(dev_bufsz, &dev_opar);
- aproc_setout(dev_mix, buf);
- aproc_setin(dev_sub, buf);
+ buf = abuf_new(d->bufsz, &d->opar);
+ aproc_setout(d->mix, buf);
+ aproc_setin(d->sub, buf);
- dev_mix->flags |= APROC_QUIT;
- dev_sub->flags |= APROC_QUIT;
- dev_rate = dev_opar.rate;
+ d->mix->flags |= APROC_QUIT;
+ d->sub->flags |= APROC_QUIT;
+ d->rate = d->opar.rate;
}
- if (dev_rec) {
- aparams_init(&par, dev_ipar.cmin, dev_ipar.cmax, dev_rate);
+ if (d->rec) {
+ aparams_init(&par, d->ipar.cmin, d->ipar.cmax, d->rate);
/*
* Create device <-> demuxer buffer
*/
- buf = abuf_new(dev_bufsz, &dev_ipar);
- aproc_setout(dev_rec, buf);
+ buf = abuf_new(d->bufsz, &d->ipar);
+ aproc_setout(d->rec, buf);
/*
* Insert a converter, if needed.
*/
- if (!aparams_eqenc(&dev_ipar, &par)) {
- conv = dec_new("rec", &dev_ipar);
+ if (!aparams_eqenc(&d->ipar, &par)) {
+ conv = dec_new("rec", &d->ipar);
aproc_setin(conv, buf);
- buf = abuf_new(dev_round, &par);
+ buf = abuf_new(d->round, &par);
aproc_setout(conv, buf);
}
- dev_ipar = par;
- aproc_setin(dev_sub, buf);
+ d->ipar = par;
+ aproc_setin(d->sub, buf);
}
- if (dev_play) {
- aparams_init(&par, dev_opar.cmin, dev_opar.cmax, dev_rate);
+ if (d->play) {
+ aparams_init(&par, d->opar.cmin, d->opar.cmax, d->rate);
/*
* Create device <-> mixer buffer
*/
- buf = abuf_new(dev_bufsz, &dev_opar);
- aproc_setin(dev_play, buf);
+ buf = abuf_new(d->bufsz, &d->opar);
+ aproc_setin(d->play, buf);
/*
* Append a converter, if needed.
*/
- if (!aparams_eqenc(&par, &dev_opar)) {
- conv = enc_new("play", &dev_opar);
+ if (!aparams_eqenc(&par, &d->opar)) {
+ conv = enc_new("play", &d->opar);
aproc_setout(conv, buf);
- buf = abuf_new(dev_round, &par);
+ buf = abuf_new(d->round, &par);
aproc_setin(conv, buf);
}
- dev_opar = par;
- aproc_setout(dev_mix, buf);
+ d->opar = par;
+ aproc_setout(d->mix, buf);
}
- if (dev_mode & MODE_MON) {
- dev_mon = mon_new("mon", dev_bufsz);
- dev_mon->refs++;
- buf = abuf_new(dev_bufsz, &dev_opar);
- aproc_setout(dev_mon, buf);
+ if (d->mode & MODE_MON) {
+ d->mon = mon_new("mon", d->bufsz);
+ d->mon->refs++;
+ buf = abuf_new(d->bufsz, &d->opar);
+ aproc_setout(d->mon, buf);
/*
* Append a "sub" to which clients will connect.
*/
- dev_submon = sub_new("mon", dev_bufsz, dev_round);
- dev_submon->refs++;
- aproc_setin(dev_submon, buf);
+ d->submon = sub_new("mon", d->bufsz, d->round);
+ d->submon->refs++;
+ aproc_setin(d->submon, buf);
/*
* Attach to the mixer
*/
- dev_mix->u.mix.mon = dev_mon;
- dev_mon->refs++;
+ d->mix->u.mix.mon = d->mon;
+ d->mon->refs++;
}
#ifdef DEBUG
if (debug_level >= 2) {
- if (dev_mode & (MODE_PLAY | MODE_RECMASK)) {
+ if (d->mode & (MODE_PLAY | MODE_RECMASK)) {
dbg_puts("device block size is ");
- dbg_putu(dev_round);
+ dbg_putu(d->round);
dbg_puts(" frames, using ");
- dbg_putu(dev_bufsz / dev_round);
+ dbg_putu(d->bufsz / d->round);
dbg_puts(" blocks\n");
}
}
#endif
- dev_pstate = DEV_INIT;
- if (dev_reqprime)
- dev_prime();
+ d->pstate = DEV_INIT;
+ if (d->prime)
+ dev_prime(d);
return 1;
}
@@ -387,7 +401,7 @@ dev_open(void)
* once both play chain and record chain are gone.
*/
void
-dev_close(void)
+dev_close(struct dev *d)
{
struct file *f;
@@ -395,20 +409,20 @@ dev_close(void)
* if the device is starting, ensure it actually starts
* so buffers are drained, else clear any buffers
*/
- switch (dev_pstate) {
+ switch (d->pstate) {
case DEV_START:
#ifdef DEBUG
if (debug_level >= 3)
dbg_puts("draining device\n");
#endif
- dev_start();
+ dev_start(d);
break;
case DEV_INIT:
#ifdef DEBUG
if (debug_level >= 3)
dbg_puts("flushing device\n");
#endif
- dev_clear();
+ dev_clear(d);
break;
}
#ifdef DEBUG
@@ -416,7 +430,7 @@ dev_close(void)
dbg_puts("closing device\n");
#endif
- if (dev_mix) {
+ if (d->mix) {
/*
* Put the mixer in ``autoquit'' state and generate
* EOF on all inputs connected it. Once buffers are
@@ -427,26 +441,26 @@ dev_close(void)
* reorder the file_list, we have to restart the loop
* after each call to file_eof().
*/
- if (APROC_OK(dev_mix))
- mix_quit(dev_mix);
+ if (APROC_OK(d->mix))
+ mix_quit(d->mix);
/*
* XXX: handle this in mix_done()
*/
- if (APROC_OK(dev_mix->u.mix.mon)) {
- dev_mix->u.mix.mon->refs--;
- aproc_del(dev_mix->u.mix.mon);
- dev_mix->u.mix.mon = NULL;
+ if (APROC_OK(d->mix->u.mix.mon)) {
+ d->mix->u.mix.mon->refs--;
+ aproc_del(d->mix->u.mix.mon);
+ d->mix->u.mix.mon = NULL;
}
restart_mix:
LIST_FOREACH(f, &file_list, entry) {
if (f->rproc != NULL &&
- aproc_depend(dev_mix, f->rproc)) {
+ aproc_depend(d->mix, f->rproc)) {
file_eof(f);
goto restart_mix;
}
}
- } else if (dev_sub || dev_submon) {
+ } else if (d->sub || d->submon) {
/*
* Same as above, but since there's no mixer,
* we generate EOF on the record-end of the
@@ -455,85 +469,97 @@ dev_close(void)
restart_sub:
LIST_FOREACH(f, &file_list, entry) {
if (f->rproc != NULL &&
- (aproc_depend(dev_sub, f->rproc) ||
- aproc_depend(dev_submon, f->rproc))) {
+ (aproc_depend(d->sub, f->rproc) ||
+ aproc_depend(d->submon, f->rproc))) {
file_eof(f);
goto restart_sub;
}
}
}
- if (dev_midi) {
- dev_midi->flags |= APROC_QUIT;
- if (LIST_EMPTY(&dev_midi->ins))
- aproc_del(dev_midi);
+ if (d->midi) {
+ d->midi->flags |= APROC_QUIT;
+ if (LIST_EMPTY(&d->midi->ins))
+ aproc_del(d->midi);
restart_midi:
LIST_FOREACH(f, &file_list, entry) {
if (f->rproc &&
- aproc_depend(dev_midi, f->rproc)) {
+ aproc_depend(d->midi, f->rproc)) {
file_eof(f);
goto restart_midi;
}
}
}
- if (dev_mix) {
- if (--dev_mix->refs == 0 && (dev_mix->flags & APROC_ZOMB))
- aproc_del(dev_mix);
- dev_mix = NULL;
+ if (d->mix) {
+ if (--d->mix->refs == 0 && (d->mix->flags & APROC_ZOMB))
+ aproc_del(d->mix);
+ d->mix = NULL;
}
- if (dev_play) {
- if (--dev_play->refs == 0 && (dev_play->flags & APROC_ZOMB))
- aproc_del(dev_play);
- dev_play = NULL;
+ if (d->play) {
+ if (--d->play->refs == 0 && (d->play->flags & APROC_ZOMB))
+ aproc_del(d->play);
+ d->play = NULL;
}
- if (dev_sub) {
- if (--dev_sub->refs == 0 && (dev_sub->flags & APROC_ZOMB))
- aproc_del(dev_sub);
- dev_sub = NULL;
+ if (d->sub) {
+ if (--d->sub->refs == 0 && (d->sub->flags & APROC_ZOMB))
+ aproc_del(d->sub);
+ d->sub = NULL;
}
- if (dev_rec) {
- if (--dev_rec->refs == 0 && (dev_rec->flags & APROC_ZOMB))
- aproc_del(dev_rec);
- dev_rec = NULL;
+ if (d->rec) {
+ if (--d->rec->refs == 0 && (d->rec->flags & APROC_ZOMB))
+ aproc_del(d->rec);
+ d->rec = NULL;
}
- if (dev_submon) {
- if (--dev_submon->refs == 0 && (dev_submon->flags & APROC_ZOMB))
- aproc_del(dev_submon);
- dev_submon = NULL;
+ if (d->submon) {
+ if (--d->submon->refs == 0 && (d->submon->flags & APROC_ZOMB))
+ aproc_del(d->submon);
+ d->submon = NULL;
}
- if (dev_mon) {
- if (--dev_mon->refs == 0 && (dev_mon->flags & APROC_ZOMB))
- aproc_del(dev_mon);
- dev_mon = NULL;
+ if (d->mon) {
+ if (--d->mon->refs == 0 && (d->mon->flags & APROC_ZOMB))
+ aproc_del(d->mon);
+ d->mon = NULL;
}
- if (dev_midi) {
- if (--dev_midi->refs == 0 && (dev_midi->flags & APROC_ZOMB))
- aproc_del(dev_midi);
- dev_midi = NULL;
+ if (d->midi) {
+ if (--d->midi->refs == 0 && (d->midi->flags & APROC_ZOMB))
+ aproc_del(d->midi);
+ d->midi = NULL;
}
- dev_pstate = DEV_CLOSED;
+ d->pstate = DEV_CLOSED;
}
/*
* Free the device
*/
void
-dev_done(void)
+dev_del(struct dev *d)
{
- if (dev_pstate != DEV_CLOSED)
- dev_close();
+ struct dev **p;
+
+ if (d->pstate != DEV_CLOSED)
+ dev_close(d);
+ for (p = &dev_list; *p != d; p = &(*p)->next) {
+#ifdef DEBUG
+ if (*p == NULL) {
+ dbg_puts("device to delete not on the list\n");
+ dbg_panic();
+ }
+#endif
+ }
+ *p = d->next;
+ free(d);
}
/*
* Open a MIDI device and connect it to the thru box
*/
int
-dev_thruadd(char *name, int in, int out)
+dev_thruadd(struct dev *d, char *name, int in, int out)
{
struct file *f;
struct abuf *rbuf = NULL, *wbuf = NULL;
struct aproc *rproc, *wproc;
- if (!dev_ref())
+ if (!dev_ref(d))
return 0;
f = (struct file *)miofile_new(&miofile_ops, name, in, out);
if (f == NULL)
@@ -548,7 +574,7 @@ dev_thruadd(char *name, int in, int out)
wbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
aproc_setin(wproc, wbuf);
}
- dev_midiattach(rbuf, wbuf);
+ dev_midiattach(d, rbuf, wbuf);
return 1;
}
@@ -556,12 +582,12 @@ dev_thruadd(char *name, int in, int out)
* Attach a bi-directional MIDI stream to the MIDI device
*/
void
-dev_midiattach(struct abuf *ibuf, struct abuf *obuf)
+dev_midiattach(struct dev *d, struct abuf *ibuf, struct abuf *obuf)
{
if (ibuf)
- aproc_setin(dev_midi, ibuf);
+ aproc_setin(d->midi, ibuf);
if (obuf) {
- aproc_setout(dev_midi, obuf);
+ aproc_setout(d->midi, obuf);
if (ibuf) {
ibuf->duplex = obuf;
obuf->duplex = ibuf;
@@ -570,16 +596,16 @@ dev_midiattach(struct abuf *ibuf, struct abuf *obuf)
}
unsigned
-dev_roundof(unsigned newrate)
+dev_roundof(struct dev *d, unsigned newrate)
{
- return (dev_round * newrate + dev_rate / 2) / dev_rate;
+ return (d->round * newrate + d->rate / 2) / d->rate;
}
/*
* Start the (paused) device. By default it's paused.
*/
void
-dev_start(void)
+dev_start(struct dev *d)
{
struct file *f;
@@ -587,20 +613,20 @@ dev_start(void)
if (debug_level >= 2)
dbg_puts("starting device\n");
#endif
- dev_pstate = DEV_RUN;
- if (dev_mode & MODE_LOOP)
+ d->pstate = DEV_RUN;
+ if (d->mode & MODE_LOOP)
return;
- if (APROC_OK(dev_mix))
- dev_mix->flags |= APROC_DROP;
- if (APROC_OK(dev_sub))
- dev_sub->flags |= APROC_DROP;
- if (APROC_OK(dev_submon))
- dev_submon->flags |= APROC_DROP;
- if (APROC_OK(dev_play) && dev_play->u.io.file) {
- f = dev_play->u.io.file;
+ if (APROC_OK(d->mix))
+ d->mix->flags |= APROC_DROP;
+ if (APROC_OK(d->sub))
+ d->sub->flags |= APROC_DROP;
+ if (APROC_OK(d->submon))
+ d->submon->flags |= APROC_DROP;
+ if (APROC_OK(d->play) && d->play->u.io.file) {
+ f = d->play->u.io.file;
f->ops->start(f);
- } else if (APROC_OK(dev_rec) && dev_rec->u.io.file) {
- f = dev_rec->u.io.file;
+ } else if (APROC_OK(d->rec) && d->rec->u.io.file) {
+ f = d->rec->u.io.file;
f->ops->start(f);
}
}
@@ -610,55 +636,58 @@ dev_start(void)
* so it shouldn't be called from aproc methods
*/
void
-dev_stop(void)
+dev_stop(struct dev *d)
{
struct file *f;
#ifdef DEBUG
if (debug_level >= 2)
- dbg_puts("stopping stopped\n");
+ dbg_puts("device stopped\n");
#endif
- dev_pstate = DEV_INIT;
- if (dev_mode & MODE_LOOP)
+ d->pstate = DEV_INIT;
+ if (d->mode & MODE_LOOP)
return;
- if (APROC_OK(dev_play) && dev_play->u.io.file) {
- f = dev_play->u.io.file;
+ if (APROC_OK(d->play) && d->play->u.io.file) {
+ f = d->play->u.io.file;
f->ops->stop(f);
- } else if (APROC_OK(dev_rec) && dev_rec->u.io.file) {
- f = dev_rec->u.io.file;
+ } else if (APROC_OK(d->rec) && d->rec->u.io.file) {
+ f = d->rec->u.io.file;
f->ops->stop(f);
}
- if (APROC_OK(dev_mix))
- dev_mix->flags &= ~APROC_DROP;
- if (APROC_OK(dev_sub))
- dev_sub->flags &= ~APROC_DROP;
- if (APROC_OK(dev_submon))
- dev_submon->flags &= ~APROC_DROP;
+ if (APROC_OK(d->mix))
+ d->mix->flags &= ~APROC_DROP;
+ if (APROC_OK(d->sub))
+ d->sub->flags &= ~APROC_DROP;
+ if (APROC_OK(d->submon))
+ d->submon->flags &= ~APROC_DROP;
}
int
-dev_ref(void)
+dev_ref(struct dev *d)
{
#ifdef DEBUG
if (debug_level >= 3)
dbg_puts("device requested\n");
#endif
- if (dev_pstate == DEV_CLOSED && !dev_open())
+ if (d->pstate == DEV_CLOSED && !dev_open(d)) {
+ if (d->hold)
+ dev_del(d);
return 0;
- dev_refcnt++;
+ }
+ d->refcnt++;
return 1;
}
void
-dev_unref(void)
+dev_unref(struct dev *d)
{
#ifdef DEBUG
if (debug_level >= 3)
dbg_puts("device released\n");
#endif
- dev_refcnt--;
- if (dev_refcnt == 0 && dev_pstate == DEV_INIT)
- dev_close();
+ d->refcnt--;
+ if (d->refcnt == 0 && d->pstate == DEV_INIT && !d->hold)
+ dev_close(d);
}
/*
@@ -672,53 +701,57 @@ dev_unref(void)
* on fatal error
*/
int
-dev_run(void)
+dev_run(struct dev *d)
{
- if (dev_pstate == DEV_CLOSED)
+ if (d->pstate == DEV_CLOSED)
return 1;
/*
* check if device isn't gone
*/
- if (((dev_mode & MODE_PLAY) && !APROC_OK(dev_mix)) ||
- ((dev_mode & MODE_REC) && !APROC_OK(dev_sub)) ||
- ((dev_mode & MODE_MON) && !APROC_OK(dev_submon))) {
+ if (((d->mode & MODE_PLAY) && !APROC_OK(d->mix)) ||
+ ((d->mode & MODE_REC) && !APROC_OK(d->sub)) ||
+ ((d->mode & MODE_MON) && !APROC_OK(d->submon))) {
#ifdef DEBUG
if (debug_level >= 1)
dbg_puts("device disappeared\n");
#endif
- dev_close();
- return 0;
+ if (d->hold) {
+ dev_del(d);
+ return 0;
+ }
+ dev_close(d);
+ return 1;
}
- switch (dev_pstate) {
+ switch (d->pstate) {
case DEV_INIT:
/* nothing */
break;
case DEV_START:
- dev_start();
+ dev_start(d);
/* PASSTHROUGH */
case DEV_RUN:
/*
* if the device is not used, then stop it
*/
- if ((!APROC_OK(dev_mix) ||
- dev_mix->u.mix.idle > 2 * dev_bufsz) &&
- (!APROC_OK(dev_sub) ||
- dev_sub->u.sub.idle > 2 * dev_bufsz) &&
- (!APROC_OK(dev_submon) ||
- dev_submon->u.sub.idle > 2 * dev_bufsz) &&
- (!APROC_OK(dev_midi) ||
- dev_midi->u.ctl.tstate != CTL_RUN)) {
+ if ((!APROC_OK(d->mix) ||
+ d->mix->u.mix.idle > 2 * d->bufsz) &&
+ (!APROC_OK(d->sub) ||
+ d->sub->u.sub.idle > 2 * d->bufsz) &&
+ (!APROC_OK(d->submon) ||
+ d->submon->u.sub.idle > 2 * d->bufsz) &&
+ (!APROC_OK(d->midi) ||
+ d->midi->u.ctl.tstate != CTL_RUN)) {
#ifdef DEBUG
if (debug_level >= 3)
dbg_puts("device idle, suspending\n");
#endif
- dev_stop();
- if (dev_refcnt == 0)
- dev_close();
+ dev_stop(d);
+ if (d->refcnt == 0 && !d->hold)
+ dev_close(d);
else {
- dev_clear();
- if (dev_reqprime)
- dev_prime();
+ dev_clear(d);
+ if (d->prime)
+ dev_prime(d);
}
}
break;
@@ -734,22 +767,23 @@ dev_run(void)
* This routine can be called from aproc context.
*/
void
-dev_wakeup(void)
+dev_wakeup(struct dev *d)
{
- if (dev_pstate == DEV_INIT)
- dev_pstate = DEV_START;
+ if (d->pstate == DEV_INIT)
+ d->pstate = DEV_START;
}
/*
* Find the end points connected to the mix/sub.
*/
int
-dev_getep(unsigned mode, struct abuf **sibuf, struct abuf **sobuf)
+dev_getep(struct dev *d,
+ unsigned mode, struct abuf **sibuf, struct abuf **sobuf)
{
struct abuf *ibuf, *obuf;
if (mode & MODE_PLAY) {
- if (!APROC_OK(dev_mix))
+ if (!APROC_OK(d->mix))
return 0;
ibuf = *sibuf;
for (;;) {
@@ -762,14 +796,14 @@ dev_getep(unsigned mode, struct abuf **sibuf, struct abuf **sobuf)
#endif
return 0;
}
- if (ibuf->rproc == dev_mix)
+ if (ibuf->rproc == d->mix)
break;
ibuf = LIST_FIRST(&ibuf->rproc->outs);
}
*sibuf = ibuf;
}
if (mode & MODE_REC) {
- if (!APROC_OK(dev_sub))
+ if (!APROC_OK(d->sub))
return 0;
obuf = *sobuf;
for (;;) {
@@ -782,14 +816,14 @@ dev_getep(unsigned mode, struct abuf **sibuf, struct abuf **sobuf)
#endif
return 0;
}
- if (obuf->wproc == dev_sub)
+ if (obuf->wproc == d->sub)
break;
obuf = LIST_FIRST(&obuf->wproc->ins);
}
*sobuf = obuf;
}
if (mode & MODE_MON) {
- if (!APROC_OK(dev_submon))
+ if (!APROC_OK(d->submon))
return 0;
obuf = *sobuf;
for (;;) {
@@ -802,7 +836,7 @@ dev_getep(unsigned mode, struct abuf **sibuf, struct abuf **sobuf)
#endif
return 0;
}
- if (obuf->wproc == dev_submon)
+ if (obuf->wproc == d->submon)
break;
obuf = LIST_FIRST(&obuf->wproc->ins);
}
@@ -816,12 +850,12 @@ dev_getep(unsigned mode, struct abuf **sibuf, struct abuf **sobuf)
* them underruns/overruns).
*/
void
-dev_sync(unsigned mode, struct abuf *ibuf, struct abuf *obuf)
+dev_sync(struct dev *d, unsigned mode, struct abuf *ibuf, struct abuf *obuf)
{
int delta, offs;
- struct abuf *mbuf;
+ struct abuf *mbuf = NULL;
- if (!dev_getep(mode, &ibuf, &obuf))
+ if (!dev_getep(d, mode, &ibuf, &obuf))
return;
/*
* Calculate delta, the number of frames the play chain is ahead
@@ -830,29 +864,29 @@ dev_sync(unsigned mode, struct abuf *ibuf, struct abuf *obuf)
*/
offs = 0;
delta = 0;
- if (APROC_OK(dev_mix)) {
- mbuf = LIST_FIRST(&dev_mix->outs);
+ if (APROC_OK(d->mix)) {
+ mbuf = LIST_FIRST(&d->mix->outs);
offs += mbuf->w.mix.todo;
- delta += dev_mix->u.mix.lat;
+ delta += d->mix->u.mix.lat;
}
- if (APROC_OK(dev_sub))
- delta += dev_sub->u.sub.lat;
+ if (APROC_OK(d->sub))
+ delta += d->sub->u.sub.lat;
#ifdef DEBUG
if (debug_level >= 3) {
dbg_puts("syncing device");
- if (APROC_OK(dev_mix)) {
+ if (APROC_OK(d->mix)) {
dbg_puts(", ");
- aproc_dbg(dev_mix);
+ aproc_dbg(d->mix);
dbg_puts(": todo = ");
dbg_putu(mbuf->w.mix.todo);
dbg_puts(": lat = ");
- dbg_putu(dev_mix->u.mix.lat);
+ dbg_putu(d->mix->u.mix.lat);
}
- if (APROC_OK(dev_sub)) {
+ if (APROC_OK(d->sub)) {
dbg_puts(", ");
- aproc_dbg(dev_sub);
+ aproc_dbg(d->sub);
dbg_puts(": lat = ");
- dbg_putu(dev_sub->u.sub.lat);
+ dbg_putu(d->sub->u.sub.lat);
}
dbg_puts("\n");
}
@@ -868,13 +902,13 @@ dev_sync(unsigned mode, struct abuf *ibuf, struct abuf *obuf)
* a stream would have if dev_attach() is called on it.
*/
int
-dev_getpos(void)
+dev_getpos(struct dev *d)
{
struct abuf *mbuf = NULL;
- if (APROC_OK(dev_mix)) {
- mbuf = LIST_FIRST(&dev_mix->outs);
- return -(mbuf->w.mix.todo + dev_mix->u.mix.lat);
+ if (APROC_OK(d->mix)) {
+ mbuf = LIST_FIRST(&d->mix->outs);
+ return -(mbuf->w.mix.todo + d->mix->u.mix.lat);
} else
return 0;
}
@@ -886,7 +920,7 @@ dev_getpos(void)
* and rec.
*/
void
-dev_attach(char *name, unsigned mode,
+dev_attach(struct dev *d, char *name, unsigned mode,
struct abuf *ibuf, struct aparams *sipar, unsigned inch,
struct abuf *obuf, struct aparams *sopar, unsigned onch,
unsigned xrun, int vol)
@@ -897,26 +931,26 @@ dev_attach(char *name, unsigned mode,
unsigned round, nblk, nch;
#ifdef DEBUG
- if ((!APROC_OK(dev_mix) && (mode & MODE_PLAY)) ||
- (!APROC_OK(dev_sub) && (mode & MODE_REC)) ||
- (!APROC_OK(dev_submon) && (mode & MODE_MON))) {
+ if ((!APROC_OK(d->mix) && (mode & MODE_PLAY)) ||
+ (!APROC_OK(d->sub) && (mode & MODE_REC)) ||
+ (!APROC_OK(d->submon) && (mode & MODE_MON))) {
dbg_puts("mode beyond device mode, not attaching\n");
return;
}
#endif
if (mode & MODE_PLAY) {
ipar = *sipar;
- pbuf = LIST_FIRST(&dev_mix->outs);
- nblk = (dev_bufsz / dev_round + 3) / 4;
- round = dev_roundof(ipar.rate);
+ pbuf = LIST_FIRST(&d->mix->outs);
+ nblk = (d->bufsz / d->round + 3) / 4;
+ round = dev_roundof(d, ipar.rate);
nch = ipar.cmax - ipar.cmin + 1;
- if (!aparams_eqenc(&ipar, &dev_opar)) {
+ if (!aparams_eqenc(&ipar, &d->opar)) {
conv = dec_new(name, &ipar);
- ipar.bps = dev_opar.bps;
- ipar.bits = dev_opar.bits;
- ipar.sig = dev_opar.sig;
- ipar.le = dev_opar.le;
- ipar.msb = dev_opar.msb;
+ ipar.bps = d->opar.bps;
+ ipar.bits = d->opar.bits;
+ ipar.sig = d->opar.sig;
+ ipar.le = d->opar.le;
+ ipar.msb = d->opar.msb;
aproc_setin(conv, ibuf);
ibuf = abuf_new(nblk * round, &ipar);
aproc_setout(conv, ibuf);
@@ -928,10 +962,10 @@ dev_attach(char *name, unsigned mode,
ibuf = abuf_new(nblk * round, &ipar);
aproc_setout(conv, ibuf);
}
- if (!aparams_eqrate(&ipar, &dev_opar)) {
- conv = resamp_new(name, round, dev_round);
- ipar.rate = dev_opar.rate;
- round = dev_round;
+ if (!aparams_eqrate(&ipar, &d->opar)) {
+ conv = resamp_new(name, round, d->round);
+ ipar.rate = d->opar.rate;
+ round = d->round;
aproc_setin(conv, ibuf);
ibuf = abuf_new(nblk * round, &ipar);
aproc_setout(conv, ibuf);
@@ -943,24 +977,24 @@ dev_attach(char *name, unsigned mode,
ibuf = abuf_new(nblk * round, &ipar);
aproc_setout(conv, ibuf);
}
- aproc_setin(dev_mix, ibuf);
+ aproc_setin(d->mix, ibuf);
ibuf->r.mix.xrun = xrun;
ibuf->r.mix.maxweight = vol;
- mix_setmaster(dev_mix);
+ mix_setmaster(d->mix);
}
if (mode & MODE_REC) {
opar = *sopar;
- rbuf = LIST_FIRST(&dev_sub->ins);
- round = dev_roundof(opar.rate);
- nblk = (dev_bufsz / dev_round + 3) / 4;
+ rbuf = LIST_FIRST(&d->sub->ins);
+ round = dev_roundof(d, opar.rate);
+ nblk = (d->bufsz / d->round + 3) / 4;
nch = opar.cmax - opar.cmin + 1;
- if (!aparams_eqenc(&opar, &dev_ipar)) {
+ if (!aparams_eqenc(&opar, &d->ipar)) {
conv = enc_new(name, &opar);
- opar.bps = dev_ipar.bps;
- opar.bits = dev_ipar.bits;
- opar.sig = dev_ipar.sig;
- opar.le = dev_ipar.le;
- opar.msb = dev_ipar.msb;
+ opar.bps = d->ipar.bps;
+ opar.bits = d->ipar.bits;
+ opar.sig = d->ipar.sig;
+ opar.le = d->ipar.le;
+ opar.msb = d->ipar.msb;
aproc_setout(conv, obuf);
obuf = abuf_new(nblk * round, &opar);
aproc_setin(conv, obuf);
@@ -972,10 +1006,10 @@ dev_attach(char *name, unsigned mode,
obuf = abuf_new(nblk * round, &opar);
aproc_setin(conv, obuf);
}
- if (!aparams_eqrate(&opar, &dev_ipar)) {
- conv = resamp_new(name, dev_round, round);
- opar.rate = dev_ipar.rate;
- round = dev_round;
+ if (!aparams_eqrate(&opar, &d->ipar)) {
+ conv = resamp_new(name, d->round, round);
+ opar.rate = d->ipar.rate;
+ round = d->round;
aproc_setout(conv, obuf);
obuf = abuf_new(nblk * round, &opar);
aproc_setin(conv, obuf);
@@ -987,22 +1021,22 @@ dev_attach(char *name, unsigned mode,
obuf = abuf_new(nblk * round, &opar);
aproc_setin(conv, obuf);
}
- aproc_setout(dev_sub, obuf);
+ aproc_setout(d->sub, obuf);
obuf->w.sub.xrun = xrun;
}
if (mode & MODE_MON) {
opar = *sopar;
- rbuf = LIST_FIRST(&dev_submon->ins);
- round = dev_roundof(opar.rate);
- nblk = (dev_bufsz / dev_round + 3) / 4;
+ rbuf = LIST_FIRST(&d->submon->ins);
+ round = dev_roundof(d, opar.rate);
+ nblk = (d->bufsz / d->round + 3) / 4;
nch = opar.cmax - opar.cmin + 1;
- if (!aparams_eqenc(&opar, &dev_opar)) {
+ if (!aparams_eqenc(&opar, &d->opar)) {
conv = enc_new(name, &opar);
- opar.bps = dev_opar.bps;
- opar.bits = dev_opar.bits;
- opar.sig = dev_opar.sig;
- opar.le = dev_opar.le;
- opar.msb = dev_opar.msb;
+ opar.bps = d->opar.bps;
+ opar.bits = d->opar.bits;
+ opar.sig = d->opar.sig;
+ opar.le = d->opar.le;
+ opar.msb = d->opar.msb;
aproc_setout(conv, obuf);
obuf = abuf_new(nblk * round, &opar);
aproc_setin(conv, obuf);
@@ -1014,10 +1048,10 @@ dev_attach(char *name, unsigned mode,
obuf = abuf_new(nblk * round, &opar);
aproc_setin(conv, obuf);
}
- if (!aparams_eqrate(&opar, &dev_opar)) {
- conv = resamp_new(name, dev_round, round);
- opar.rate = dev_opar.rate;
- round = dev_round;
+ if (!aparams_eqrate(&opar, &d->opar)) {
+ conv = resamp_new(name, d->round, round);
+ opar.rate = d->opar.rate;
+ round = d->round;
aproc_setout(conv, obuf);
obuf = abuf_new(nblk * round, &opar);
aproc_setin(conv, obuf);
@@ -1029,7 +1063,7 @@ dev_attach(char *name, unsigned mode,
obuf = abuf_new(nblk * round, &opar);
aproc_setin(conv, obuf);
}
- aproc_setout(dev_submon, obuf);
+ aproc_setout(d->submon, obuf);
obuf->w.sub.xrun = xrun;
}
@@ -1040,14 +1074,14 @@ dev_attach(char *name, unsigned mode,
ibuf->duplex = obuf;
obuf->duplex = ibuf;
}
- dev_sync(mode, ibuf, obuf);
+ dev_sync(d, mode, ibuf, obuf);
}
/*
* Change the playback volume of the given stream.
*/
void
-dev_setvol(struct abuf *ibuf, int vol)
+dev_setvol(struct dev *d, struct abuf *ibuf, int vol)
{
#ifdef DEBUG
if (debug_level >= 3) {
@@ -1057,7 +1091,7 @@ dev_setvol(struct abuf *ibuf, int vol)
dbg_puts("\n");
}
#endif
- if (!dev_getep(MODE_PLAY, &ibuf, NULL)) {
+ if (!dev_getep(d, MODE_PLAY, &ibuf, NULL)) {
return;
}
ibuf->r.mix.vol = vol;
@@ -1068,53 +1102,53 @@ dev_setvol(struct abuf *ibuf, int vol)
* is started, playback and record start in sync.
*/
void
-dev_clear(void)
+dev_clear(struct dev *d)
{
struct abuf *buf;
- if (APROC_OK(dev_mix)) {
+ if (APROC_OK(d->mix)) {
#ifdef DEBUG
- if (!LIST_EMPTY(&dev_mix->ins)) {
+ if (!LIST_EMPTY(&d->mix->ins)) {
dbg_puts("play end not idle, can't clear device\n");
dbg_panic();
}
#endif
- buf = LIST_FIRST(&dev_mix->outs);
+ buf = LIST_FIRST(&d->mix->outs);
while (buf) {
abuf_clear(buf);
buf = LIST_FIRST(&buf->rproc->outs);
}
- mix_clear(dev_mix);
+ mix_clear(d->mix);
}
- if (APROC_OK(dev_sub)) {
+ if (APROC_OK(d->sub)) {
#ifdef DEBUG
- if (!LIST_EMPTY(&dev_sub->outs)) {
+ if (!LIST_EMPTY(&d->sub->outs)) {
dbg_puts("record end not idle, can't clear device\n");
dbg_panic();
}
#endif
- buf = LIST_FIRST(&dev_sub->ins);
+ buf = LIST_FIRST(&d->sub->ins);
while (buf) {
abuf_clear(buf);
buf = LIST_FIRST(&buf->wproc->ins);
}
- sub_clear(dev_sub);
+ sub_clear(d->sub);
}
- if (APROC_OK(dev_submon)) {
+ if (APROC_OK(d->submon)) {
#ifdef DEBUG
dbg_puts("clearing monitor\n");
- if (!LIST_EMPTY(&dev_submon->outs)) {
+ if (!LIST_EMPTY(&d->submon->outs)) {
dbg_puts("monitoring end not idle, can't clear device\n");
dbg_panic();
}
#endif
- buf = LIST_FIRST(&dev_submon->ins);
+ buf = LIST_FIRST(&d->submon->ins);
while (buf) {
abuf_clear(buf);
buf = LIST_FIRST(&buf->wproc->ins);
}
- sub_clear(dev_submon);
- mon_clear(dev_mon);
+ sub_clear(d->submon);
+ mon_clear(d->mon);
}
}
@@ -1123,20 +1157,20 @@ dev_clear(void)
* samples to drop
*/
void
-dev_prime(void)
+dev_prime(struct dev *d)
{
#ifdef DEBUG
if (debug_level >= 3)
dbg_puts("priming device\n");
#endif
- if (APROC_OK(dev_mix)) {
+ if (APROC_OK(d->mix)) {
#ifdef DEBUG
- if (!LIST_EMPTY(&dev_mix->ins)) {
+ if (!LIST_EMPTY(&d->mix->ins)) {
dbg_puts("play end not idle, can't prime device\n");
dbg_panic();
}
#endif
- mix_prime(dev_mix);
+ mix_prime(d->mix);
}
}
diff --git a/usr.bin/aucat/dev.h b/usr.bin/aucat/dev.h
index 0e0f83ca198..62ad96b074e 100644
--- a/usr.bin/aucat/dev.h
+++ b/usr.bin/aucat/dev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.h,v 1.23 2010/05/08 15:35:45 ratchov Exp $ */
+/* $OpenBSD: dev.h,v 1.24 2010/06/04 06:15:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -21,30 +21,58 @@ struct aproc;
struct aparams;
struct abuf;
-extern unsigned dev_reqprime;
-extern unsigned dev_bufsz, dev_round, dev_rate;
-extern struct aparams dev_ipar, dev_opar;
-extern struct aproc *dev_mix, *dev_sub, *dev_midi, *dev_submon, *dev_mon;
+struct dev {
+ struct dev *next;
-int dev_run(void);
-int dev_open(void);
-void dev_close(void);
-int dev_ref(void);
-void dev_unref(void);
-void dev_done(void);
-void dev_wakeup(void);
-void dev_init_thru(void);
-void dev_init_loop(struct aparams *, struct aparams *, unsigned);
-void dev_init_sio(char *, unsigned,
- struct aparams *, struct aparams *, unsigned, unsigned);
-int dev_thruadd(char *, int, int);
-void dev_midiattach(struct abuf *, struct abuf *);
-unsigned dev_roundof(unsigned);
-int dev_getpos(void);
-void dev_attach(char *, unsigned,
+ /*
+ * desired parameters
+ */
+ unsigned reqmode; /* mode */
+ struct aparams reqipar, reqopar; /* parameters */
+ unsigned reqbufsz; /* buffer size */
+ unsigned reqround; /* block size */
+ unsigned reqrate; /* sample rate */
+ unsigned prime; /* prime play buffer? */
+ unsigned hold; /* hold the device open ? */
+ unsigned refcnt; /* number of openers */
+#define DEV_CLOSED 0 /* closed */
+#define DEV_INIT 1 /* stopped */
+#define DEV_START 2 /* ready to start */
+#define DEV_RUN 3 /* started */
+ unsigned pstate; /* on of DEV_xxx */
+ char *path; /* sio path */
+
+ /*
+ * actual parameters and runtime state (i.e. once opened)
+ */
+ unsigned mode; /* bitmap of MODE_xxx */
+ unsigned bufsz, round, rate;
+ struct aparams ipar, opar;
+ struct aproc *mix, *sub, *submon;
+ struct aproc *rec, *play, *mon;
+ struct aproc *midi;
+};
+
+extern struct dev *dev_list;
+
+int dev_run(struct dev *);
+int dev_ref(struct dev *);
+void dev_unref(struct dev *);
+void dev_del(struct dev *);
+void dev_wakeup(struct dev *);
+struct dev *dev_new_thru(void);
+struct dev *dev_new_loop(struct aparams *, struct aparams *, unsigned);
+struct dev *dev_new_sio(char *, unsigned,
+ struct aparams *, struct aparams *, unsigned, unsigned,
+ unsigned, unsigned);
+int dev_thruadd(struct dev *, char *, int, int);
+void dev_midiattach(struct dev *, struct abuf *, struct abuf *);
+unsigned dev_roundof(struct dev *, unsigned);
+int dev_getpos(struct dev *);
+void dev_attach(struct dev *, char *, unsigned,
struct abuf *, struct aparams *, unsigned,
struct abuf *, struct aparams *, unsigned,
unsigned, int);
-void dev_setvol(struct abuf *, int);
+void dev_setvol(struct dev *, struct abuf *, int);
#endif /* !define(DEV_H) */
diff --git a/usr.bin/aucat/midi.c b/usr.bin/aucat/midi.c
index 7bd408dfdf0..51a4571eb88 100644
--- a/usr.bin/aucat/midi.c
+++ b/usr.bin/aucat/midi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.c,v 1.24 2010/05/08 15:35:45 ratchov Exp $ */
+/* $OpenBSD: midi.c,v 1.25 2010/06/04 06:15:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -676,11 +676,11 @@ ctl_trystart(struct aproc *p, int caller)
if (caller >= 0)
p->u.ctl.slot[caller].tstate = CTL_RUN;
p->u.ctl.tstate = CTL_RUN;
- p->u.ctl.delta = MTC_SEC * dev_getpos();
- if (dev_rate % (30 * 4 * dev_round) == 0) {
+ p->u.ctl.delta = MTC_SEC * dev_getpos(p->u.ctl.dev);
+ if (p->u.ctl.dev->rate % (30 * 4 * p->u.ctl.dev->round) == 0) {
p->u.ctl.fps_id = MTC_FPS_30;
p->u.ctl.fps = 30;
- } else if (dev_rate % (25 * 4 * dev_round) == 0) {
+ } else if (p->u.ctl.dev->rate % (25 * 4 * p->u.ctl.dev->round) == 0) {
p->u.ctl.fps_id = MTC_FPS_25;
p->u.ctl.fps = 25;
} else {
@@ -697,7 +697,7 @@ ctl_trystart(struct aproc *p, int caller)
dbg_puts(" mtc fps\n");
}
#endif
- dev_wakeup();
+ dev_wakeup(p->u.ctl.dev);
ctl_full(p);
return 1;
}
@@ -778,7 +778,7 @@ ctl_ontick(struct aproc *p, int delta)
if (p->u.ctl.delta < 0)
return;
- qfrlen = dev_rate * (MTC_SEC / (4 * p->u.ctl.fps));
+ qfrlen = p->u.ctl.dev->rate * (MTC_SEC / (4 * p->u.ctl.fps));
while (p->u.ctl.delta >= qfrlen) {
ctl_qfr(p);
p->u.ctl.delta -= qfrlen;
@@ -1155,20 +1155,20 @@ ctl_newin(struct aproc *p, struct abuf *ibuf)
void
ctl_done(struct aproc *p)
{
-#ifdef DEBUG
unsigned i;
struct ctl_slot *s;
for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) {
- /*
- * XXX: shouldn't we abord() here ?
- */
+ if (s->ops != NULL)
+ s->ops->quit(s->arg);
+#ifdef DEBUG
if (s->ops != NULL) {
ctl_slotdbg(p, i);
dbg_puts(": still in use\n");
+ dbg_panic();
}
- }
#endif
+ }
}
struct aproc_ops ctl_ops = {
@@ -1185,13 +1185,14 @@ struct aproc_ops ctl_ops = {
};
struct aproc *
-ctl_new(char *name)
+ctl_new(char *name, struct dev *dev)
{
struct aproc *p;
struct ctl_slot *s;
unsigned i;
p = aproc_new(&ctl_ops, name);
+ p->u.ctl.dev = dev;
p->u.ctl.serial = 0;
p->u.ctl.tstate = CTL_STOP;
for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) {
diff --git a/usr.bin/aucat/midi.h b/usr.bin/aucat/midi.h
index 89f7703c8a5..d55fb42ab4b 100644
--- a/usr.bin/aucat/midi.h
+++ b/usr.bin/aucat/midi.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.h,v 1.8 2010/04/06 20:07:01 ratchov Exp $ */
+/* $OpenBSD: midi.h,v 1.9 2010/06/04 06:15:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -17,8 +17,10 @@
#ifndef MIDI_H
#define MIDI_H
+struct dev;
+
struct aproc *thru_new(char *);
-struct aproc *ctl_new(char *);
+struct aproc *ctl_new(char *, struct dev *);
int ctl_slotnew(struct aproc *, char *, struct ctl_ops *, void *, int);
void ctl_slotdel(struct aproc *, int);
diff --git a/usr.bin/aucat/miofile.c b/usr.bin/aucat/miofile.c
index f3038c88b47..b457ec0cb53 100644
--- a/usr.bin/aucat/miofile.c
+++ b/usr.bin/aucat/miofile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: miofile.c,v 1.4 2010/01/10 21:47:41 ratchov Exp $ */
+/* $OpenBSD: miofile.c,v 1.5 2010/06/04 06:15:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -64,19 +64,19 @@ struct fileops miofile_ops = {
struct miofile *
miofile_new(struct fileops *ops, char *path, int input, int output)
{
+ char *siopath;
struct mio_hdl *hdl;
struct miofile *f;
int mode = 0;
+ siopath = (strcmp(path, "default") == 0) ? NULL : path;
if (input)
mode |= MIO_IN;
if (output)
mode |= MIO_OUT;
- hdl = mio_open(path, mode, 1);
+ hdl = mio_open(siopath, mode, 1);
if (hdl == NULL)
return NULL;
- if (path == NULL)
- path = "default";
f = (struct miofile *)file_new(ops, path, mio_nfds(hdl));
if (f == NULL)
goto bad_close;
diff --git a/usr.bin/aucat/opt.c b/usr.bin/aucat/opt.c
index ef36daf4ff8..6ab06ce677c 100644
--- a/usr.bin/aucat/opt.c
+++ b/usr.bin/aucat/opt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: opt.c,v 1.8 2010/04/21 06:13:07 ratchov Exp $ */
+/* $OpenBSD: opt.c,v 1.9 2010/06/04 06:15:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -27,7 +27,7 @@
struct optlist opt_list = SLIST_HEAD_INITIALIZER(&opt_list);
void
-opt_new(char *name, struct aparams *wpar, struct aparams *rpar,
+opt_new(char *name, struct dev *d, struct aparams *wpar, struct aparams *rpar,
int maxweight, int mmc, int join, unsigned mode)
{
struct opt *o;
@@ -48,6 +48,12 @@ opt_new(char *name, struct aparams *wpar, struct aparams *rpar,
exit(1);
}
}
+ SLIST_FOREACH(o, &opt_list, entry) {
+ if (strcmp(name, o->name) == 0) {
+ fprintf(stderr, "%s: already defined\n", name);
+ exit(1);
+ }
+ }
o = malloc(sizeof(struct opt));
if (o == NULL) {
perror("opt_new: malloc");
@@ -62,6 +68,7 @@ opt_new(char *name, struct aparams *wpar, struct aparams *rpar,
o->mmc = mmc;
o->join = join;
o->mode = mode;
+ o->dev = d;
#ifdef DEBUG
if (debug_level >= 2) {
dbg_puts(o->name);
diff --git a/usr.bin/aucat/opt.h b/usr.bin/aucat/opt.h
index 752e7dd5eae..79cb4164f45 100644
--- a/usr.bin/aucat/opt.h
+++ b/usr.bin/aucat/opt.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: opt.h,v 1.7 2010/05/02 11:54:26 ratchov Exp $ */
+/* $OpenBSD: opt.h,v 1.8 2010/06/04 06:15:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -20,6 +20,8 @@
#include <sys/queue.h>
#include "aparams.h"
+struct dev;
+
struct opt {
SLIST_ENTRY(opt) entry;
#define OPT_NAMEMAX 11
@@ -36,12 +38,15 @@ struct opt {
#define MODE_MON 0x10 /* allowed to monitor */
#define MODE_LOOP 0x20 /* deviceless mode */
#define MODE_RECMASK (MODE_REC | MODE_MON)
+#define MODE_AUDIOMASK (MODE_REC | MODE_MON | MODE_PLAY)
+#define MODE_MIDIMASK (MODE_MIDIIN | MODE_MIDIOUT)
unsigned mode; /* bitmap of above */
+ struct dev *dev; /* device to which we're attached */
};
SLIST_HEAD(optlist,opt);
-void opt_new(char *, struct aparams *, struct aparams *,
+void opt_new(char *, struct dev *, struct aparams *, struct aparams *,
int, int, int, unsigned);
struct opt *opt_byname(char *);
diff --git a/usr.bin/aucat/siofile.c b/usr.bin/aucat/siofile.c
index 780356126d8..a371521abc0 100644
--- a/usr.bin/aucat/siofile.c
+++ b/usr.bin/aucat/siofile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: siofile.c,v 1.5 2010/05/02 11:54:26 ratchov Exp $ */
+/* $OpenBSD: siofile.c,v 1.6 2010/06/04 06:15:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -198,20 +198,22 @@ siofile_new(struct fileops *ops, char *path, unsigned *rmode,
struct aparams *ipar, struct aparams *opar,
unsigned *bufsz, unsigned *round)
{
+ char *siopath;
struct sio_par par;
struct sio_hdl *hdl;
struct siofile *f;
unsigned mode = *rmode;
- hdl = sio_open(path, mode, 1);
+ siopath = (strcmp(path, "default") == 0) ? NULL : path;
+ hdl = sio_open(siopath, mode, 1);
if (hdl == NULL) {
if (mode != (SIO_PLAY | SIO_REC))
return NULL;
- hdl = sio_open(path, SIO_PLAY, 1);
+ hdl = sio_open(siopath, SIO_PLAY, 1);
if (hdl != NULL)
mode = SIO_PLAY;
else {
- hdl = sio_open(path, SIO_REC, 1);
+ hdl = sio_open(siopath, SIO_REC, 1);
if (hdl != NULL)
mode = SIO_REC;
else
@@ -272,8 +274,6 @@ siofile_new(struct fileops *ops, char *path, unsigned *rmode,
*rmode = mode;
*bufsz = par.bufsz;
*round = par.round;
- if (path == NULL)
- path = "default";
f = (struct siofile *)file_new(ops, path, sio_nfds(hdl));
if (f == NULL)
goto bad_close;
diff --git a/usr.bin/aucat/sock.c b/usr.bin/aucat/sock.c
index 396783ab1de..6cf05b8bdd0 100644
--- a/usr.bin/aucat/sock.c
+++ b/usr.bin/aucat/sock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sock.c,v 1.47 2010/05/08 15:35:45 ratchov Exp $ */
+/* $OpenBSD: sock.c,v 1.48 2010/06/04 06:15:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -60,10 +60,12 @@ sock_dbg(struct sock *f)
static char *pstates[] = { "hel", "ini", "sta", "rdy", "run", "mid" };
static char *rstates[] = { "rdat", "rmsg", "rret" };
static char *wstates[] = { "widl", "wmsg", "wdat" };
+ struct aproc *midi;
- if (f->slot >= 0 && APROC_OK(dev_midi)) {
- dbg_puts(dev_midi->u.ctl.slot[f->slot].name);
- dbg_putu(dev_midi->u.ctl.slot[f->slot].unit);
+ midi = f->dev ? f->dev->midi : NULL;
+ if (f->slot >= 0 && APROC_OK(midi)) {
+ dbg_puts(midi->u.ctl.slot[f->slot].name);
+ dbg_putu(midi->u.ctl.slot[f->slot].unit);
} else
dbg_puts(f->pipe.file.name);
dbg_puts("/");
@@ -78,24 +80,31 @@ sock_dbg(struct sock *f)
void sock_setvol(void *, unsigned);
void sock_startreq(void *);
void sock_stopreq(void *);
+void sock_quitreq(void *);
void sock_locreq(void *, unsigned);
struct ctl_ops ctl_sockops = {
sock_setvol,
sock_startreq,
sock_stopreq,
- sock_locreq
+ sock_locreq,
+ sock_quitreq
};
unsigned sock_sesrefs = 0; /* connections to the session */
uid_t sock_sesuid; /* owner of the session */
void
-sock_close(struct file *f)
+sock_close(struct file *arg)
{
+ struct sock *f = (struct sock *)arg;
+
sock_sesrefs--;
- pipe_close(f);
- dev_unref();
+ pipe_close(&f->pipe.file);
+ if (f->dev) {
+ dev_unref(f->dev);
+ f->dev = NULL;
+ }
}
void
@@ -109,7 +118,7 @@ rsock_done(struct aproc *p)
f->pipe.file.rproc = NULL;
if (f->pipe.file.wproc) {
if (f->slot >= 0)
- ctl_slotdel(dev_midi, f->slot);
+ ctl_slotdel(f->dev->midi, f->slot);
aproc_del(f->pipe.file.wproc);
file_del(&f->pipe.file);
}
@@ -214,7 +223,7 @@ wsock_done(struct aproc *p)
f->pipe.file.wproc = NULL;
if (f->pipe.file.rproc) {
if (f->slot >= 0)
- ctl_slotdel(dev_midi, f->slot);
+ ctl_slotdel(f->dev->midi, f->slot);
aproc_del(f->pipe.file.rproc);
file_del(&f->pipe.file);
}
@@ -338,22 +347,11 @@ sock_new(struct fileops *ops, int fd)
close(fd);
return NULL;
}
- if (!dev_ref()) {
- close(fd);
- return NULL;
- }
f->pstate = SOCK_HELLO;
f->mode = 0;
- f->opt = opt_byname("default");
- if (f->opt) {
- if (f->opt->mode & MODE_RECMASK)
- f->wpar = f->opt->wpar;
- if (f->opt->mode & MODE_PLAY)
- f->rpar = f->opt->rpar;
- }
+ f->opt = NULL;
+ f->dev = NULL;
f->xrun = AMSG_IGNORE;
- f->bufsz = dev_bufsz;
- f->round = dev_round;
f->delta = 0;
f->tickpending = 0;
f->startpending = 0;
@@ -394,7 +392,7 @@ sock_freebuf(struct sock *f)
wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
if (rbuf || wbuf)
- ctl_slotstop(dev_midi, f->slot);
+ ctl_slotstop(f->dev->midi, f->slot);
if (rbuf)
abuf_eof(rbuf);
if (wbuf)
@@ -442,7 +440,7 @@ sock_allocbuf(struct sock *f)
f->pstate = SOCK_START;
} else {
f->pstate = SOCK_READY;
- if (ctl_slotstart(dev_midi, f->slot))
+ if (ctl_slotstart(f->dev->midi, f->slot))
(void)sock_attach(f, 0);
}
}
@@ -467,7 +465,7 @@ sock_setvol(void *arg, unsigned vol)
#endif
return;
}
- dev_setvol(rbuf, MIDI_TO_ADATA(vol));
+ dev_setvol(f->dev, rbuf, MIDI_TO_ADATA(vol));
}
/*
@@ -521,7 +519,24 @@ sock_locreq(void *arg, unsigned mmcpos)
}
/*
- * Attach play and/or record buffers to dev_mix and/or dev_sub.
+ * Callback invoked when slot is gone
+ */
+void
+sock_quitreq(void *arg)
+{
+ struct sock *f = (struct sock *)arg;
+
+#ifdef DEBUG
+ if (debug_level >= 3) {
+ sock_dbg(f);
+ dbg_puts(": slot gone\n");
+ }
+#endif
+ file_close(&f->pipe.file);
+}
+
+/*
+ * Attach play and/or record buffers to dev->mix and/or dev->sub.
*/
void
sock_attach(struct sock *f, int force)
@@ -542,13 +557,13 @@ sock_attach(struct sock *f, int force)
* start the device (dev_getpos() and dev_attach() must
* be called on a started device
*/
- dev_wakeup();
+ dev_wakeup(f->dev);
/*
* get the current position, the origin is when
* the first sample is played/recorded
*/
- f->delta = dev_getpos() * (int)f->round / (int)dev_round;
+ f->delta = dev_getpos(f->dev) * (int)f->round / (int)f->dev->round;
f->startpending = 1;
f->pstate = SOCK_RUN;
#ifdef DEBUG
@@ -564,14 +579,14 @@ sock_attach(struct sock *f, int force)
* because dev_xxx() functions are supposed to
* work (i.e., not to crash)
*/
- dev_attach(f->pipe.file.name, f->mode,
+ dev_attach(f->dev, f->pipe.file.name, f->mode,
rbuf, &f->rpar,
f->opt->join ? f->opt->rpar.cmax - f->opt->rpar.cmin + 1 : 0,
wbuf, &f->wpar,
f->opt->join ? f->opt->wpar.cmax - f->opt->wpar.cmin + 1 : 0,
f->xrun, f->opt->maxweight);
if (f->mode & AMSG_PLAY)
- dev_setvol(rbuf, MIDI_TO_ADATA(f->vol));
+ dev_setvol(f->dev, rbuf, MIDI_TO_ADATA(f->vol));
/*
* Send the initial position, if needed.
@@ -588,7 +603,7 @@ sock_reset(struct sock *f)
switch (f->pstate) {
case SOCK_START:
case SOCK_READY:
- if (ctl_slotstart(dev_midi, f->slot)) {
+ if (ctl_slotstart(f->dev->midi, f->slot)) {
(void)sock_attach(f, 1);
f->pstate = SOCK_RUN;
}
@@ -859,10 +874,10 @@ sock_setpar(struct sock *f)
p->rate = RATE_MIN;
if (p->rate > RATE_MAX)
p->rate = RATE_MAX;
- f->round = dev_roundof(p->rate);
+ f->round = dev_roundof(f->dev, p->rate);
f->rpar.rate = f->wpar.rate = p->rate;
if (!AMSG_ISSET(p->appbufsz)) {
- p->appbufsz = dev_bufsz / dev_round * f->round;
+ p->appbufsz = f->dev->bufsz / f->dev->round * f->round;
#ifdef DEBUG
if (debug_level >= 3) {
sock_dbg(f);
@@ -922,7 +937,7 @@ sock_setpar(struct sock *f)
dbg_puts("fr total buffer size\n");
}
#endif
- min = (dev_bufsz / dev_round) * f->round;
+ min = (f->dev->bufsz / f->dev->round) * f->round;
if (p->bufsz < min)
p->bufsz = min;
p->appbufsz = p->bufsz - min;
@@ -930,7 +945,7 @@ sock_setpar(struct sock *f)
if (AMSG_ISSET(p->appbufsz)) {
rate = (f->mode & AMSG_PLAY) ? f->rpar.rate : f->wpar.rate;
min = 1;
- max = 1 + rate / dev_round;
+ max = 1 + rate / f->dev->round;
min *= f->round;
max *= f->round;
p->appbufsz += f->round - 1;
@@ -951,9 +966,9 @@ sock_setpar(struct sock *f)
}
#ifdef DEBUG
if (debug_level >= 2) {
- if (f->slot >= 0 && dev_midi) {
- dbg_puts(dev_midi->u.ctl.slot[f->slot].name);
- dbg_putu(dev_midi->u.ctl.slot[f->slot].unit);
+ if (APROC_OK(f->dev->midi)) {
+ dbg_puts(f->dev->midi->u.ctl.slot[f->slot].name);
+ dbg_putu(f->dev->midi->u.ctl.slot[f->slot].unit);
} else
dbg_puts(f->pipe.file.name);
dbg_puts(": buffer size = ");
@@ -988,7 +1003,7 @@ sock_midiattach(struct sock *f, unsigned mode)
wbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
aproc_setin(f->pipe.file.wproc, wbuf);
}
- dev_midiattach(rbuf, wbuf);
+ dev_midiattach(f->dev, rbuf, wbuf);
}
int
@@ -1019,10 +1034,14 @@ sock_hello(struct sock *f)
#endif
return 0;
}
- /*
- * XXX : dev_midi can no longer be NULL, right ?
- */
- if (APROC_OK(dev_midi) && (p->proto & (AMSG_MIDIIN | AMSG_MIDIOUT))) {
+ f->opt = opt_byname(p->opt);
+ if (f->opt == NULL)
+ return 0;
+ if (!dev_ref(f->opt->dev))
+ return 0;
+ f->dev = f->opt->dev;
+
+ if (APROC_OK(f->dev->midi) && (p->proto & (AMSG_MIDIIN | AMSG_MIDIOUT))) {
if (p->proto & ~(AMSG_MIDIIN | AMSG_MIDIOUT)) {
#ifdef DEBUG
if (debug_level >= 1) {
@@ -1039,15 +1058,14 @@ sock_hello(struct sock *f)
sock_midiattach(f, p->proto);
return 1;
}
- f->opt = opt_byname(p->opt);
- if (f->opt == NULL)
- return 0;
if (f->opt->mode & MODE_RECMASK)
f->wpar = f->opt->wpar;
if (f->opt->mode & MODE_PLAY)
f->rpar = f->opt->rpar;
if (f->opt->mmc)
f->xrun = AMSG_SYNC;
+ f->bufsz = f->dev->bufsz;
+ f->round = f->dev->round;
if ((p->proto & ~(AMSG_PLAY | AMSG_REC)) != 0 ||
(p->proto & (AMSG_PLAY | AMSG_REC)) == 0) {
#ifdef DEBUG
@@ -1062,7 +1080,7 @@ sock_hello(struct sock *f)
}
f->mode = 0;
if (p->proto & AMSG_PLAY) {
- if (!APROC_OK(dev_mix) || !(f->opt->mode & MODE_PLAY)) {
+ if (!APROC_OK(f->dev->mix) || !(f->opt->mode & MODE_PLAY)) {
#ifdef DEBUG
if (debug_level >= 1) {
sock_dbg(f);
@@ -1074,8 +1092,8 @@ sock_hello(struct sock *f)
f->mode |= AMSG_PLAY;
}
if (p->proto & AMSG_REC) {
- if (!(APROC_OK(dev_sub) && (f->opt->mode & MODE_REC)) &&
- !(APROC_OK(dev_submon) && (f->opt->mode & MODE_MON))) {
+ if (!(APROC_OK(f->dev->sub) && (f->opt->mode & MODE_REC)) &&
+ !(APROC_OK(f->dev->submon) && (f->opt->mode & MODE_MON))) {
#ifdef DEBUG
if (debug_level >= 1) {
sock_dbg(f);
@@ -1086,8 +1104,8 @@ sock_hello(struct sock *f)
}
f->mode |= (f->opt->mode & MODE_MON) ? AMSG_MON : AMSG_REC;
}
- if (APROC_OK(dev_midi)) {
- f->slot = ctl_slotnew(dev_midi,
+ if (APROC_OK(f->dev->midi)) {
+ f->slot = ctl_slotnew(f->dev->midi,
p->who, &ctl_sockops, f,
f->opt->mmc);
if (f->slot < 0) {
@@ -1234,7 +1252,7 @@ sock_execmsg(struct sock *f)
*/
}
if ((f->pstate == SOCK_START || f->pstate == SOCK_READY) &&
- ctl_slotstart(dev_midi, f->slot))
+ ctl_slotstart(f->dev->midi, f->slot))
(void)sock_attach(f, 1);
if (f->wstate != SOCK_WDATA || f->wtodo == 0)
sock_freebuf(f);
@@ -1309,7 +1327,7 @@ sock_execmsg(struct sock *f)
}
m->u.par.appbufsz = f->bufsz;
m->u.par.bufsz =
- f->bufsz + (dev_bufsz / dev_round) * f->round;
+ f->bufsz + (f->dev->bufsz / f->dev->round) * f->round;
m->u.par.round = f->round;
f->rstate = SOCK_RRET;
f->rtodo = sizeof(struct amsg);
@@ -1333,7 +1351,7 @@ sock_execmsg(struct sock *f)
}
AMSG_INIT(m);
m->cmd = AMSG_GETCAP;
- m->u.cap.rate = dev_rate;
+ m->u.cap.rate = f->dev->rate;
m->u.cap.pchan = (f->opt->mode & MODE_PLAY) ?
(f->opt->rpar.cmax - f->opt->rpar.cmin + 1) : 0;
m->u.cap.rchan = (f->opt->mode & (MODE_PLAY | MODE_REC)) ?
@@ -1373,7 +1391,7 @@ sock_execmsg(struct sock *f)
}
sock_setvol(f, m->u.vol.ctl);
if (f->slot >= 0)
- ctl_slotvol(dev_midi, f->slot, m->u.vol.ctl);
+ ctl_slotvol(f->dev->midi, f->slot, m->u.vol.ctl);
f->rtodo = sizeof(struct amsg);
f->rstate = SOCK_RMSG;
break;
@@ -1602,7 +1620,7 @@ sock_read(struct sock *f)
* samples queues, if so ctl_slotstart() will trigger
* other streams, but this one won't start.
*/
- if (f->pstate == SOCK_READY && ctl_slotstart(dev_midi, f->slot))
+ if (f->pstate == SOCK_READY && ctl_slotstart(f->dev->midi, f->slot))
(void)sock_attach(f, 0);
break;
case SOCK_RRET:
diff --git a/usr.bin/aucat/sock.h b/usr.bin/aucat/sock.h
index abeb61f1c4e..5ef793afec5 100644
--- a/usr.bin/aucat/sock.h
+++ b/usr.bin/aucat/sock.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sock.h,v 1.15 2010/04/06 20:07:01 ratchov Exp $ */
+/* $OpenBSD: sock.h,v 1.16 2010/06/04 06:15:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -64,6 +64,7 @@ struct sock {
int lastvol; /* last volume */
int slot; /* mixer ctl slot number */
struct opt *opt; /* "subdevice" definition */
+ struct dev *dev; /* actual hardware device */
char who[12]; /* label, mostly for debugging */
};
diff --git a/usr.bin/aucat/wav.c b/usr.bin/aucat/wav.c
index bb6844ac899..fa1dc4e99d6 100644
--- a/usr.bin/aucat/wav.c
+++ b/usr.bin/aucat/wav.c
@@ -138,12 +138,14 @@ void wav_setvol(void *, unsigned);
void wav_startreq(void *);
void wav_stopreq(void *);
void wav_locreq(void *, unsigned);
+void wav_quitreq(void *);
struct ctl_ops ctl_wavops = {
wav_setvol,
wav_startreq,
wav_stopreq,
- wav_locreq
+ wav_locreq,
+ wav_quitreq
};
struct aproc_ops rwav_ops = {
@@ -180,11 +182,12 @@ void
wav_dbg(struct wav *f)
{
static char *pstates[] = { "ini", "sta", "rdy", "run", "fai" };
+ struct aproc *midi = f->dev ? f->dev->midi : NULL;
dbg_puts("wav(");
- if (f->slot >= 0 && APROC_OK(dev_midi)) {
- dbg_puts(dev_midi->u.ctl.slot[f->slot].name);
- dbg_putu(dev_midi->u.ctl.slot[f->slot].unit);
+ if (f->slot >= 0 && APROC_OK(midi)) {
+ dbg_puts(midi->u.ctl.slot[f->slot].name);
+ dbg_putu(midi->u.ctl.slot[f->slot].unit);
} else
dbg_puts(f->pipe.file.name);
dbg_puts(")/");
@@ -231,7 +234,7 @@ wav_read(struct file *file, unsigned char *data, unsigned count)
dbg_puts(": read complete\n");
}
#endif
- if (!f->tr)
+ if (!f->mmc)
file_eof(&f->pipe.file);
return 0;
}
@@ -295,7 +298,10 @@ wav_close(struct file *file)
}
}
pipe_close(file);
- dev_unref();
+ if (f->dev) {
+ dev_unref(f->dev);
+ f->dev = NULL;
+ }
}
/*
@@ -306,6 +312,7 @@ int
wav_attach(struct wav *f, int force)
{
struct abuf *rbuf = NULL, *wbuf = NULL;
+ struct dev *d = f->dev;
if (f->mode & MODE_PLAY)
rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
@@ -323,14 +330,14 @@ wav_attach(struct wav *f, int force)
* start the device (dev_getpos() and dev_attach() must
* be called on a started device
*/
- dev_wakeup();
+ dev_wakeup(d);
- dev_attach(f->pipe.file.name, f->mode,
- rbuf, &f->hpar, f->join ? dev_opar.cmax - dev_opar.cmin + 1 : 0,
- wbuf, &f->hpar, f->join ? dev_ipar.cmax - dev_ipar.cmin + 1 : 0,
+ dev_attach(d, f->pipe.file.name, f->mode,
+ rbuf, &f->hpar, f->join ? d->opar.cmax - d->opar.cmin + 1 : 0,
+ wbuf, &f->hpar, f->join ? d->ipar.cmax - d->ipar.cmin + 1 : 0,
f->xrun, f->maxweight);
if (f->mode & MODE_PLAY)
- dev_setvol(rbuf, MIDI_TO_ADATA(f->vol));
+ dev_setvol(d, rbuf, MIDI_TO_ADATA(f->vol));
return 1;
}
@@ -346,11 +353,12 @@ void
wav_allocbuf(struct wav *f)
{
struct abuf *buf;
+ struct dev *d = f->dev;
unsigned nfr;
f->pstate = WAV_START;
if (f->mode & MODE_PLAY) {
- nfr = 2 * dev_bufsz * f->hpar.rate / dev_rate;
+ nfr = 2 * d->bufsz * f->hpar.rate / d->rate;
buf = abuf_new(nfr, &f->hpar);
aproc_setout(f->pipe.file.rproc, buf);
abuf_fill(buf);
@@ -358,7 +366,7 @@ wav_allocbuf(struct wav *f)
f->pstate = WAV_READY;
}
if (f->mode & MODE_RECMASK) {
- nfr = 2 * dev_bufsz * f->hpar.rate / dev_rate;
+ nfr = 2 * d->bufsz * f->hpar.rate / d->rate;
buf = abuf_new(nfr, &f->hpar);
aproc_setin(f->pipe.file.wproc, buf);
f->pstate = WAV_READY;
@@ -369,7 +377,7 @@ wav_allocbuf(struct wav *f)
dbg_puts(": allocating buffers\n");
}
#endif
- if (f->pstate == WAV_READY && ctl_slotstart(dev_midi, f->slot))
+ if (f->pstate == WAV_READY && ctl_slotstart(d->midi, f->slot))
(void)wav_attach(f, 0);
}
@@ -393,7 +401,7 @@ wav_freebuf(struct wav *f)
}
#endif
if (rbuf || wbuf)
- ctl_slotstop(dev_midi, f->slot);
+ ctl_slotstop(f->dev->midi, f->slot);
if (rbuf)
abuf_eof(rbuf);
if (wbuf)
@@ -410,7 +418,7 @@ wav_reset(struct wav *f)
switch (f->pstate) {
case WAV_START:
case WAV_READY:
- if (ctl_slotstart(dev_midi, f->slot))
+ if (ctl_slotstart(f->dev->midi, f->slot))
(void)wav_attach(f, 1);
/* PASSTHROUGH */
case WAV_RUN:
@@ -430,6 +438,7 @@ wav_reset(struct wav *f)
void
wav_exit(struct wav *f)
{
+ /* XXX: call file_close() ? */
if (f->mode & MODE_PLAY) {
aproc_del(f->pipe.file.rproc);
} else if (f->mode & MODE_RECMASK) {
@@ -455,7 +464,7 @@ wav_seekmmc(struct wav *f)
* don't make other stream wait for us
*/
if (f->slot >= 0)
- ctl_slotstart(dev_midi, f->slot);
+ ctl_slotstart(f->dev->midi, f->slot);
return 0;
}
if (!pipe_seek(&f->pipe.file, f->mmcpos)) {
@@ -493,7 +502,7 @@ wav_rdata(struct wav *f)
f->pstate = WAV_READY;
/* PASSTHROUGH */
case WAV_READY:
- if (ctl_slotstart(dev_midi, f->slot))
+ if (ctl_slotstart(f->dev->midi, f->slot))
(void)wav_attach(f, 0);
break;
#ifdef DEBUG
@@ -505,7 +514,7 @@ wav_rdata(struct wav *f)
dbg_panic();
#endif
}
- if (f->rbytes == 0 && f->tr) {
+ if (f->rbytes == 0 && f->mmc) {
#ifdef DEBUG
if (debug_level >= 3) {
wav_dbg(f);
@@ -549,7 +558,7 @@ wav_setvol(void *arg, unsigned vol)
f->vol = vol;
if ((f->mode & MODE_PLAY) && f->pstate == WAV_RUN) {
rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
- dev_setvol(rbuf, MIDI_TO_ADATA(vol));
+ dev_setvol(f->dev, rbuf, MIDI_TO_ADATA(vol));
}
}
@@ -605,7 +614,7 @@ wav_stopreq(void *arg)
dbg_puts("\n");
}
#endif
- if (!f->tr) {
+ if (!f->mmc) {
wav_exit(f);
return;
}
@@ -634,10 +643,29 @@ wav_locreq(void *arg, unsigned mmc)
}
/*
+ * Callback invoked when slot is gone
+ */
+void
+wav_quitreq(void *arg)
+{
+ struct wav *f = (struct wav *)arg;
+
+#ifdef DEBUG
+ if (debug_level >= 3) {
+ wav_dbg(f);
+ dbg_puts(": slot gone\n");
+ }
+#endif
+ if (f->pstate != WAV_RUN)
+ wav_exit(f);
+}
+
+/*
* create a file reader in the ``INIT'' state
*/
struct wav *
-wav_new_in(struct fileops *ops, unsigned mode, char *name, unsigned hdr,
+wav_new_in(struct fileops *ops,
+ struct dev *dev, unsigned mode, char *name, unsigned hdr,
struct aparams *par, unsigned xrun, unsigned volctl, int tr, int join)
{
int fd;
@@ -660,10 +688,11 @@ wav_new_in(struct fileops *ops, unsigned mode, char *name, unsigned hdr,
close(fd);
return NULL;
}
- if (!dev_ref()) {
+ if (!dev_ref(dev)) {
close(fd);
return NULL;
}
+ f->dev = dev;
if (hdr == HDR_WAV) {
if (!wav_readhdr(f->pipe.fd, par, &f->startpos, &f->rbytes, &f->map)) {
file_del((struct file *)f);
@@ -683,14 +712,14 @@ wav_new_in(struct fileops *ops, unsigned mode, char *name, unsigned hdr,
f->rbytes = -1;
f->map = NULL;
}
- f->tr = tr;
+ f->mmc = tr;
f->join = join;
f->mode = mode;
f->hpar = *par;
f->hdr = 0;
f->xrun = xrun;
f->maxweight = MIDI_TO_ADATA(volctl);
- f->slot = ctl_slotnew(dev_midi, "play", &ctl_wavops, f, 1);
+ f->slot = ctl_slotnew(f->dev->midi, "play", &ctl_wavops, f, 1);
rwav_new((struct file *)f);
wav_allocbuf(f);
#ifdef DEBUG
@@ -702,7 +731,7 @@ wav_new_in(struct fileops *ops, unsigned mode, char *name, unsigned hdr,
dbg_putu(f->endpos);
dbg_puts(": playing ");
aparams_dbg(par);
- if (f->tr)
+ if (f->mmc)
dbg_puts(", mmc");
dbg_puts("\n");
}
@@ -714,7 +743,8 @@ wav_new_in(struct fileops *ops, unsigned mode, char *name, unsigned hdr,
* create a file writer in the ``INIT'' state
*/
struct wav *
-wav_new_out(struct fileops *ops, unsigned mode, char *name, unsigned hdr,
+wav_new_out(struct fileops *ops,
+ struct dev *dev, unsigned mode, char *name, unsigned hdr,
struct aparams *par, unsigned xrun, int tr, int join)
{
int fd;
@@ -738,10 +768,11 @@ wav_new_out(struct fileops *ops, unsigned mode, char *name, unsigned hdr,
close(fd);
return NULL;
}
- if (!dev_ref()) {
+ if (!dev_ref(dev)) {
close(fd);
return NULL;
}
+ f->dev = dev;
if (hdr == HDR_WAV) {
par->le = 1;
par->sig = (par->bits <= 8) ? 0 : 1;
@@ -756,13 +787,13 @@ wav_new_out(struct fileops *ops, unsigned mode, char *name, unsigned hdr,
f->wbytes = -1;
f->startpos = f->endpos = 0;
}
- f->tr = tr;
+ f->mmc = tr;
f->join = join;
f->mode = mode;
f->hpar = *par;
f->hdr = hdr;
f->xrun = xrun;
- f->slot = ctl_slotnew(dev_midi, "rec", &ctl_wavops, f, 1);
+ f->slot = ctl_slotnew(f->dev->midi, "rec", &ctl_wavops, f, 1);
wwav_new((struct file *)f);
wav_allocbuf(f);
#ifdef DEBUG
@@ -782,7 +813,7 @@ rwav_done(struct aproc *p)
struct wav *f = (struct wav *)p->u.io.file;
if (f->slot >= 0)
- ctl_slotdel(dev_midi, f->slot);
+ ctl_slotdel(f->dev->midi, f->slot);
f->slot = -1;
rfile_done(p);
}
@@ -835,7 +866,7 @@ wwav_done(struct aproc *p)
struct wav *f = (struct wav *)p->u.io.file;
if (f->slot >= 0)
- ctl_slotdel(dev_midi, f->slot);
+ ctl_slotdel(f->dev->midi, f->slot);
f->slot = -1;
wfile_done(p);
}
diff --git a/usr.bin/aucat/wav.h b/usr.bin/aucat/wav.h
index f8fafeb34db..c929b973704 100644
--- a/usr.bin/aucat/wav.h
+++ b/usr.bin/aucat/wav.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wav.h,v 1.9 2010/04/21 06:13:07 ratchov Exp $ */
+/* $OpenBSD: wav.h,v 1.10 2010/06/04 06:15:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -37,7 +37,7 @@ struct wav {
off_t mmcpos; /* play/rec start point set by MMC */
short *map; /* mulaw/alaw -> s16 conversion table */
int slot; /* mixer ctl slot number */
- int tr; /* use MMC control */
+ int mmc; /* use MMC control */
int join; /* join/expand channels */
unsigned vol; /* current volume */
unsigned maxweight; /* dynamic range when vol == 127 */
@@ -48,14 +48,15 @@ struct wav {
#define WAV_FAILED 4 /* failed to seek */
unsigned pstate; /* one of above */
unsigned mode; /* bitmap of MODE_* */
+ struct dev *dev; /* device playing or recording */
};
extern struct fileops wav_ops;
-struct wav *wav_new_in(struct fileops *, unsigned, char *, unsigned,
- struct aparams *, unsigned, unsigned, int, int);
-struct wav *wav_new_out(struct fileops *, unsigned, char *, unsigned,
- struct aparams *, unsigned, int, int);
+struct wav *wav_new_in(struct fileops *, struct dev *,
+ unsigned, char *, unsigned, struct aparams *, unsigned, unsigned, int, int);
+struct wav *wav_new_out(struct fileops *, struct dev *,
+ unsigned, char *, unsigned, struct aparams *, unsigned, int, int);
unsigned wav_read(struct file *, unsigned char *, unsigned);
unsigned wav_write(struct file *, unsigned char *, unsigned);
void wav_close(struct file *);