switch to type@hostname,unit/num.opt device names

This commit is contained in:
Alexandre Ratchov 2011-11-01 13:02:13 +01:00
parent dc2884ed7d
commit e4ef0dc8d9
18 changed files with 287 additions and 195 deletions

View File

@ -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;

View File

@ -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 ");

View File

@ -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 *);

View File

@ -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");
}

View File

@ -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) */

View File

@ -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))

View File

@ -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 {

View File

@ -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;
}

View File

@ -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 *);

View File

@ -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

View File

@ -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;
}

View File

@ -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))

View File

@ -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 *);

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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