From 007a5ce2e1a244df2279b04b17ffeab967abf0bb Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Mon, 20 Jun 2011 17:53:09 +0200 Subject: [PATCH] make -a apply on MIDI ports --- aucat/aucat.1 | 13 +++--- aucat/aucat.c | 56 +++++++++++++++++++------- aucat/dev.c | 102 ++++++++++++++++++++++++++++++++++-------------- aucat/dev.h | 8 +++- aucat/midicat.1 | 14 +++++++ aucat/miofile.c | 9 +---- aucat/miofile.h | 4 +- 7 files changed, 147 insertions(+), 59 deletions(-) diff --git a/aucat/aucat.1 b/aucat/aucat.1 index f0a1a64..775237a 100644 --- a/aucat/aucat.1 +++ b/aucat/aucat.1 @@ -74,15 +74,18 @@ The options are as follows: .It Fl a Ar flag Control whether .Nm -opens the audio device only when needed or keeps it open all the time. +opens the audio device +.Pq Fl f +or the MIDI port +.Pq Fl q +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. +then it 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. +access to it, or corresponding audio or MIDI hardware to be disconnected. The default is .Va on . .It Fl b Ar nframes @@ -319,7 +322,7 @@ On the command line, per-device parameters .Pq Fl abwz must precede the device definition -.Pq Fl f , +.Pq Fl fq , and per-stream parameters .Pq Fl Ccehjmrtvx must precede the stream definition diff --git a/aucat/aucat.c b/aucat/aucat.c index d99f668..e604c1d 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -235,6 +235,7 @@ SLIST_HEAD(cfstrlist, cfstr); struct cfmid { SLIST_ENTRY(cfmid) entry; char *path; /* static path (no need to copy it) */ + int hold; }; SLIST_HEAD(cfmidlist, cfmid); @@ -338,16 +339,28 @@ cfstr_add(struct cfstrlist *list, struct cfstr *cs, char *path) SLIST_INSERT_HEAD(list, cs, entry); } -void -cfmid_add(struct cfmidlist *list, char *path) +struct cfmid * +cfmid_new(struct cfmid *templ) { struct cfmid *cm; - + cm = malloc(sizeof(struct cfmid)); if (cm == NULL) { perror("malloc"); abort(); } + if (templ) + memcpy(cm, templ, sizeof(struct cfmid)); + else { + cm->hold = 1; + } + cm->path = NULL; + return cm; +} + +void +cfmid_add(struct cfmidlist *list, struct cfmid *cm, char *path) +{ cm->path = path; SLIST_INSERT_HEAD(list, cm, entry); } @@ -506,6 +519,7 @@ aucat_main(int argc, char **argv) */ cd = cfdev_new(NULL); cs = cfstr_new(NULL); + cm = cfmid_new(NULL); while ((c = getopt(argc, argv, "a:w:dnb:c:C:e:r:h:x:v:i:o:f:m:luq:s:U:L:t:j:z:")) != -1) { switch (c) { @@ -587,13 +601,14 @@ aucat_main(int argc, char **argv) nsock++; break; case 'a': - cd->hold = opt_onoff(); + cm->hold = cd->hold = opt_onoff(); break; case 'w': cd->autovol = opt_onoff(); break; case 'q': - cfmid_add(&cd->mids, optarg); + cfmid_add(&cd->mids, cm, optarg); + cm = cfmid_new(cm); break; case 'b': cd->bufsz = strtonum(optarg, 1, RATE_MAX * 5, &str); @@ -673,6 +688,7 @@ aucat_main(int argc, char **argv) free(cs); free(cd); } + free(cm); /* * Check modes and calculate "best" device parameters. Iterate over all @@ -752,8 +768,8 @@ aucat_main(int argc, char **argv) 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); + if (!devctl_add(d, cm->path, cm->hold, MODE_MIDIMASK)) + errx(1, "%s: can't open port", cm->path); free(cm); } @@ -870,8 +886,9 @@ aucat_main(int argc, char **argv) void midicat_usage(void) { - (void)fputs("usage: " PROG_MIDICAT " [-dl] " - "[-i file] [-L addr] [-o file] [-q port] [-s name] [-U unit]\n", + (void)fputs("usage: " PROG_MIDICAT " [-dl] [-a flag] " + "[-i file] [-L addr] [-o file] [-q port]\n\t" + "[-s name] [-U unit]\n", stderr); } @@ -908,8 +925,9 @@ midicat_main(int argc, char **argv) */ cs = cfstr_new(NULL); cd = cfdev_new(NULL); + cm = cfmid_new(NULL); - while ((c = getopt(argc, argv, "di:o:ls:q:U:L:")) != -1) { + while ((c = getopt(argc, argv, "di:o:ls:a:q:U:L:")) != -1) { switch (c) { case 'd': #ifdef DEBUG @@ -926,8 +944,12 @@ midicat_main(int argc, char **argv) cfstr_add(&cd->outs, cs, optarg); cs = cfstr_new(cs); break; + case 'a': + cm->hold = opt_onoff(); + break; case 'q': - cfmid_add(&cd->mids, optarg); + cfmid_add(&cd->mids, cm, optarg); + cm = cfmid_new(cm); break; case 's': cfstr_add(&cd->opts, cs, optarg); @@ -978,15 +1000,19 @@ midicat_main(int argc, char **argv) if (SLIST_EMPTY(&cd->mids)) { if (SLIST_EMPTY(&cd->ins) && SLIST_EMPTY(&cd->outs)) { cfstr_add(&cd->opts, cs, DEFAULT_OPT); + free(cm); nsock++; } else { - cfmid_add(&cd->mids, "default"); + cfmid_add(&cd->mids, cm, "default"); free(cs); } - } else + } else { + free(cm); free(cs); + } cfdev_add(&cfdevs, cd, "default"); } else { + free(cm); free(cs); free(cd); } @@ -1014,8 +1040,8 @@ midicat_main(int argc, char **argv) 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); + if (!devctl_add(d, cm->path, cm->hold, MODE_MIDIMASK)) + errx(1, "%s: can't open port", cm->path); free(cm); } diff --git a/aucat/dev.c b/aucat/dev.c index fcf146a..28c8dbf 100644 --- a/aucat/dev.c +++ b/aucat/dev.c @@ -105,6 +105,7 @@ void dev_close(struct dev *); void dev_start(struct dev *); void dev_stop(struct dev *); void dev_clear(struct dev *); +int devctl_open(struct dev *, struct devctl *); struct dev *dev_list = NULL; @@ -123,6 +124,7 @@ dev_new_sio(char *path, perror("malloc"); exit(1); } + d->ctl_list = NULL; d->path = path; d->reqmode = mode; if (mode & MODE_PLAY) @@ -158,6 +160,7 @@ dev_new_loop(struct aparams *dipar, struct aparams *dopar, unsigned bufsz) perror("malloc"); exit(1); } + d->ctl_list = NULL; 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; @@ -189,6 +192,7 @@ dev_new_thru(void) perror("malloc"); exit(1); } + d->ctl_list = NULL; d->reqmode = MODE_MIDIMASK; d->pstate = DEV_CLOSED; d->hold = 0; @@ -198,6 +202,62 @@ dev_new_thru(void) return d; } +/* + * Add a MIDI port to the device + */ +int +devctl_add(struct dev *d, char *name, int hold, unsigned mode) +{ + struct devctl *c; + + if (hold) { + if (!dev_ref(d)) + return 0; + } + c = malloc(sizeof(struct devctl)); + if (c == NULL) { + perror("malloc"); + exit(1); + } + c->path = name; + c->hold = hold; + c->mode = mode; + c->next = d->ctl_list; + d->ctl_list = c; + if (d->pstate != DEV_CLOSED) { + if (!devctl_open(d, c)) + return 0; + } + return 1; +} + +/* + * Open a MIDI device and connect it to the thru box + */ +int +devctl_open(struct dev *d, struct devctl *c) +{ + struct file *f; + struct abuf *rbuf = NULL, *wbuf = NULL; + struct aproc *rproc, *wproc; + + f = (struct file *)miofile_new(&miofile_ops, c->path, c->mode); + if (f == NULL) + return 0; + if (c->mode & MODE_MIDIIN) { + rproc = rfile_new(f); + rbuf = abuf_new(MIDI_BUFSZ, &aparams_none); + aproc_setout(rproc, rbuf); + } + if (c->mode & MODE_MIDIOUT) { + wproc = wfile_new(f); + wbuf = abuf_new(MIDI_BUFSZ, &aparams_none); + aproc_setin(wproc, wbuf); + } + dev_midiattach(d, rbuf, wbuf); + return 1; +} + /* * Open the device with the dev_reqxxx capabilities. Setup a mixer, demuxer, * monitor, midi control, and any necessary conversions. @@ -206,6 +266,7 @@ int dev_open(struct dev *d) { struct file *f; + struct devctl *c; struct aparams par; struct aproc *conv; struct abuf *buf; @@ -399,6 +460,18 @@ dev_open(struct dev *d) } #endif d->pstate = DEV_INIT; + for (c = d->ctl_list; c != NULL; c = c->next) { + if (!devctl_open(d, c)) { +#ifdef DEBUG + if (debug_level >= 1) { + dbg_puts(c->path); + dbg_puts(": couldn't open MIDI port\n"); + } +#endif + dev_close(d); + return 0; + } + } return 1; } @@ -575,35 +648,6 @@ dev_del(struct dev *d) free(d); } -/* - * Open a MIDI device and connect it to the thru box - */ -int -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(d)) - return 0; - f = (struct file *)miofile_new(&miofile_ops, name, in, out); - if (f == NULL) - return 0; - if (in) { - rproc = rfile_new(f); - rbuf = abuf_new(MIDI_BUFSZ, &aparams_none); - aproc_setout(rproc, rbuf); - } - if (out) { - wproc = wfile_new(f); - wbuf = abuf_new(MIDI_BUFSZ, &aparams_none); - aproc_setin(wproc, wbuf); - } - dev_midiattach(d, rbuf, wbuf); - return 1; -} - /* * Attach a bi-directional MIDI stream to the MIDI device */ diff --git a/aucat/dev.h b/aucat/dev.h index 193a8dc..27acac2 100644 --- a/aucat/dev.h +++ b/aucat/dev.h @@ -52,6 +52,12 @@ struct dev { struct aproc *mix, *sub, *submon; struct aproc *rec, *play, *mon; struct aproc *midi; + struct devctl { + struct devctl *next; + char *path; + unsigned mode; + int hold; + } *ctl_list; }; extern struct dev *dev_list; @@ -67,7 +73,7 @@ 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); +int devctl_add(struct dev *, char *, int, unsigned); void dev_midiattach(struct dev *, struct abuf *, struct abuf *); unsigned dev_roundof(struct dev *, unsigned); int dev_getpos(struct dev *); diff --git a/aucat/midicat.1 b/aucat/midicat.1 index ce70978..5cce4bb 100644 --- a/aucat/midicat.1 +++ b/aucat/midicat.1 @@ -23,6 +23,7 @@ .Sh SYNOPSIS .Nm midicat .Op Fl dl +.Op Fl a Ar flag .Op Fl i Ar file .Op Fl L Ar addr .Op Fl o Ar file @@ -47,6 +48,19 @@ MIDI hardware or to another application in a uniform way. .Pp The options are as follows: .Bl -tag -width Ds +.It Fl a Ar flag +Control whether +.Nm +opens the MIDI port only when needed or keeps it open all the time. +If the flag is +.Va on +then it 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 it, or the corresponding MIDI hardware to be disconnected. +The default is +.Va on . .It Fl d Increase log verbosity. .Nm diff --git a/aucat/miofile.c b/aucat/miofile.c index b457ec0..ca0c2d1 100644 --- a/aucat/miofile.c +++ b/aucat/miofile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: miofile.c,v 1.5 2010/06/04 06:15:28 ratchov Exp $ */ +/* $OpenBSD$ */ /* * Copyright (c) 2008 Alexandre Ratchov * @@ -62,18 +62,13 @@ struct fileops miofile_ops = { * open the device */ struct miofile * -miofile_new(struct fileops *ops, char *path, int input, int output) +miofile_new(struct fileops *ops, char *path, unsigned mode) { 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(siopath, mode, 1); if (hdl == NULL) return NULL; diff --git a/aucat/miofile.h b/aucat/miofile.h index e1b2e73..86059a4 100644 --- a/aucat/miofile.h +++ b/aucat/miofile.h @@ -1,4 +1,4 @@ -/* $OpenBSD: miofile.h,v 1.1 2009/07/25 08:44:27 ratchov Exp $ */ +/* $OpenBSD$ */ /* * Copyright (c) 2008 Alexandre Ratchov * @@ -21,7 +21,7 @@ struct file; struct fileops; struct miofile; -struct miofile *miofile_new(struct fileops *, char *, int, int); +struct miofile *miofile_new(struct fileops *, char *, unsigned); extern struct fileops miofile_ops;