summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 *);