mirror of https://github.com/ericonr/sndio.git
switch to type@hostname,unit/num.opt device names
This commit is contained in:
parent
dc2884ed7d
commit
e4ef0dc8d9
|
@ -72,6 +72,13 @@
|
|||
#define DEFAULT_ROUND (44100 / 15)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* default device in server mode
|
||||
*/
|
||||
#ifndef DEFAULT_DEV
|
||||
#define DEFAULT_DEV "rsnd/0"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
volatile sig_atomic_t debug_level = 1;
|
||||
#endif
|
||||
|
@ -338,7 +345,10 @@ mkdev(char *path, int mode, int bufsz, int round, int hold, int autovol)
|
|||
bufsz = round * 4;
|
||||
} else if (!round)
|
||||
round = bufsz / 4;
|
||||
return dev_new(path, mode, bufsz, round, hold, autovol);
|
||||
d = dev_new(path, mode, bufsz, round, hold, autovol);
|
||||
if (d == NULL)
|
||||
exit(1);
|
||||
return d;
|
||||
}
|
||||
|
||||
struct opt *
|
||||
|
@ -538,16 +548,20 @@ main(int argc, char **argv)
|
|||
fputs(usagestr, stderr);
|
||||
exit(1);
|
||||
}
|
||||
if (wav_list == NULL) {
|
||||
if (opt_list == NULL) {
|
||||
d = mkdev(NULL, 0, bufsz, round, 1, autovol);
|
||||
mkopt("default", d, &rpar, &ppar,
|
||||
mode, vol, mmc, join);
|
||||
server = 1;
|
||||
}
|
||||
} else {
|
||||
d = mkdev(NULL, 0, bufsz, round, 1, autovol);
|
||||
if ((d->reqmode & MODE_THRU) && !d->ctl_list) {
|
||||
if (dev_list == NULL)
|
||||
mkdev(DEFAULT_DEV, 0, bufsz, round, hold, autovol);
|
||||
for (d = dev_list; d != NULL; d = d->next) {
|
||||
if ((d->reqmode & (MODE_PLAYREC | MODE_MIDIMASK)) != 0)
|
||||
continue;
|
||||
mkopt("default", d, &rpar, &ppar, mode, vol, mmc, join);
|
||||
server = 1;
|
||||
}
|
||||
if (wav_list) {
|
||||
if (server)
|
||||
errx(1, "-io not allowed in server mode");
|
||||
if ((d = dev_list) && d->next)
|
||||
errx(1, "single device required in non-server mode");
|
||||
if ((d->reqmode & MODE_THRU) && d->ctl_list == NULL) {
|
||||
if (!devctl_add(d, "default", MODE_MIDIMASK))
|
||||
errx(1, "%s: can't open port", optarg);
|
||||
d->reqmode |= MODE_MIDIMASK;
|
||||
|
|
65
aucat/dev.c
65
aucat/dev.c
|
@ -62,27 +62,6 @@
|
|||
* finished draining), then the device
|
||||
* automatically switches to INIT or CLOSED
|
||||
*/
|
||||
/*
|
||||
* TODO:
|
||||
*
|
||||
* priming buffer is not ok, because it will insert silence and
|
||||
* break synchronization to other programs.
|
||||
*
|
||||
* priming buffer in server mode is required, because f->bufsz may
|
||||
* be smaller than the server buffer and may cause underrun in the
|
||||
* dev_bufsz part of the buffer, in turn causing apps to break. It
|
||||
* doesn't hurt because we care only in synchronization between
|
||||
* clients.
|
||||
*
|
||||
* Priming is not required in non-server mode, because streams
|
||||
* actually start when they are in the READY state, and their
|
||||
* buffer is large enough to never cause underruns of dev_bufsz.
|
||||
*
|
||||
* Fix sock.c to allocate dev_bufsz, but to use only appbufsz --
|
||||
* or whatever -- but to avoid underruns in dev_bufsz. Then remove
|
||||
* this ugly hack.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
@ -108,6 +87,21 @@ void dev_clear(struct dev *);
|
|||
int devctl_open(struct dev *, struct devctl *);
|
||||
|
||||
struct dev *dev_list = NULL;
|
||||
unsigned dev_sndnum = 0, dev_midnum = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
dev_dbg(struct dev *d)
|
||||
{
|
||||
if (d->num >= DEV_NMAX) {
|
||||
dbg_puts("mid");
|
||||
dbg_putu(d->num - DEV_NMAX);
|
||||
} else {
|
||||
dbg_puts("snd");
|
||||
dbg_putu(d->num);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create a sndio device
|
||||
|
@ -117,12 +111,23 @@ dev_new(char *path, unsigned mode,
|
|||
unsigned bufsz, unsigned round, unsigned hold, unsigned autovol)
|
||||
{
|
||||
struct dev *d;
|
||||
unsigned *pnum;
|
||||
|
||||
d = malloc(sizeof(struct dev));
|
||||
if (d == NULL) {
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
pnum = (mode & MODE_THRU) ? &dev_midnum : &dev_sndnum;
|
||||
if (*pnum == DEV_NMAX) {
|
||||
#ifdef DEBUG
|
||||
dbg_puts("too many devices\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
d->num = (*pnum)++;
|
||||
if (mode & MODE_THRU)
|
||||
d->num += DEV_NMAX;
|
||||
d->ctl_list = NULL;
|
||||
d->path = path;
|
||||
d->reqmode = mode;
|
||||
|
@ -135,7 +140,7 @@ dev_new(char *path, unsigned mode,
|
|||
d->autostart = 0;
|
||||
d->pstate = DEV_CLOSED;
|
||||
d->next = dev_list;
|
||||
dev_list = d;
|
||||
dev_list = d;
|
||||
return d;
|
||||
}
|
||||
|
||||
|
@ -161,7 +166,7 @@ dev_init(struct dev *d)
|
|||
{
|
||||
if ((d->reqmode & (MODE_AUDIOMASK | MODE_MIDIMASK)) == 0) {
|
||||
#ifdef DEBUG
|
||||
dbg_puts(d->path);
|
||||
dev_dbg(d);
|
||||
dbg_puts(": has no streams, skipped\n");
|
||||
#endif
|
||||
return 1;
|
||||
|
@ -177,7 +182,7 @@ dev_init(struct dev *d)
|
|||
* Add a MIDI port to the device
|
||||
*/
|
||||
int
|
||||
devctl_add(struct dev *d, char *name, unsigned mode)
|
||||
devctl_add(struct dev *d, char *path, unsigned mode)
|
||||
{
|
||||
struct devctl *c;
|
||||
|
||||
|
@ -186,7 +191,7 @@ devctl_add(struct dev *d, char *name, unsigned mode)
|
|||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
c->path = name;
|
||||
c->path = path;
|
||||
c->mode = mode;
|
||||
c->next = d->ctl_list;
|
||||
d->ctl_list = c;
|
||||
|
@ -283,6 +288,8 @@ dev_open(struct dev *d)
|
|||
if (f == NULL) {
|
||||
#ifdef DEBUG
|
||||
if (debug_level >= 1) {
|
||||
dev_dbg(d);
|
||||
dbg_puts(": ");
|
||||
dbg_puts(d->path);
|
||||
dbg_puts(": failed to open audio device\n");
|
||||
}
|
||||
|
@ -296,7 +303,7 @@ dev_open(struct dev *d)
|
|||
if ((d->mode & (MODE_PLAY | MODE_REC)) == 0) {
|
||||
#ifdef DEBUG
|
||||
if (debug_level >= 1) {
|
||||
dbg_puts(d->path);
|
||||
dev_dbg(d);
|
||||
dbg_puts(": mode not supported by device\n");
|
||||
}
|
||||
#endif
|
||||
|
@ -356,13 +363,13 @@ dev_open(struct dev *d)
|
|||
#ifdef DEBUG
|
||||
if (debug_level >= 2) {
|
||||
if (d->mode & MODE_REC) {
|
||||
dbg_puts(d->path);
|
||||
dev_dbg(d);
|
||||
dbg_puts(": recording ");
|
||||
aparams_dbg(&d->ipar);
|
||||
dbg_puts("\n");
|
||||
}
|
||||
if (d->mode & MODE_PLAY) {
|
||||
dbg_puts(d->path);
|
||||
dev_dbg(d);
|
||||
dbg_puts(": playing ");
|
||||
aparams_dbg(&d->opar);
|
||||
dbg_puts("\n");
|
||||
|
@ -471,7 +478,7 @@ dev_open(struct dev *d)
|
|||
#ifdef DEBUG
|
||||
if (debug_level >= 2) {
|
||||
if (d->mode & (MODE_PLAY | MODE_RECMASK)) {
|
||||
dbg_puts(d->path);
|
||||
dev_dbg(d);
|
||||
dbg_puts(": block size is ");
|
||||
dbg_putu(d->round);
|
||||
dbg_puts(" frames, using ");
|
||||
|
|
|
@ -37,6 +37,8 @@ struct dev {
|
|||
unsigned autovol; /* auto adjust playvol ? */
|
||||
unsigned autostart; /* don't wait for MMC start */
|
||||
unsigned refcnt; /* number of openers */
|
||||
#define DEV_NMAX 16 /* max number of devices */
|
||||
unsigned num; /* serial number */
|
||||
#define DEV_CLOSED 0 /* closed */
|
||||
#define DEV_INIT 1 /* stopped */
|
||||
#define DEV_START 2 /* ready to start */
|
||||
|
@ -62,6 +64,7 @@ struct dev {
|
|||
|
||||
extern struct dev *dev_list;
|
||||
|
||||
void dev_dbg(struct dev *);
|
||||
int dev_init(struct dev *);
|
||||
int dev_run(struct dev *);
|
||||
int dev_ref(struct dev *);
|
||||
|
|
22
aucat/opt.c
22
aucat/opt.c
|
@ -28,7 +28,8 @@
|
|||
struct opt *opt_list = NULL;
|
||||
|
||||
struct opt *
|
||||
opt_new(char *name, struct dev *dev, struct aparams *wpar, struct aparams *rpar,
|
||||
opt_new(char *name, struct dev *dev,
|
||||
struct aparams *wpar, struct aparams *rpar,
|
||||
int maxweight, int mmc, int join, unsigned mode)
|
||||
{
|
||||
struct opt *o, **po;
|
||||
|
@ -54,7 +55,6 @@ opt_new(char *name, struct dev *dev, struct aparams *wpar, struct aparams *rpar,
|
|||
perror("opt_new: malloc");
|
||||
exit(1);
|
||||
}
|
||||
memcpy(o->name, name, len + 1);
|
||||
if (mode & MODE_RECMASK)
|
||||
o->wpar = (mode & MODE_MON) ? *rpar : *wpar;
|
||||
if (mode & MODE_PLAY)
|
||||
|
@ -64,8 +64,10 @@ opt_new(char *name, struct dev *dev, struct aparams *wpar, struct aparams *rpar,
|
|||
o->join = join;
|
||||
o->mode = mode;
|
||||
o->dev = dev;
|
||||
memcpy(o->name, name, len + 1);
|
||||
for (po = &opt_list; *po != NULL; po = &(*po)->next) {
|
||||
if (strcmp(o->name, (*po)->name) == 0) {
|
||||
if (o->dev->num == (*po)->dev->num &&
|
||||
strcmp(o->name, (*po)->name) == 0) {
|
||||
fprintf(stderr, "%s: already defined\n", o->name);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -74,9 +76,9 @@ opt_new(char *name, struct dev *dev, struct aparams *wpar, struct aparams *rpar,
|
|||
*po = o;
|
||||
#ifdef DEBUG
|
||||
if (debug_level >= 2) {
|
||||
dev_dbg(o->dev);
|
||||
dbg_puts(".");
|
||||
dbg_puts(o->name);
|
||||
dbg_puts("@");
|
||||
dbg_puts(o->dev->path);
|
||||
dbg_puts(":");
|
||||
if (o->mode & MODE_REC) {
|
||||
dbg_puts(" rec=");
|
||||
|
@ -115,15 +117,19 @@ opt_new(char *name, struct dev *dev, struct aparams *wpar, struct aparams *rpar,
|
|||
}
|
||||
|
||||
struct opt *
|
||||
opt_byname(char *name)
|
||||
opt_byname(char *name, unsigned num)
|
||||
{
|
||||
struct opt *o;
|
||||
|
||||
for (o = opt_list; o != NULL; o = o->next) {
|
||||
if (o->dev->num != num)
|
||||
continue;
|
||||
if (strcmp(name, o->name) == 0) {
|
||||
#ifdef DEBUG
|
||||
if (debug_level >= 3) {
|
||||
dbg_puts(o->name);
|
||||
dbg_putu(num);
|
||||
dbg_puts(".");
|
||||
dbg_puts(name);
|
||||
dbg_puts(": option found\n");
|
||||
}
|
||||
#endif
|
||||
|
@ -132,6 +138,8 @@ opt_byname(char *name)
|
|||
}
|
||||
#ifdef DEBUG
|
||||
if (debug_level >= 3) {
|
||||
dbg_putu(num);
|
||||
dbg_puts(".");
|
||||
dbg_puts(name);
|
||||
dbg_puts(": option not found\n");
|
||||
}
|
||||
|
|
|
@ -40,6 +40,6 @@ extern struct opt *opt_list;
|
|||
struct opt *opt_new(char *, struct dev *, struct aparams *, struct aparams *,
|
||||
int, int, int, unsigned);
|
||||
int opt_bind(struct opt *);
|
||||
struct opt *opt_byname(char *);
|
||||
struct opt *opt_byname(char *, unsigned);
|
||||
|
||||
#endif /* !defined(OPT_H) */
|
||||
|
|
|
@ -1033,7 +1033,7 @@ sock_hello(struct sock *f)
|
|||
#endif
|
||||
return 0;
|
||||
}
|
||||
f->opt = opt_byname(p->opt);
|
||||
f->opt = opt_byname(p->opt, AMSG_ISSET(p->devnum) ? p->devnum : 0);
|
||||
if (f->opt == NULL)
|
||||
return 0;
|
||||
if (!dev_ref(f->opt->dev))
|
||||
|
|
|
@ -82,8 +82,10 @@ struct amsg {
|
|||
uint16_t mode; /* bitmap of MODE_XXX */
|
||||
#define AMSG_VERSION 5
|
||||
uint8_t version; /* protocol version */
|
||||
uint8_t reserved1[5]; /* for future use */
|
||||
char opt[12]; /* profile name */
|
||||
uint8_t devnum; /* device number */
|
||||
uint32_t _reserved[1]; /* for future use */
|
||||
#define AMSG_OPTMAX 12
|
||||
char opt[AMSG_OPTMAX]; /* profile name */
|
||||
char who[12]; /* hint for leases */
|
||||
} hello;
|
||||
struct amsg_auth {
|
||||
|
|
116
libsndio/aucat.c
116
libsndio/aucat.c
|
@ -186,7 +186,7 @@ aucat_rdata(struct aucat *hdl, void *buf, size_t len, int *eof)
|
|||
hdl->rstate = RSTATE_MSG;
|
||||
hdl->rtodo = sizeof(struct amsg);
|
||||
}
|
||||
DPRINTF("aucat_rdata: read: n = %zd\n", n);
|
||||
DPRINTFN(2, "aucat_rdata: read: n = %zd\n", n);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -228,7 +228,7 @@ aucat_wdata(struct aucat *hdl, const void *buf, size_t len, unsigned wbpf, int *
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
DPRINTF("aucat_wdata: write: n = %zd\n", n);
|
||||
DPRINTFN(2, "aucat_wdata: write: n = %zd\n", n);
|
||||
hdl->wtodo -= n;
|
||||
if (hdl->wtodo == 0) {
|
||||
hdl->wstate = WSTATE_IDLE;
|
||||
|
@ -324,18 +324,13 @@ bad_gen:
|
|||
}
|
||||
|
||||
int
|
||||
aucat_connect_tcp(struct aucat *hdl, char *host, char *unit)
|
||||
aucat_connect_tcp(struct aucat *hdl, char *host, unsigned unit)
|
||||
{
|
||||
int s, error, opt;
|
||||
struct addrinfo *ailist, *ai, aihints;
|
||||
unsigned port;
|
||||
char serv[NI_MAXSERV];
|
||||
|
||||
if (sscanf(unit, "%u", &port) != 1) {
|
||||
DPRINTF("%s: bad unit number\n", unit);
|
||||
return 0;
|
||||
}
|
||||
snprintf(serv, sizeof(serv), "%u", port + AUCAT_PORT);
|
||||
snprintf(serv, sizeof(serv), "%u", unit + AUCAT_PORT);
|
||||
memset(&aihints, 0, sizeof(struct addrinfo));
|
||||
aihints.ai_socktype = SOCK_STREAM;
|
||||
aihints.ai_protocol = IPPROTO_TCP;
|
||||
|
@ -376,7 +371,7 @@ aucat_connect_tcp(struct aucat *hdl, char *host, char *unit)
|
|||
}
|
||||
|
||||
int
|
||||
aucat_connect_un(struct aucat *hdl, char *unit)
|
||||
aucat_connect_un(struct aucat *hdl, unsigned unit)
|
||||
{
|
||||
struct sockaddr_un ca;
|
||||
socklen_t len = sizeof(struct sockaddr_un);
|
||||
|
@ -385,7 +380,7 @@ aucat_connect_un(struct aucat *hdl, char *unit)
|
|||
|
||||
uid = geteuid();
|
||||
snprintf(ca.sun_path, sizeof(ca.sun_path),
|
||||
"/tmp/aucat-%u/%s%s", uid, AUCAT_PATH, unit);
|
||||
"/tmp/aucat-%u/%s%u", uid, AUCAT_PATH, unit);
|
||||
ca.sun_family = AF_UNIX;
|
||||
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (s < 0)
|
||||
|
@ -396,7 +391,7 @@ aucat_connect_un(struct aucat *hdl, char *unit)
|
|||
DPERROR(ca.sun_path);
|
||||
/* try shared server */
|
||||
snprintf(ca.sun_path, sizeof(ca.sun_path),
|
||||
"/tmp/aucat/%s%s", AUCAT_PATH, unit);
|
||||
"/tmp/aucat/%s%u", AUCAT_PATH, unit);
|
||||
while (connect(s, (struct sockaddr *)&ca, len) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
@ -411,42 +406,82 @@ aucat_connect_un(struct aucat *hdl, char *unit)
|
|||
}
|
||||
|
||||
int
|
||||
aucat_open(struct aucat *hdl, const char *str, unsigned mode)
|
||||
aucat_open(struct aucat *hdl, const char *str, unsigned mode, unsigned type)
|
||||
{
|
||||
extern char *__progname;
|
||||
int eof, hashost;
|
||||
char unit[4], *sep, *opt;
|
||||
char host[NI_MAXHOST];
|
||||
int eof;
|
||||
char host[NI_MAXHOST], opt[AMSG_OPTMAX];
|
||||
const char *p;
|
||||
unsigned unit, optlen, hostlen, devnum;
|
||||
|
||||
if (str == NULL)
|
||||
str = "0";
|
||||
sep = strchr(str, '/');
|
||||
if (sep == NULL) {
|
||||
hashost = 0;
|
||||
} else {
|
||||
if (sep - str >= sizeof(host)) {
|
||||
DPRINTF("aucat_open: %s: host too long\n", str);
|
||||
p = str;
|
||||
hostlen = 0;
|
||||
if (*p == '@') {
|
||||
p++;
|
||||
while (*p != '\0' && *p != ',' && *p != '/') {
|
||||
if (hostlen == NI_MAXHOST - 1) {
|
||||
DPRINTF("%s: host too long\n", str);
|
||||
return 0;
|
||||
}
|
||||
host[hostlen++] = *p++;
|
||||
}
|
||||
}
|
||||
host[hostlen++] = 0;
|
||||
unit = 0;
|
||||
if (*p == ',') {
|
||||
/* XXX : use strtol(3) */
|
||||
p++;
|
||||
if (*p < '0' || *p > '9') {
|
||||
DPRINTF("%s: unit expected after ','\n", str);
|
||||
return 0;
|
||||
}
|
||||
memcpy(host, str, sep - str);
|
||||
host[sep - str] = '\0';
|
||||
hashost = 1;
|
||||
str = sep + 1;
|
||||
for (unit = 0; *p >= '0' && *p <= '9'; p++) {
|
||||
unit = 10 * unit + (*p - '0');
|
||||
if (unit >= 16) { /* XXX */
|
||||
DPRINTF("%s: unit too large\n", str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
sep = strchr(str, '.');
|
||||
if (sep == NULL) {
|
||||
opt = "default";
|
||||
strlcpy(unit, str, sizeof(unit));
|
||||
} else {
|
||||
opt = sep + 1;
|
||||
if (sep - str >= sizeof(unit)) {
|
||||
DPRINTF("aucat_init: %s: too long\n", str);
|
||||
devnum = 0;
|
||||
if (*p == '/' || *p == ':') { /* XXX: backward comapt, remove ':' */
|
||||
/* XXX : use strtol(3) */
|
||||
p++;
|
||||
if (*p < '0' || *p > '9') {
|
||||
DPRINTF("%s: devnum expected after '/'\n", str);
|
||||
return 0;
|
||||
}
|
||||
strlcpy(unit, str, opt - str);
|
||||
for (devnum = 0; *p >= '0' && *p <= '9'; p++) {
|
||||
devnum = 10 * devnum + (*p - '0');
|
||||
if (devnum >= 16) { /* XXX */
|
||||
DPRINTF("%s: devnum too large\n", str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
DPRINTF("aucat_init: trying %s -> %s.%s\n", str, unit, opt);
|
||||
if (hashost) {
|
||||
if (type)
|
||||
devnum += 16; /* XXX */
|
||||
optlen = 0;
|
||||
if (*p == '.') {
|
||||
p++;
|
||||
while ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
|
||||
(*p >= '0' && *p <= '9') || *p == '_') {
|
||||
if (optlen == AMSG_OPTMAX - 1) {
|
||||
DPRINTF("%s: opt too long\n", str);
|
||||
return 0;
|
||||
}
|
||||
opt[optlen++] = *p++;
|
||||
}
|
||||
opt[optlen++] = '\0';
|
||||
} else
|
||||
strlcpy(opt, "default", AMSG_OPTMAX);
|
||||
if (*p != '\0') {
|
||||
DPRINTF("%s: junk at end of dev name\n", p);
|
||||
return 0;
|
||||
}
|
||||
DPRINTF("aucat_open: host=%s unit=%u devnum=%u opt=%s\n",
|
||||
host, unit, devnum, opt);
|
||||
if (host[0] != '\0') {
|
||||
if (!aucat_connect_tcp(hdl, host, unit))
|
||||
return 0;
|
||||
} else {
|
||||
|
@ -476,6 +511,7 @@ aucat_open(struct aucat *hdl, const char *str, unsigned mode)
|
|||
hdl->wmsg.cmd = htonl(AMSG_HELLO);
|
||||
hdl->wmsg.u.hello.version = AMSG_VERSION;
|
||||
hdl->wmsg.u.hello.mode = htons(mode);
|
||||
hdl->wmsg.u.hello.devnum = devnum;
|
||||
strlcpy(hdl->wmsg.u.hello.who, __progname,
|
||||
sizeof(hdl->wmsg.u.hello.who));
|
||||
strlcpy(hdl->wmsg.u.hello.opt, opt,
|
||||
|
@ -544,6 +580,6 @@ aucat_revents(struct aucat *hdl, struct pollfd *pfd)
|
|||
{
|
||||
int revents = pfd->revents;
|
||||
|
||||
DPRINTF("aucat_revents: revents: %x\n", revents);
|
||||
DPRINTFN(2, "aucat_revents: revents: %x\n", revents);
|
||||
return revents;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ int aucat_rmsg(struct aucat *, int *);
|
|||
int aucat_wmsg(struct aucat *, int *);
|
||||
size_t aucat_rdata(struct aucat *, void *, size_t, int *);
|
||||
size_t aucat_wdata(struct aucat *, const void *, size_t, unsigned, int *);
|
||||
int aucat_open(struct aucat *, const char *, unsigned);
|
||||
int aucat_open(struct aucat *, const char *, unsigned, unsigned);
|
||||
void aucat_close(struct aucat *, int);
|
||||
int aucat_pollfd(struct aucat *, struct pollfd *, int);
|
||||
int aucat_revents(struct aucat *, struct pollfd *);
|
||||
|
|
|
@ -20,6 +20,12 @@
|
|||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
|
||||
#define DPRINTFN(n, ...) \
|
||||
do { \
|
||||
if (sndio_debug >= (n)) \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define DPRINTF(...) \
|
||||
do { \
|
||||
if (sndio_debug > 0) \
|
||||
|
@ -36,6 +42,7 @@ void sndio_debug_init(void);
|
|||
extern int sndio_debug;
|
||||
#else
|
||||
#define DPRINTF(...) do {} while(0)
|
||||
#define DPRINTFN(...) do {} while(0)
|
||||
#define DPERROR(s) do {} while(0)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -32,15 +32,13 @@
|
|||
#include "mio_priv.h"
|
||||
#include "bsd-compat.h"
|
||||
|
||||
#define ISSEP(c) ((c) == '/' || (c) == ':' || \
|
||||
(c) == '.' || (c) == '@' || (c) == '\0')
|
||||
struct mio_hdl *
|
||||
mio_open(const char *str, unsigned mode, int nbio)
|
||||
{
|
||||
static char prefix_midithru[] = "midithru";
|
||||
static char prefix_rmidi[] = "rmidi";
|
||||
static char prefix_aucat[] = "aucat";
|
||||
struct mio_hdl *hdl;
|
||||
char *sep;
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
#ifdef DEBUG
|
||||
sndio_debug_init();
|
||||
|
@ -50,26 +48,20 @@ mio_open(const char *str, unsigned mode, int nbio)
|
|||
if (str == NULL && !issetugid())
|
||||
str = getenv("MIDIDEVICE");
|
||||
if (str == NULL) {
|
||||
hdl = mio_aucat_open("0", mode, nbio);
|
||||
hdl = mio_aucat_open("/0", mode, nbio, 1);
|
||||
if (hdl != NULL)
|
||||
return hdl;
|
||||
return mio_rmidi_open("0", mode, nbio);
|
||||
return mio_rmidi_open("/0", mode, nbio);
|
||||
}
|
||||
sep = strchr(str, ':');
|
||||
if (sep == NULL) {
|
||||
DPRINTF("mio_open: %s: ':' missing in device name\n", str);
|
||||
return NULL;
|
||||
}
|
||||
len = sep - str;
|
||||
if (len == (sizeof(prefix_midithru) - 1) &&
|
||||
memcmp(str, prefix_midithru, len) == 0)
|
||||
return mio_aucat_open(sep + 1, mode, nbio);
|
||||
if (len == (sizeof(prefix_aucat) - 1) &&
|
||||
memcmp(str, prefix_aucat, len) == 0)
|
||||
return mio_aucat_open(sep + 1, mode, nbio);
|
||||
if (len == (sizeof(prefix_rmidi) - 1) &&
|
||||
memcmp(str, prefix_rmidi, len) == 0)
|
||||
return mio_rmidi_open(sep + 1, mode, nbio);
|
||||
for (len = 0; !ISSEP(str[len]); len++)
|
||||
; /* nothing */
|
||||
if (strncmp("snd", str, len) == 0 ||
|
||||
strncmp("aucat", str, len) == 0)
|
||||
return mio_aucat_open(str + len, mode, nbio, 0);
|
||||
if (strncmp("midithru", str, len) == 0)
|
||||
return mio_aucat_open(str + len, mode, nbio, 1);
|
||||
if (strncmp("rmidi", str, len) == 0)
|
||||
return mio_rmidi_open(str + len, mode, nbio);
|
||||
DPRINTF("mio_open: %s: unknown device type\n", str);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -53,14 +53,14 @@ static struct mio_ops mio_aucat_ops = {
|
|||
};
|
||||
|
||||
struct mio_hdl *
|
||||
mio_aucat_open(const char *str, unsigned mode, int nbio)
|
||||
mio_aucat_open(const char *str, unsigned mode, int nbio, unsigned type)
|
||||
{
|
||||
struct mio_aucat_hdl *hdl;
|
||||
|
||||
hdl = malloc(sizeof(struct mio_aucat_hdl));
|
||||
if (hdl == NULL)
|
||||
return NULL;
|
||||
if (!aucat_open(&hdl->aucat, str, mode))
|
||||
if (!aucat_open(&hdl->aucat, str, mode, type))
|
||||
goto bad;
|
||||
mio_create(&hdl->mio, &mio_aucat_ops, mode, nbio);
|
||||
if (!aucat_setfl(&hdl->aucat, nbio, &hdl->mio.eof))
|
||||
|
|
|
@ -42,7 +42,7 @@ struct mio_ops {
|
|||
};
|
||||
|
||||
struct mio_hdl *mio_rmidi_open(const char *, unsigned, int);
|
||||
struct mio_hdl *mio_aucat_open(const char *, unsigned, int);
|
||||
struct mio_hdl *mio_aucat_open(const char *, unsigned, int, unsigned);
|
||||
void mio_create(struct mio_hdl *, struct mio_ops *, unsigned, int);
|
||||
void mio_destroy(struct mio_hdl *);
|
||||
|
||||
|
|
|
@ -56,6 +56,15 @@ mio_rmidi_open(const char *str, unsigned mode, int nbio)
|
|||
struct mio_rmidi_hdl *hdl;
|
||||
char path[PATH_MAX];
|
||||
|
||||
switch (*str) {
|
||||
case '/':
|
||||
case ':': /* XXX: for backward compat */
|
||||
str++;
|
||||
break;
|
||||
default:
|
||||
DPRINTF("sio_sun_open: %s: '/<devnum>' expected\n", str);
|
||||
return NULL;
|
||||
}
|
||||
hdl = malloc(sizeof(struct mio_rmidi_hdl));
|
||||
if (hdl == NULL)
|
||||
return NULL;
|
||||
|
|
|
@ -34,21 +34,8 @@
|
|||
|
||||
#define SIO_PAR_MAGIC 0x83b905a4
|
||||
|
||||
struct sio_backend {
|
||||
char *prefix;
|
||||
struct sio_hdl *(*open)(const char *, unsigned, int);
|
||||
};
|
||||
|
||||
static struct sio_backend backends[] = {
|
||||
{ "aucat", sio_aucat_open },
|
||||
#ifdef USE_SUN
|
||||
{ "sun", sio_sun_open },
|
||||
#endif
|
||||
#ifdef USE_ALSA
|
||||
{ "alsa", sio_alsa_open },
|
||||
#endif
|
||||
{ NULL, NULL }
|
||||
};
|
||||
#define ISSEP(c) ((c) == '/' || (c) == ':' || \
|
||||
(c) == '.' || (c) == '@' || (c) == '\0')
|
||||
|
||||
void
|
||||
sio_initpar(struct sio_par *par)
|
||||
|
@ -60,10 +47,8 @@ sio_initpar(struct sio_par *par)
|
|||
struct sio_hdl *
|
||||
sio_open(const char *str, unsigned mode, int nbio)
|
||||
{
|
||||
struct sio_backend *b;
|
||||
struct sio_hdl *hdl;
|
||||
char *sep;
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
#ifdef DEBUG
|
||||
sndio_debug_init();
|
||||
|
@ -73,23 +58,32 @@ sio_open(const char *str, unsigned mode, int nbio)
|
|||
if (str == NULL && !issetugid())
|
||||
str = getenv("AUDIODEVICE");
|
||||
if (str == NULL) {
|
||||
for (b = backends; b->prefix != NULL; b++) {
|
||||
hdl = b->open(NULL, mode, nbio);
|
||||
if (hdl != NULL)
|
||||
return hdl;
|
||||
}
|
||||
hdl = sio_aucat_open("/0", mode, nbio);
|
||||
if (hdl != NULL)
|
||||
return hdl;
|
||||
#if defined(USE_SUN)
|
||||
return sio_sun_open("", mode, nbio);
|
||||
#elif defined(USE_ALSA)
|
||||
return sio_alsa_open("/0", mode, nbio);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
sep = strchr(str, ':');
|
||||
if (sep == NULL) {
|
||||
DPRINTF("sio_open: %s: ':' missing in device name\n", str);
|
||||
return NULL;
|
||||
}
|
||||
len = sep - str;
|
||||
for (b = backends; b->prefix != NULL; b++) {
|
||||
if (strlen(b->prefix) == len && memcmp(b->prefix, str, len) == 0)
|
||||
return b->open(sep + 1, mode, nbio);
|
||||
for (len = 0; !ISSEP(str[len]); len++)
|
||||
; /* nothing */
|
||||
if (strncmp("snd", str, len) == 0 ||
|
||||
strncmp("aucat", str, len) == 0)
|
||||
return sio_aucat_open(str + len, mode, nbio);
|
||||
#if defined(USE_ALSA) || defined(USE_SUN)
|
||||
if (strncmp("rsnd", str, len) == 0 ||
|
||||
strncmp("sun", str, len) == 0) {
|
||||
#if defined(USE_SUN)
|
||||
return sio_sun_open(str + len, mode, nbio);
|
||||
#elif defined(USE_ALSA)
|
||||
return sio_sun_open(str + len, mode, nbio);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
DPRINTF("sio_open: %s: unknown device type\n", str);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ sio_aucat_runmsg(struct sio_aucat_hdl *hdl)
|
|||
delta = ntohl(hdl->aucat.rmsg.u.ts.delta);
|
||||
hdl->maxwrite += delta * hdl->wbpf;
|
||||
hdl->delta += delta;
|
||||
DPRINTF("aucat: move = %d, delta = %d, maxwrite = %d\n",
|
||||
DPRINTFN(2, "aucat: move = %d, delta = %d, maxwrite = %d\n",
|
||||
delta, hdl->delta, hdl->maxwrite);
|
||||
if (hdl->delta >= 0) {
|
||||
sio_onmove_cb(&hdl->sio, hdl->delta);
|
||||
|
@ -157,7 +157,7 @@ sio_aucat_open(const char *str, unsigned mode, int nbio)
|
|||
hdl = malloc(sizeof(struct sio_aucat_hdl));
|
||||
if (hdl == NULL)
|
||||
return NULL;
|
||||
if (!aucat_open(&hdl->aucat, str, mode)) {
|
||||
if (!aucat_open(&hdl->aucat, str, mode, 0)) {
|
||||
free(hdl);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -467,7 +467,7 @@ sio_aucat_revents(struct sio_hdl *sh, struct pollfd *pfd)
|
|||
}
|
||||
if (hdl->sio.eof)
|
||||
return POLLHUP;
|
||||
DPRINTF("sio_aucat_revents: %x\n", revents & hdl->events);
|
||||
DPRINTFN(2, "sio_aucat_revents: %x\n", revents & hdl->events);
|
||||
return revents & (hdl->events | POLLHUP);
|
||||
}
|
||||
|
||||
|
|
|
@ -345,8 +345,24 @@ sio_sun_open(const char *str, unsigned mode, int nbio)
|
|||
struct sio_par par;
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (str == NULL)
|
||||
str = "";
|
||||
switch (*str) {
|
||||
case '/':
|
||||
case ':':
|
||||
/* XXX: for backward compat */
|
||||
str++;
|
||||
break;
|
||||
case '\0':
|
||||
/*
|
||||
* XXX: allow ``rsnd'' to map to /dev/audio symlink for
|
||||
* compatibility, remove this once aucat is enabled
|
||||
* by default and default device selection is done
|
||||
* using aucat
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
DPRINTF("sio_sun_open: %s: '/<devnum>' expected\n", str);
|
||||
return NULL;
|
||||
}
|
||||
hdl = malloc(sizeof(struct sio_sun_hdl));
|
||||
if (hdl == NULL)
|
||||
return NULL;
|
||||
|
|
|
@ -68,73 +68,77 @@ From the user's perspective every audio interface, MIDI port,
|
|||
.Xr aucat 1
|
||||
service has a name of the form:
|
||||
.Bd -literal -offset center
|
||||
type:[hostname/]unit[.option]
|
||||
type[@hostname][,unit]/devnum[.option]
|
||||
.Ed
|
||||
.Pp
|
||||
This information is used by audio and MIDI applications to determine
|
||||
how to access the audio device or MIDI port.
|
||||
.Bl -tag -width "option"
|
||||
.Bl -tag -width "hostname"
|
||||
.It Pa type
|
||||
The type of the audio device or MIDI port.
|
||||
Possible values for audio devices are
|
||||
.Pa aucat
|
||||
and
|
||||
.Pa sun ,
|
||||
corresponding to
|
||||
.Xr aucat 1
|
||||
sockets and hardware
|
||||
Possible values are:
|
||||
.Pp
|
||||
.Bl -tag -width "midithru" -offset 3n -compact
|
||||
.It Pa rsnd
|
||||
Raw
|
||||
.Xr audio 4
|
||||
devices.
|
||||
Possible values for MIDI ports are
|
||||
.Pa aucat
|
||||
and
|
||||
.Pa rmidi
|
||||
corresponding to
|
||||
.Xr aucat 1
|
||||
software MIDI thru boxes or control ports and hardware
|
||||
device.
|
||||
.It Pa rmidi
|
||||
Raw
|
||||
.Xr midi 4
|
||||
ports respectively.
|
||||
port.
|
||||
.It Pa snd
|
||||
Audio device exposed by
|
||||
.Xr aucat 1
|
||||
.It Pa midithru
|
||||
MIDI thru box created with
|
||||
.Xr aucat 1
|
||||
.El
|
||||
.It Pa hostname
|
||||
The hostname where the remote
|
||||
The hostname or address where the remote
|
||||
.Xr aucat 1
|
||||
server to connect to is running.
|
||||
.It Pa unit
|
||||
The number of the
|
||||
.Xr aucat 1
|
||||
server to connect to, corresponds to the integer specified unsing the
|
||||
.Fl U
|
||||
option of
|
||||
.Xr aucat 1 .
|
||||
Useful only if multiple
|
||||
.Xr aucat 1
|
||||
servers are running on the same system.
|
||||
.It Pa devnum
|
||||
Device number.
|
||||
For hardware audio or MIDI ports, this corresponds to
|
||||
the character device minor number.
|
||||
For audio devices or MIDI ports created with
|
||||
.Xr aucat 1
|
||||
it corresponds to the server
|
||||
.Em unit
|
||||
number, typically 0.
|
||||
it corresponds to the number of the corresponding
|
||||
.Fl fM
|
||||
option on the command line.
|
||||
.It Pa option
|
||||
Corresponds to the profile string registered using the
|
||||
Corresponds to the sub-device string registered using the
|
||||
.Fl s
|
||||
option of
|
||||
.Xr aucat 1 .
|
||||
Only meaningful for
|
||||
.Pa aucat
|
||||
device types.
|
||||
.El
|
||||
.Pp
|
||||
For example:
|
||||
.Pp
|
||||
.Bl -tag -width "aucat:0.rear" -offset 3n -compact
|
||||
.It Pa sun:0
|
||||
.Bl -tag -width "snd/0.rear" -offset 3n -compact
|
||||
.It Pa rsnd/0
|
||||
First hardware audio device.
|
||||
.It Pa aucat:0
|
||||
Default audio device of the first
|
||||
.Xr aucat 1
|
||||
audio server.
|
||||
.It Pa aucat:0.rear
|
||||
First
|
||||
.Xr aucat 1
|
||||
server;
|
||||
device registered with
|
||||
.Fl s Fa rear .
|
||||
.It Pa rmidi:5
|
||||
.It Pa rmidi/5
|
||||
Hardware MIDI port number 5.
|
||||
.It Pa aucat:0
|
||||
First software MIDI thru box or control port created with
|
||||
.It Pa snd/0
|
||||
First audio device exposed by
|
||||
.Xr aucat 1 .
|
||||
.It Pa snd/0.rear
|
||||
Sub-device registered with
|
||||
.Fl s Fa rear .
|
||||
.It Pa midithru/0
|
||||
First MIDI thru box created with
|
||||
.Xr aucat 1 .
|
||||
.El
|
||||
.Sh AUTHENTICATION
|
||||
|
|
Loading…
Reference in New Issue