diff options
-rw-r--r-- | usr.bin/aucat/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/aucat/aucat.1 | 26 | ||||
-rw-r--r-- | usr.bin/aucat/aucat.c | 213 | ||||
-rw-r--r-- | usr.bin/aucat/dev.c | 3 | ||||
-rw-r--r-- | usr.bin/aucat/listen.c | 238 | ||||
-rw-r--r-- | usr.bin/aucat/listen.h | 43 | ||||
-rw-r--r-- | usr.bin/aucat/opt.c | 123 | ||||
-rw-r--r-- | usr.bin/aucat/opt.h | 45 | ||||
-rw-r--r-- | usr.bin/aucat/sock.c | 1724 | ||||
-rw-r--r-- | usr.bin/aucat/sock.h | 75 | ||||
-rw-r--r-- | usr.bin/aucat/wav.c | 1 |
11 files changed, 16 insertions, 2479 deletions
diff --git a/usr.bin/aucat/Makefile b/usr.bin/aucat/Makefile index 523da803605..c8606efd625 100644 --- a/usr.bin/aucat/Makefile +++ b/usr.bin/aucat/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.18 2012/11/23 07:03:28 ratchov Exp $ +# $OpenBSD: Makefile,v 1.19 2013/11/12 06:47:34 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 dbg.c + siofile.c miofile.c pipe.c wav.c dbg.c MAN= aucat.1 CFLAGS+= -Wall -Wstrict-prototypes -Wundef -DDEBUG -I${.CURDIR}/../../lib/libsndio LDADD+= -lsndio diff --git a/usr.bin/aucat/aucat.1 b/usr.bin/aucat/aucat.1 index b0b1b7be7fa..1fd8110719a 100644 --- a/usr.bin/aucat/aucat.1 +++ b/usr.bin/aucat/aucat.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: aucat.1,v 1.102 2012/12/03 15:35:25 ratchov Exp $ +.\" $OpenBSD: aucat.1,v 1.103 2013/11/12 06:47:34 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: December 3 2012 $ +.Dd $Mdocdate: November 12 2013 $ .Dt AUCAT 1 .Os .Sh NAME @@ -31,7 +31,6 @@ .Op Fl h Ar fmt .Op Fl i Ar file .Op Fl j Ar flag -.Op Fl m Ar mode .Op Fl o Ar file .Op Fl q Ar port .Op Fl r Ar rate @@ -144,28 +143,7 @@ to any number of MIDI outputs, similarly to a hardware MIDI thru box. Only MIDI ports .Pq Fl q and MIDI files -.Po -.Fl io -preceded by -.Fl m Ar midi -.Pc can be attached to it. -.It Fl m Ar mode -Set the stream mode. -Valid modes are -.Ar play , -.Ar rec , -.Ar mon , -and -.Ar midi , -corresponding to playback, recording, monitoring and MIDI control. -A monitoring stream is a fake recording stream corresponding to -the mix of all playback streams. -Multiple modes can be specified, separated by commas, -but the same stream cannot be used for both recording and monitoring. -The default is -.Ar play , Ns Ar rec , Ns Ar midi -(i.e. full-duplex with MIDI control enabled). .It Fl n Create a loopback pseudo audio device. Send input streams diff --git a/usr.bin/aucat/aucat.c b/usr.bin/aucat/aucat.c index 850c8d2f64e..88be81d6882 100644 --- a/usr.bin/aucat/aucat.c +++ b/usr.bin/aucat/aucat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aucat.c,v 1.141 2012/12/03 15:35:25 ratchov Exp $ */ +/* $OpenBSD: aucat.c,v 1.142 2013/11/12 06:47:34 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -39,30 +39,13 @@ #include "aproc.h" #include "conf.h" #include "dev.h" -#include "listen.h" #include "midi.h" -#include "opt.h" #include "wav.h" #ifdef DEBUG #include "dbg.h" #endif -/* - * unprivileged user name - */ -#ifndef SNDIO_USER -#define SNDIO_USER "_sndio" -#endif - -/* - * priority when run as root - */ -#ifndef SNDIO_PRIO -#define SNDIO_PRIO (-20) -#endif - #define PROG_AUCAT "aucat" -#define PROG_SNDIOD "sndiod" /* * sample rate if no ``-r'' is used @@ -85,29 +68,16 @@ #define DEFAULT_BUFSZ 7860 #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 volatile sig_atomic_t quit_flag = 0; -char aucat_usage[] = "usage: " PROG_AUCAT " [-dMn] " +char aucat_usage[] = "usage: " PROG_AUCAT " [-dMn]\n\t" "[-C min:max] [-c min:max] [-e enc] [-f device]\n\t" - "[-h fmt] [-i file] [-j flag] [-m mode] [-o file] [-q port]\n\t" + "[-h fmt] [-i file] [-j flag] [-o file] [-q port]\n\t" "[-r rate] [-t mode] [-v volume] [-w flag] [-x policy]\n"; -char sndiod_usage[] = "usage: " PROG_SNDIOD " [-dM] [-a flag] [-b nframes] " - "[-C min:max] [-c min:max] [-e enc]\n\t" - "[-f device] [-j flag] [-L addr] [-m mode] [-q port] [-r rate]\n\t" - "[-s name] [-t mode] [-U unit] [-v volume] [-w flag] [-x policy]\n\t" - "[-z nframes]\n"; - /* * SIGINT handler, it raises the quit flag. If the flag is already set, * that means that the last SIGINT was not handled, because the process @@ -219,34 +189,6 @@ opt_xrun(void) errx(1, "%s: bad underrun/overrun policy", optarg); } -unsigned int -opt_mode(void) -{ - unsigned int mode = 0; - char *p = optarg; - size_t len; - - for (p = optarg; *p != '\0'; p++) { - len = strcspn(p, ","); - if (strncmp("play", p, len) == 0) { - mode |= MODE_PLAY; - } else if (strncmp("rec", p, len) == 0) { - mode |= MODE_REC; - } else if (strncmp("mon", p, len) == 0) { - mode |= MODE_MON; - } else if (strncmp("midi", p, len) == 0) { - mode |= MODE_MIDIMASK; - } else - errx(1, "%s: bad mode", optarg); - p += len; - if (*p == '\0') - break; - } - if (mode == 0) - errx(1, "empty mode"); - return mode; -} - void setsig(void) { @@ -294,46 +236,6 @@ unsetsig(void) err(1, "unsetsig(int): sigaction failed\n"); } -void -getbasepath(char *base, size_t size) -{ - uid_t uid; - struct stat sb; - mode_t mask; - - uid = geteuid(); - if (uid == 0) { - mask = 022; - snprintf(base, PATH_MAX, "/tmp/aucat"); - } else { - mask = 077; - snprintf(base, PATH_MAX, "/tmp/aucat-%u", uid); - } - if (mkdir(base, 0777 & ~mask) < 0) { - if (errno != EEXIST) - err(1, "mkdir(\"%s\")", base); - } - if (stat(base, &sb) < 0) - err(1, "stat(\"%s\")", base); - if (sb.st_uid != uid || (sb.st_mode & mask) != 0) - errx(1, "%s has wrong permissions", base); -} - -void -privdrop(void) -{ - struct passwd *pw; - - if ((pw = getpwnam(SNDIO_USER)) == NULL) - errx(1, "unknown user %s", SNDIO_USER); - if (setpriority(PRIO_PROCESS, 0, SNDIO_PRIO) < 0) - err(1, "setpriority"); - if (setgroups(1, &pw->pw_gid) || - setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || - setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) - err(1, "cannot drop privileges"); -} - struct dev * mkdev(char *path, int mode, int bufsz, int round, int hold, int autovol) { @@ -364,37 +266,15 @@ mkdev(char *path, int mode, int bufsz, int round, int hold, int autovol) return d; } -struct opt * -mkopt(char *path, struct dev *d, struct aparams *rpar, struct aparams *ppar, - int mode, int vol, int mmc, int join) -{ - struct opt *o; - - if (d->reqmode & MODE_LOOP) - errx(1, "%s: can't attach to loopback", path); - if (d->reqmode & MODE_THRU) - mode = MODE_MIDIMASK; - if (!rpar->rate) - ppar->rate = rpar->rate = DEFAULT_RATE; - o = opt_new(path, d, rpar, ppar, MIDI_TO_ADATA(vol), mmc, join, mode); - if (o == NULL) - errx(1, "%s: couldn't create subdev", path); - dev_adjpar(d, o->mode, rpar, ppar); - return o; -} - int main(int argc, char **argv) { - char *prog, *optstr, *usagestr; int c, background, unit, active; - char base[PATH_MAX], path[PATH_MAX]; unsigned int mode, hdr, xrun, rate, join, mmc, vol; unsigned int hold, autovol, bufsz, round; const char *str; struct aparams ppar, rpar; struct dev *d, *dnext; - struct listen *l; struct wav *w; /* @@ -421,23 +301,8 @@ main(int argc, char **argv) setsig(); filelist_init(); - prog = strrchr(argv[0], '/'); - if (prog == NULL) - prog = argv[0]; - else - prog++; - if (strcmp(prog, PROG_AUCAT) == 0) { - optstr = "a:b:c:C:de:f:h:i:j:L:m:Mno:q:r:s:t:U:v:w:x:z:"; - usagestr = aucat_usage; - hold = 1; - } else if (strcmp(prog, PROG_SNDIOD) == 0) { - optstr = "a:b:c:C:de:f:j:L:m:Mq:r:s:t:U:v:w:x:z:"; - usagestr = sndiod_usage; - background = 1; - } else - errx(1, "%s: can't determine program to run", prog); - - while ((c = getopt(argc, argv, optstr)) != -1) { + while ((c = getopt(argc, argv, + "a:b:c:C:de:f:h:i:j:Mno:q:r:t:v:w:x:z:")) != -1) { switch (c) { case 'd': #ifdef DEBUG @@ -446,19 +311,6 @@ main(int argc, char **argv) #endif background = 0; break; - case 'U': - if (listen_list) - errx(1, "-U must come before -L"); - unit = strtonum(optarg, 0, MIDI_MAXCTL, &str); - if (str) - errx(1, "%s: unit number is %s", optarg, str); - break; - case 'L': - listen_new_tcp(optarg, AUCAT_PORT + unit); - break; - case 'm': - mode = opt_mode(); - break; case 'h': hdr = opt_hdr(); break; @@ -510,23 +362,12 @@ main(int argc, char **argv) errx(1, "%s: couldn't create stream", optarg); dev_adjpar(d, w->mode, &w->hpar, NULL); break; - case 's': - if ((d = dev_list) == NULL) { - d = mkdev(DEFAULT_DEV, 0, bufsz, round, - hold, autovol); - } - mkopt(optarg, d, &rpar, &ppar, mode, vol, mmc, join); - /* XXX: set device rate, if never set */ - break; case 'q': d = mkdev(NULL, mode, bufsz, round, 1, autovol); if (!devctl_add(d, optarg, MODE_MIDIMASK)) errx(1, "%s: can't open port", optarg); d->reqmode |= MODE_MIDIMASK; break; - case 'a': - hold = opt_onoff(); - break; case 'w': autovol = opt_onoff(); break; @@ -550,41 +391,27 @@ main(int argc, char **argv) mkdev("midithru", MODE_THRU, 0, 0, hold, 0); break; default: - fputs(usagestr, stderr); + fputs(aucat_usage, stderr); exit(1); } } argc -= optind; argv += optind; if (argc > 0) { - fputs(usagestr, stderr); + fputs(aucat_usage, stderr); exit(1); } if (wav_list) { - if (opt_list || listen_list) - errx(1, "-io not allowed in server mode"); if ((d = dev_list) && d->next) - errx(1, "only one device allowed in non-server mode"); + errx(1, "only one device allowed"); 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; } } else { - if (dev_list == NULL) - mkdev(DEFAULT_DEV, 0, bufsz, round, hold, autovol); - for (d = dev_list; d != NULL; d = d->next) { - if (opt_byname("default", d->num)) - continue; - mkopt("default", d, &rpar, &ppar, mode, vol, mmc, join); - } - } - if (opt_list) { - getbasepath(base, sizeof(base)); - snprintf(path, PATH_MAX, "%s/%s%u", base, AUCAT_PATH, unit); - listen_new_un(path); - if (geteuid() == 0) - privdrop(); + fputs(aucat_usage, stderr); + exit(1); } for (w = wav_list; w != NULL; w = w->next) { if (!wav_init(w)) @@ -596,18 +423,6 @@ main(int argc, char **argv) if (d->autostart && (d->mode & MODE_AUDIOMASK)) dev_mmcstart(d); } - for (l = listen_list; l != NULL; l = l->next) { - if (!listen_init(l)) - exit(1); - } - if (background) { -#ifdef DEBUG - debug_level = 0; - dbg_flush(); -#endif - if (daemon(0, 0) < 0) - err(1, "daemon"); - } /* * Loop, start audio. @@ -625,14 +440,12 @@ main(int argc, char **argv) } if (dev_list == NULL) break; - if (!opt_list && !active) + if (!active) break; if (!file_poll()) break; } fatal: - while (listen_list != NULL) - file_close(&listen_list->file); /* * give a chance to drain @@ -645,10 +458,6 @@ main(int argc, char **argv) while (dev_list) dev_del(dev_list); filelist_done(); - if (opt_list) { - if (rmdir(base) < 0 && errno != ENOTEMPTY && errno != EPERM) - warn("rmdir(\"%s\")", base); - } unsetsig(); return 0; } diff --git a/usr.bin/aucat/dev.c b/usr.bin/aucat/dev.c index da403fabb1e..21351220a65 100644 --- a/usr.bin/aucat/dev.c +++ b/usr.bin/aucat/dev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dev.c,v 1.82 2012/09/25 20:12:34 ratchov Exp $ */ +/* $OpenBSD: dev.c,v 1.83 2013/11/12 06:47:34 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -75,7 +75,6 @@ #include "miofile.h" #include "siofile.h" #include "midi.h" -#include "opt.h" #ifdef DEBUG #include "dbg.h" #endif diff --git a/usr.bin/aucat/listen.c b/usr.bin/aucat/listen.c deleted file mode 100644 index b54ccc0c007..00000000000 --- a/usr.bin/aucat/listen.c +++ /dev/null @@ -1,238 +0,0 @@ -/* $OpenBSD: listen.c,v 1.21 2013/03/13 08:28:34 ratchov Exp $ */ -/* - * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/signal.h> -#include <sys/stat.h> -#include <sys/un.h> - -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <netdb.h> - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <poll.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "conf.h" -#include "listen.h" -#include "sock.h" -#include "dbg.h" - -struct fileops listen_ops = { - "listen", - sizeof(struct listen), - listen_close, - NULL, /* read */ - NULL, /* write */ - NULL, /* start */ - NULL, /* stop */ - listen_nfds, - listen_pollfd, - listen_revents -}; - -struct listen *listen_list = NULL; - -void -listen_new_un(char *path) -{ - int sock, oldumask; - struct sockaddr_un sockname; - struct listen *f; - - sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - err(1, "socket"); - if (unlink(path) < 0 && errno != ENOENT) { - perror("unlink"); - goto bad_close; - } - sockname.sun_family = AF_UNIX; - strlcpy(sockname.sun_path, path, sizeof(sockname.sun_path)); - oldumask = umask(0111); - if (bind(sock, (struct sockaddr *)&sockname, - sizeof(struct sockaddr_un)) < 0) { - perror("bind"); - goto bad_close; - } - umask(oldumask); - f = (struct listen *)file_new(&listen_ops, path, 1); - if (f == NULL) - goto bad_close; - f->path = strdup(path); - if (f->path == NULL) - err(1, "strdup"); - f->fd = sock; - f->next = listen_list; - listen_list = f; - return; - bad_close: - close(sock); - exit(1); -} - -void -listen_new_tcp(char *addr, unsigned int port) -{ - char *host, serv[sizeof(unsigned int) * 3 + 1]; - struct addrinfo *ailist, *ai, aihints; - struct listen *f; - int s, error, opt = 1, n = 0; - - /* - * obtain a list of possible addresses for the host/port - */ - memset(&aihints, 0, sizeof(struct addrinfo)); - snprintf(serv, sizeof(serv), "%u", port); - host = strcmp(addr, "-") == 0 ? NULL : addr; - aihints.ai_flags |= AI_PASSIVE; - aihints.ai_socktype = SOCK_STREAM; - aihints.ai_protocol = IPPROTO_TCP; - error = getaddrinfo(host, serv, &aihints, &ailist); - if (error) - errx(1, "%s: %s", addr, gai_strerror(error)); - - /* - * for each address, try create a listening socket bound on - * that address - */ - for (ai = ailist; ai != NULL; ai = ai->ai_next) { - s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (s < 0) { - perror("socket"); - continue; - } - opt = 1; - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) < 0) { - perror("setsockopt"); - goto bad_close; - } - if (bind(s, ai->ai_addr, ai->ai_addrlen) < 0) { - perror("bind"); - goto bad_close; - } - f = (struct listen *)file_new(&listen_ops, addr, 1); - if (f == NULL) { - bad_close: - close(s); - continue; - } - f->path = NULL; - f->fd = s; - f->next = listen_list; - listen_list = f; - n++; - } - freeaddrinfo(ailist); - if (n == 0) - exit(1); -} - -int -listen_init(struct listen *f) -{ - if (listen(f->fd, 1) < 0) { - perror("listen"); - return 0; - } - return 1; -} - -int -listen_nfds(struct file *f) { - return 1; -} - -int -listen_pollfd(struct file *file, struct pollfd *pfd, int events) -{ - struct listen *f = (struct listen *)file; - - if (file_slowaccept) - return 0; - pfd->fd = f->fd; - pfd->events = POLLIN; - return 1; -} - -int -listen_revents(struct file *file, struct pollfd *pfd) -{ - struct listen *f = (struct listen *)file; - struct sockaddr caddr; - socklen_t caddrlen; - int sock, opt; - - if (pfd->revents & POLLIN) { - caddrlen = sizeof(caddrlen); - while ((sock = accept(f->fd, &caddr, &caddrlen)) < 0) { - if (errno == EINTR) - continue; - if (errno == ENFILE || errno == EMFILE) - file_slowaccept = 1; - else if (errno != ECONNABORTED && errno != EWOULDBLOCK) - perror("accept"); - return 0; - } - if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { - perror("fcntl(sock, O_NONBLOCK)"); - close(sock); - return 0; - } - if (f->path == NULL) { - opt = 1; - if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, - &opt, sizeof(int)) < 0) { - perror("setsockopt"); - close(sock); - return 0; - } - } - if (sock_new(&sock_ops, sock) == NULL) { - close(sock); - return 0; - } - } - return 0; -} - -void -listen_close(struct file *file) -{ - struct listen *f = (struct listen *)file, **pf; - - if (f->path != NULL) { - unlink(f->path); - free(f->path); - } - close(f->fd); - for (pf = &listen_list; *pf != f; pf = &(*pf)->next) { -#ifdef DEBUG - if (*pf == NULL) { - dbg_puts("listen_close: not on list\n"); - dbg_panic(); - } -#endif - } - *pf = f->next; -} diff --git a/usr.bin/aucat/listen.h b/usr.bin/aucat/listen.h deleted file mode 100644 index 88de0278339..00000000000 --- a/usr.bin/aucat/listen.h +++ /dev/null @@ -1,43 +0,0 @@ -/* $OpenBSD: listen.h,v 1.9 2012/04/11 06:05:43 ratchov Exp $ */ -/* - * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef LISTEN_H -#define LISTEN_H - -#include <sys/types.h> - -#include "aparams.h" -#include "file.h" - -struct listen { - struct file file; - struct listen *next; - char *path; - int fd; -}; - -extern struct listen *listen_list; - -void listen_new_un(char *); -void listen_new_tcp(char *, unsigned int); -int listen_init(struct listen *); -int listen_nfds(struct file *); -int listen_pollfd(struct file *, struct pollfd *, int); -int listen_revents(struct file *, struct pollfd *); -void listen_close(struct file *); -void listen_closeall(void); - -#endif /* !defined(LISTEN_H) */ diff --git a/usr.bin/aucat/opt.c b/usr.bin/aucat/opt.c deleted file mode 100644 index b0b09538cdb..00000000000 --- a/usr.bin/aucat/opt.c +++ /dev/null @@ -1,123 +0,0 @@ -/* $OpenBSD: opt.c,v 1.14 2012/06/27 06:53:13 ratchov Exp $ */ -/* - * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include <err.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "dev.h" -#include "conf.h" -#include "opt.h" -#ifdef DEBUG -#include "dbg.h" -#endif - -struct opt *opt_list = NULL; - -struct opt * -opt_new(char *name, struct dev *dev, - struct aparams *wpar, struct aparams *rpar, - int maxweight, int mmc, int join, unsigned int mode) -{ - struct opt *o, **po; - unsigned int len; - char c; - - for (len = 0; name[len] != '\0'; len++) { - if (len == OPT_NAMEMAX) - errx(1, "%s: name too long", name); - c = name[len]; - if ((c < 'a' || c > 'z') && - (c < 'A' || c > 'Z')) - errx(1, "%s: '%c' not allowed", name, c); - } - o = malloc(sizeof(struct opt)); - if (o == NULL) - err(1, "opt_new: malloc"); - if (mode & MODE_RECMASK) - o->wpar = (mode & MODE_MON) ? *rpar : *wpar; - if (mode & MODE_PLAY) - o->rpar = *rpar; - o->maxweight = maxweight; - o->mmc = mmc; - 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 (o->dev->num == (*po)->dev->num && - strcmp(o->name, (*po)->name) == 0) - errx(1, "%s: already defined", o->name); - } - o->next = NULL; - *po = o; -#ifdef DEBUG - if (debug_level >= 2) { - dev_dbg(o->dev); - dbg_puts("."); - dbg_puts(o->name); - dbg_puts(":"); - if (o->mode & MODE_REC) { - dbg_puts(" rec="); - dbg_putu(o->wpar.cmin); - dbg_puts(":"); - dbg_putu(o->wpar.cmax); - } - if (o->mode & MODE_PLAY) { - dbg_puts(" play="); - dbg_putu(o->rpar.cmin); - dbg_puts(":"); - dbg_putu(o->rpar.cmax); - dbg_puts(" vol="); - dbg_putu(o->maxweight); - } - if (o->mode & MODE_MON) { - dbg_puts(" mon="); - dbg_putu(o->wpar.cmin); - dbg_puts(":"); - dbg_putu(o->wpar.cmax); - } - if (o->mode & (MODE_RECMASK | MODE_PLAY)) { - if (o->mmc) - dbg_puts(" mmc"); - if (o->join) - dbg_puts(" join"); - } - if (o->mode & MODE_MIDIIN) - dbg_puts(" midi/in"); - if (o->mode & MODE_MIDIOUT) - dbg_puts(" midi/out"); - dbg_puts("\n"); - } -#endif - return o; -} - -struct opt * -opt_byname(char *name, unsigned int 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) - return o; - } - return NULL; -} - diff --git a/usr.bin/aucat/opt.h b/usr.bin/aucat/opt.h deleted file mode 100644 index 934bd1f1728..00000000000 --- a/usr.bin/aucat/opt.h +++ /dev/null @@ -1,45 +0,0 @@ -/* $OpenBSD: opt.h,v 1.12 2012/04/11 06:05:43 ratchov Exp $ */ -/* - * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef OPT_H -#define OPT_H - -#include <sys/queue.h> -#include "aparams.h" - -struct dev; - -struct opt { - struct opt *next; -#define OPT_NAMEMAX 11 - char name[OPT_NAMEMAX + 1]; - int maxweight; /* max dynamic range for clients */ - struct aparams wpar; /* template for clients write params */ - struct aparams rpar; /* template for clients read params */ - int mmc; /* true if MMC control enabled */ - int join; /* true if join/expand enabled */ - unsigned int mode; /* bitmap of MODE_XXX */ - struct dev *dev; /* device to which we're attached */ -}; - -extern struct opt *opt_list; - -struct opt *opt_new(char *, struct dev *, struct aparams *, struct aparams *, - int, int, int, unsigned int); -int opt_bind(struct opt *); -struct opt *opt_byname(char *, unsigned int); - -#endif /* !defined(OPT_H) */ diff --git a/usr.bin/aucat/sock.c b/usr.bin/aucat/sock.c deleted file mode 100644 index b2b9c09f9e5..00000000000 --- a/usr.bin/aucat/sock.c +++ /dev/null @@ -1,1724 +0,0 @@ -/* $OpenBSD: sock.c,v 1.67 2012/11/23 06:40:26 ratchov Exp $ */ -/* - * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "abuf.h" -#include "aproc.h" -#include "conf.h" -#include "dev.h" -#include "midi.h" -#include "opt.h" -#include "sock.h" -#ifdef DEBUG -#include "dbg.h" -#endif - -void sock_attach(struct sock *, int); -int sock_read(struct sock *); -int sock_write(struct sock *); -int sock_execmsg(struct sock *); -void sock_reset(struct sock *); -void sock_close(struct file *); - -struct fileops sock_ops = { - "sock", - sizeof(struct sock), - sock_close, - pipe_read, - pipe_write, - NULL, /* start */ - NULL, /* stop */ - pipe_nfds, - pipe_pollfd, - pipe_revents -}; - -#ifdef DEBUG -void -sock_dbg(struct sock *f) -{ - static char *pstates[] = { - "aut", "hel", "ini", "sta", "rdy", "run", "stp", "mid" - }; - static char *rstates[] = { "rdat", "rmsg", "rret" }; - static char *wstates[] = { "widl", "wmsg", "wdat" }; - - if (f->slot >= 0) { - dbg_puts(f->dev->slot[f->slot].name); - dbg_putu(f->dev->slot[f->slot].unit); - } else - dbg_puts(f->pipe.file.name); - dbg_puts("/"); - dbg_puts(pstates[f->pstate]); - dbg_puts("|"); - dbg_puts(rstates[f->rstate]); - dbg_puts("|"); - dbg_puts(wstates[f->wstate]); -} -#endif - -void sock_setvol(void *, unsigned int); -void sock_startreq(void *); -void sock_stopreq(void *); -void sock_quitreq(void *); -void sock_locreq(void *, unsigned int); - -struct ctl_ops ctl_sockops = { - sock_setvol, - sock_startreq, - sock_stopreq, - sock_locreq, - sock_quitreq -}; - -unsigned int sock_sesrefs = 0; /* connections to the session */ -uint8_t sock_sescookie[AMSG_COOKIELEN]; /* owner of the session */ - -void -sock_close(struct file *arg) -{ - struct sock *f = (struct sock *)arg; - - if (f->pstate != SOCK_AUTH) - sock_sesrefs--; - pipe_close(&f->pipe.file); - if (f->dev) { - dev_unref(f->dev); - f->dev = NULL; - } -} - -void -rsock_done(struct aproc *p) -{ - struct sock *f = (struct sock *)p->u.io.file; - - if (f == NULL) - return; - sock_reset(f); - f->pipe.file.rproc = NULL; - if (f->pipe.file.wproc) { - if (f->slot >= 0) - dev_slotdel(f->dev, f->slot); - aproc_del(f->pipe.file.wproc); - file_del(&f->pipe.file); - } - p->u.io.file = NULL; -} - -int -rsock_in(struct aproc *p, struct abuf *ibuf_dummy) -{ - struct sock *f = (struct sock *)p->u.io.file; - struct abuf *obuf; - - if (!sock_read(f)) - return 0; - obuf = LIST_FIRST(&p->outs); - if (obuf && f->pstate >= SOCK_RUN) { - if (!abuf_flush(obuf)) - return 0; - } - return 1; -} - -int -rsock_out(struct aproc *p, struct abuf *obuf) -{ - struct sock *f = (struct sock *)p->u.io.file; - - if (f->pipe.file.state & FILE_RINUSE) - return 0; - - /* - * When calling sock_read(), we may receive a ``STOP'' command, - * and detach ``obuf''. In this case, there's no more caller and - * we'll stop processing further messages, resulting in a deadlock. - * The solution is to iterate over sock_read() in order to - * consume all messages(). - */ - for (;;) { - if (!sock_read(f)) - return 0; - } - return 1; -} - -void -rsock_eof(struct aproc *p, struct abuf *ibuf_dummy) -{ - aproc_del(p); -} - -void -rsock_hup(struct aproc *p, struct abuf *ibuf) -{ - aproc_del(p); -} - -void -rsock_opos(struct aproc *p, struct abuf *obuf, int delta) -{ - struct sock *f = (struct sock *)p->u.io.file; - - if (f->mode & MODE_RECMASK) - return; - - f->delta += delta; -#ifdef DEBUG - if (debug_level >= 4) { - aproc_dbg(p); - dbg_puts(": moved to delta = "); - dbg_puti(f->delta); - dbg_puts("\n"); - } -#endif - f->tickpending++; - for (;;) { - if (!sock_write(f)) - break; - } -} - -struct aproc_ops rsock_ops = { - "rsock", - rsock_in, - rsock_out, - rsock_eof, - rsock_hup, - NULL, /* newin */ - NULL, /* newout */ - NULL, /* ipos */ - rsock_opos, - rsock_done -}; - -void -wsock_done(struct aproc *p) -{ - struct sock *f = (struct sock *)p->u.io.file; - - if (f == NULL) - return; - sock_reset(f); - f->pipe.file.wproc = NULL; - if (f->pipe.file.rproc) { - if (f->slot >= 0) - dev_slotdel(f->dev, f->slot); - aproc_del(f->pipe.file.rproc); - file_del(&f->pipe.file); - } - p->u.io.file = NULL; -} - -int -wsock_in(struct aproc *p, struct abuf *ibuf) -{ - struct sock *f = (struct sock *)p->u.io.file; - - if (f->pipe.file.state & FILE_WINUSE) - return 0; - /* - * See remark in rsock_out(). - */ - for (;;) { - if (!sock_write(f)) - return 0; - } - return 1; -} - -int -wsock_out(struct aproc *p, struct abuf *obuf_dummy) -{ - struct abuf *ibuf = LIST_FIRST(&p->ins); - struct sock *f = (struct sock *)p->u.io.file; - - if (ibuf) { - if (!abuf_fill(ibuf)) - return 0; - } - if (!sock_write(f)) - return 0; - return 1; -} - -void -wsock_eof(struct aproc *p, struct abuf *obuf) -{ - aproc_del(p); -} - -void -wsock_hup(struct aproc *p, struct abuf *obuf_dummy) -{ - aproc_del(p); -} - -void -wsock_ipos(struct aproc *p, struct abuf *obuf, int delta) -{ - struct sock *f = (struct sock *)p->u.io.file; - - if (!(f->mode & MODE_RECMASK)) - return; - - f->delta += delta; -#ifdef DEBUG - if (debug_level >= 4) { - aproc_dbg(p); - dbg_puts(": moved to delta = "); - dbg_puti(f->delta); - dbg_puts("\n"); - } -#endif - f->tickpending++; - for (;;) { - if (!sock_write(f)) - break; - } -} - -struct aproc_ops wsock_ops = { - "wsock", - wsock_in, - wsock_out, - wsock_eof, - wsock_hup, - NULL, /* newin */ - NULL, /* newout */ - wsock_ipos, - NULL, /* opos */ - wsock_done -}; - -/* - * Initialise socket in the SOCK_HELLO state with default - * parameters. - */ -struct sock * -sock_new(struct fileops *ops, int fd) -{ - struct aproc *rproc, *wproc; - struct sock *f; - - f = (struct sock *)pipe_new(ops, fd, "sock"); - if (f == NULL) { - close(fd); - return NULL; - } - f->pstate = SOCK_AUTH; - f->mode = 0; - f->opt = NULL; - f->dev = NULL; - f->xrun = XRUN_IGNORE; - f->delta = 0; - f->tickpending = 0; - f->fillpending = 0; - f->vol = f->lastvol = MIDI_MAXCTL; - f->slot = -1; - - wproc = aproc_new(&wsock_ops, f->pipe.file.name); - wproc->u.io.file = &f->pipe.file; - wproc->u.io.partial = 0; - f->pipe.file.wproc = wproc; - f->wstate = SOCK_WIDLE; - f->wtodo = 0xdeadbeef; - - rproc = aproc_new(&rsock_ops, f->pipe.file.name); - rproc->u.io.file = &f->pipe.file; - rproc->u.io.partial = 0; - f->pipe.file.rproc = rproc; - f->rstate = SOCK_RMSG; - f->rtodo = sizeof(struct amsg); - return f; -} - -/* - * Free buffers. - */ -void -sock_freebuf(struct sock *f) -{ - struct abuf *rbuf, *wbuf; - - f->pstate = SOCK_INIT; -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": freeing buffers\n"); - } -#endif - wbuf = LIST_FIRST(&f->pipe.file.wproc->ins); - rbuf = LIST_FIRST(&f->pipe.file.rproc->outs); - if (rbuf || wbuf) - dev_slotstop(f->dev, f->slot); - if (rbuf) - abuf_eof(rbuf); - if (wbuf) - abuf_hup(wbuf); - f->tickpending = 0; - f->fillpending = 0; -} - -/* - * Allocate buffers, so client can start filling write-end. - */ -void -sock_allocbuf(struct sock *f) -{ - struct abuf *rbuf = NULL, *wbuf = NULL; - unsigned int bufsz; - - bufsz = f->bufsz + f->dev->bufsz / f->dev->round * f->round; - f->pstate = SOCK_START; - if (f->mode & MODE_PLAY) { - rbuf = abuf_new(bufsz, &f->rpar); - aproc_setout(f->pipe.file.rproc, rbuf); - if (!ABUF_WOK(rbuf) || (f->pipe.file.state & FILE_EOF)) - f->pstate = SOCK_READY; - f->fillpending = bufsz; - f->rmax = 0; - } - if (f->mode & MODE_RECMASK) { - wbuf = abuf_new(bufsz, &f->wpar); - aproc_setin(f->pipe.file.wproc, wbuf); - f->walign = f->round; - f->wmax = 0; - } - f->delta = 0; - f->tickpending = 0; -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": allocating "); - dbg_putu(f->bufsz); - dbg_puts("/"); - dbg_putu(bufsz); - dbg_puts(" fr buffers, rmax = "); - dbg_putu(f->rmax); - dbg_puts("\n"); - } -#endif - if (f->mode & MODE_PLAY) { - f->pstate = SOCK_START; - } else { - f->pstate = SOCK_READY; - if (dev_slotstart(f->dev, f->slot)) - (void)sock_attach(f, 0); - } -} - -/* - * Set volume. Callback invoked when volume is modified externally - */ -void -sock_setvol(void *arg, unsigned int vol) -{ - struct sock *f = (struct sock *)arg; - struct abuf *rbuf; - - f->vol = vol; - rbuf = LIST_FIRST(&f->pipe.file.rproc->outs); - if (!rbuf) { -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": no read buffer to set volume yet\n"); - } -#endif - return; - } - dev_setvol(f->dev, rbuf, MIDI_TO_ADATA(vol)); -} - -/* - * Attach the stream. Callback invoked when MMC start - */ -void -sock_startreq(void *arg) -{ - struct sock *f = (struct sock *)arg; - -#ifdef DEBUG - if (f->pstate != SOCK_READY) { - sock_dbg(f); - dbg_puts(": not in READY state\n"); - dbg_panic(); - } -#endif - (void)sock_attach(f, 0); -} - -/* - * Callback invoked by MMC stop - */ -void -sock_stopreq(void *arg) -{ -#ifdef DEBUG - struct sock *f = (struct sock *)arg; - - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": ignored STOP signal\n"); - } -#endif -} - -/* - * Callback invoked by MMC relocate, ignored - */ -void -sock_locreq(void *arg, unsigned int mmcpos) -{ -#ifdef DEBUG - struct sock *f = (struct sock *)arg; - - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": ignored RELOCATE signal\n"); - } -#endif -} - -/* - * 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 the device - */ -void -sock_attach(struct sock *f, int force) -{ - struct abuf *rbuf, *wbuf; - unsigned int rch, wch; - - rbuf = LIST_FIRST(&f->pipe.file.rproc->outs); - wbuf = LIST_FIRST(&f->pipe.file.wproc->ins); - - /* - * If in SOCK_START state, dont attach until - * the buffer isn't completely filled. - */ - if (!force && rbuf && ABUF_WOK(rbuf)) - return; - - /* - * start the device (dev_getpos() and dev_attach() must - * be called on a started device - */ - dev_wakeup(f->dev); - - /* - * get the current position, the origin is when - * the first sample is played/recorded - */ - f->delta = dev_getpos(f->dev) * - (int)f->round / (int)f->dev->round; - f->pstate = SOCK_RUN; -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": attaching at "); - dbg_puti(f->delta); - dbg_puts("fillpending = "); - dbg_puti(f->fillpending); - dbg_puts("\n"); - } -#endif - /* - * We dont check whether the device is dying, - * because dev_xxx() functions are supposed to - * work (i.e., not to crash) - */ - if (f->opt->join) { - rch = f->opt->rpar.cmax - f->opt->rpar.cmin + 1; - wch = f->opt->wpar.cmax - f->opt->wpar.cmin + 1; - } else - rch = wch = 0; - dev_attach(f->dev, f->pipe.file.name, f->mode, - rbuf, &f->rpar, rch, wbuf, &f->wpar, wch, - f->xrun, f->opt->maxweight); - if (f->mode & MODE_PLAY) - dev_setvol(f->dev, rbuf, MIDI_TO_ADATA(f->vol)); -} - -void -sock_reset(struct sock *f) -{ - switch (f->pstate) { - case SOCK_START: - case SOCK_READY: - if (dev_slotstart(f->dev, f->slot)) { - (void)sock_attach(f, 1); - f->pstate = SOCK_RUN; - } - /* PASSTHROUGH */ - case SOCK_RUN: - sock_freebuf(f); - f->pstate = SOCK_INIT; - /* PASSTHROUGH */ - case SOCK_INIT: - /* nothing yet */ - break; - } -} - -/* - * Read a message from the file descriptor, return 1 if done, 0 - * otherwise. The message is stored in f->rmsg. - */ -int -sock_rmsg(struct sock *f) -{ - unsigned int count; - unsigned char *data; - - while (f->rtodo > 0) { - if (!(f->pipe.file.state & FILE_ROK)) { -#ifdef DEBUG - if (debug_level >= 4) { - sock_dbg(f); - dbg_puts(": reading message blocked, "); - dbg_putu(f->rtodo); - dbg_puts(" bytes remaining\n"); - } -#endif - return 0; - } - data = (unsigned char *)&f->rmsg; - data += sizeof(struct amsg) - f->rtodo; - count = file_read(&f->pipe.file, data, f->rtodo); - if (count == 0) - return 0; - f->rtodo -= count; - } -#ifdef DEBUG - if (debug_level >= 4) { - sock_dbg(f); - dbg_puts(": read full message\n"); - } -#endif - return 1; -} - -/* - * Write a message to the file descriptor, return 1 if done, 0 - * otherwise. The "m" argument is f->rmsg or f->wmsg, and the "ptodo" - * points to the f->rtodo or f->wtodo respectively. - */ -int -sock_wmsg(struct sock *f, struct amsg *m, unsigned int *ptodo) -{ - unsigned int count; - unsigned char *data; - - while (*ptodo > 0) { - if (!(f->pipe.file.state & FILE_WOK)) { -#ifdef DEBUG - if (debug_level >= 4) { - sock_dbg(f); - dbg_puts(": writing message blocked, "); - dbg_putu(*ptodo); - dbg_puts(" bytes remaining\n"); - } -#endif - return 0; - } - data = (unsigned char *)m; - data += sizeof(struct amsg) - *ptodo; - count = file_write(&f->pipe.file, data, *ptodo); - if (count == 0) - return 0; - *ptodo -= count; - } -#ifdef DEBUG - if (debug_level >= 4) { - sock_dbg(f); - dbg_puts(": wrote full message\n"); - } -#endif - return 1; -} - -/* - * Read data chunk from the file descriptor, return 1 if at least one - * byte was read, 0 if the file blocked. - */ -int -sock_rdata(struct sock *f) -{ - struct aproc *p; - struct abuf *obuf; - unsigned int n; - -#ifdef DEBUG - if (f->rtodo == 0) { - sock_dbg(f); - dbg_puts(": data block already read\n"); - dbg_panic(); - } -#endif - p = f->pipe.file.rproc; - obuf = LIST_FIRST(&p->outs); - if (obuf == NULL) - return 0; - if (!ABUF_WOK(obuf) || !(f->pipe.file.state & FILE_ROK)) - return 0; - if (!rfile_do(p, f->rtodo, &n)) - return 0; - f->rtodo -= n; - if (f->pstate == SOCK_START) { - if (!ABUF_WOK(obuf) || (f->pipe.file.state & FILE_EOF)) - f->pstate = SOCK_READY; - } - return 1; -} - -/* - * Write data chunk to the file descriptor, return 1 if at least one - * byte was written, 0 if the file blocked. - */ -int -sock_wdata(struct sock *f) -{ - struct aproc *p; - struct abuf *ibuf; - unsigned int n; - -#ifdef DEBUG - if (f->wtodo == 0) { - sock_dbg(f); - dbg_puts(": attempted to write zero-sized data block\n"); - dbg_panic(); - } -#endif - if (!(f->pipe.file.state & FILE_WOK)) - return 0; - p = f->pipe.file.wproc; - ibuf = LIST_FIRST(&p->ins); -#ifdef DEBUG - if (ibuf == NULL) { - sock_dbg(f); - dbg_puts(": attempted to write on detached buffer\n"); - dbg_panic(); - } -#endif - if (ibuf == NULL) - return 0; - if (!ABUF_ROK(ibuf)) - return 0; - if (!wfile_do(p, f->wtodo, &n)) - return 0; - f->wtodo -= n; - return 1; -} - -int -sock_setpar(struct sock *f) -{ - struct amsg_par *p = &f->rmsg.u.par; - unsigned int min, max, rate, pchan, rchan, appbufsz; - - rchan = ntohs(p->rchan); - pchan = ntohs(p->pchan); - appbufsz = ntohl(p->appbufsz); - rate = ntohl(p->rate); - - if (AMSG_ISSET(p->bits)) { - if (p->bits < BITS_MIN || p->bits > BITS_MAX) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": "); - dbg_putu(p->bits); - dbg_puts(": bits out of bounds\n"); - } -#endif - return 0; - } - if (AMSG_ISSET(p->bps)) { - if (p->bps < ((p->bits + 7) / 8) || p->bps > 4) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": "); - dbg_putu(p->bps); - dbg_puts(": wrong bytes per sample\n"); - } -#endif - return 0; - } - } else - p->bps = APARAMS_BPS(p->bits); - f->rpar.bits = f->wpar.bits = p->bits; - f->rpar.bps = f->wpar.bps = p->bps; -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": using "); - dbg_putu(p->bits); - dbg_puts("bits, "); - dbg_putu(p->bps); - dbg_puts(" bytes per sample\n"); - } -#endif - } - if (AMSG_ISSET(p->sig)) - f->rpar.sig = f->wpar.sig = p->sig ? 1 : 0; - if (AMSG_ISSET(p->le)) - f->rpar.le = f->wpar.le = p->le ? 1 : 0; - if (AMSG_ISSET(p->msb)) - f->rpar.msb = f->wpar.msb = p->msb ? 1 : 0; - if (AMSG_ISSET(rchan) && (f->mode & MODE_RECMASK)) { - if (rchan < 1) - rchan = 1; - if (rchan > NCHAN_MAX) - rchan = NCHAN_MAX; - f->wpar.cmin = f->opt->wpar.cmin; - f->wpar.cmax = f->opt->wpar.cmin + rchan - 1; - if (f->wpar.cmax > f->opt->wpar.cmax) - f->wpar.cmax = f->opt->wpar.cmax; -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": using recording channels "); - dbg_putu(f->wpar.cmin); - dbg_puts(".."); - dbg_putu(f->wpar.cmax); - dbg_puts("\n"); - } -#endif - } - if (AMSG_ISSET(pchan) && (f->mode & MODE_PLAY)) { - if (pchan < 1) - pchan = 1; - if (pchan > NCHAN_MAX) - pchan = NCHAN_MAX; - f->rpar.cmin = f->opt->rpar.cmin; - f->rpar.cmax = f->opt->rpar.cmin + pchan - 1; - if (f->rpar.cmax > f->opt->rpar.cmax) - f->rpar.cmax = f->opt->rpar.cmax; -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": using playback channels "); - dbg_putu(f->rpar.cmin); - dbg_puts(".."); - dbg_putu(f->rpar.cmax); - dbg_puts("\n"); - } -#endif - } - if (AMSG_ISSET(rate)) { - if (rate < RATE_MIN) - rate = RATE_MIN; - if (rate > RATE_MAX) - rate = RATE_MAX; - f->round = dev_roundof(f->dev, rate); - f->rpar.rate = f->wpar.rate = rate; - if (!AMSG_ISSET(appbufsz)) { - appbufsz = f->dev->bufsz / f->dev->round * f->round; -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": using "); - dbg_putu(appbufsz); - dbg_puts(" fr app buffer size\n"); - } -#endif - } -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": using "); - dbg_putu(rate); - dbg_puts("Hz sample rate, "); - dbg_putu(f->round); - dbg_puts(" fr block size\n"); - } -#endif - } - if (AMSG_ISSET(p->xrun)) { - if (p->xrun != XRUN_IGNORE && - p->xrun != XRUN_SYNC && - p->xrun != XRUN_ERROR) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": "); - dbg_putx(p->xrun); - dbg_puts(": bad xrun policy\n"); - } -#endif - return 0; - } - f->xrun = p->xrun; - if (f->opt->mmc && f->xrun == XRUN_IGNORE) - f->xrun = XRUN_SYNC; -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": using 0x"); - dbg_putx(f->xrun); - dbg_puts(" xrun policy\n"); - } -#endif - } - if (AMSG_ISSET(appbufsz)) { - rate = (f->mode & MODE_PLAY) ? f->rpar.rate : f->wpar.rate; - min = 1; - max = 1 + rate / f->dev->round; - min *= f->round; - max *= f->round; - appbufsz += f->round - 1; - appbufsz -= appbufsz % f->round; - if (appbufsz < min) - appbufsz = min; - if (appbufsz > max) - appbufsz = max; - f->bufsz = appbufsz; -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": using "); - dbg_putu(f->bufsz); - dbg_puts(" buffer size\n"); - } -#endif - } -#ifdef DEBUG - if (debug_level >= 2) { - dbg_puts(f->dev->slot[f->slot].name); - dbg_putu(f->dev->slot[f->slot].unit); - dbg_puts(": buffer size = "); - dbg_putu(f->bufsz); - if (f->mode & MODE_PLAY) { - dbg_puts(", play = "); - aparams_dbg(&f->rpar); - } - if (f->mode & MODE_RECMASK) { - dbg_puts(", rec:"); - aparams_dbg(&f->wpar); - } - dbg_puts("\n"); - } -#endif - return 1; -} - -/* - * allocate buffers, so client can start filling write-end. - */ -void -sock_midiattach(struct sock *f) -{ - struct abuf *rbuf = NULL, *wbuf = NULL; - - if (f->mode & MODE_MIDIOUT) { - rbuf = abuf_new(MIDI_BUFSZ, &aparams_none); - aproc_setout(f->pipe.file.rproc, rbuf); - } - if (f->mode & MODE_MIDIIN) { - wbuf = abuf_new(MIDI_BUFSZ, &aparams_none); - aproc_setin(f->pipe.file.wproc, wbuf); - } - f->pstate = SOCK_MIDI; - f->fillpending = MIDI_BUFSZ; - dev_midiattach(f->dev, rbuf, wbuf); -} - -int -sock_auth(struct sock *f) -{ - struct amsg_auth *p = &f->rmsg.u.auth; - - if (sock_sesrefs == 0) { - /* start a new session */ - memcpy(sock_sescookie, p->cookie, AMSG_COOKIELEN); - } else if (memcmp(sock_sescookie, p->cookie, AMSG_COOKIELEN) != 0) { - /* another session is active, drop connection */ - return 0; - } - sock_sesrefs++; - f->pstate = SOCK_HELLO; - return 1; -} - -int -sock_hello(struct sock *f) -{ - struct amsg_hello *p = &f->rmsg.u.hello; - unsigned int mode; - - mode = ntohs(p->mode); -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": hello from <"); - dbg_puts(p->who); - dbg_puts(">, mode = "); - dbg_putx(mode); - dbg_puts(", ver "); - dbg_putu(p->version); - dbg_puts("\n"); - } -#endif - if (p->version != AMSG_VERSION) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": "); - dbg_putu(p->version); - dbg_puts(": unsupported protocol version\n"); - } -#endif - return 0; - } - switch (mode) { - case MODE_MIDIIN: - case MODE_MIDIOUT: - case MODE_MIDIOUT | MODE_MIDIIN: - case MODE_REC: - case MODE_PLAY: - case MODE_PLAY | MODE_REC: - break; - default: -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": "); - dbg_putx(mode); - dbg_puts(": unsupported mode\n"); - } -#endif - return 0; - } - f->opt = opt_byname(p->opt, AMSG_ISSET(p->devnum) ? p->devnum : 0); - if (f->opt == NULL) - return 0; -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": using "); - dev_dbg(f->opt->dev); - dbg_puts("."); - dbg_puts(f->opt->name); - dbg_puts("\n"); - } -#endif - if (!dev_ref(f->opt->dev)) - return 0; - if ((mode & MODE_REC) && (f->opt->mode & MODE_MON)) { - mode &= ~MODE_REC; - mode |= MODE_MON; - } - f->dev = f->opt->dev; - f->mode = (mode & f->opt->mode) & f->dev->mode; -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": using mode = "); - dbg_putx(f->mode); - dbg_puts("\n"); - } -#endif - if (f->mode != mode) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": requested mode not available\n"); - } -#endif - return 0; - } - if (f->mode & (MODE_MIDIOUT | MODE_MIDIIN)) { - sock_midiattach(f); - return 1; - } - if (f->mode & MODE_PLAY) - f->rpar = f->opt->rpar; - if (f->mode & MODE_RECMASK) - f->wpar = f->opt->wpar; - f->xrun = (f->opt->mmc) ? XRUN_SYNC : XRUN_IGNORE; - f->bufsz = f->dev->bufsz; - f->round = f->dev->round; - f->slot = dev_slotnew(f->dev, p->who, &ctl_sockops, f, f->opt->mmc); - if (f->slot < 0) - return 0; - f->pstate = SOCK_INIT; - return 1; -} - -/* - * Execute message in f->rmsg and change the state accordingly; return 1 - * on success, and 0 on failure, in which case the socket is destroyed. - */ -int -sock_execmsg(struct sock *f) -{ - struct amsg *m = &f->rmsg; - struct abuf *obuf; - unsigned int size, ctl; - - switch (ntohl(m->cmd)) { - case AMSG_DATA: -#ifdef DEBUG - if (debug_level >= 4) { - sock_dbg(f); - dbg_puts(": DATA message\n"); - } -#endif - if (f->pstate != SOCK_MIDI && f->pstate != SOCK_RUN && - f->pstate != SOCK_START && f->pstate != SOCK_READY) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": DATA, bad state\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } - if (!(f->mode & (MODE_PLAY | MODE_MIDIOUT))) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": DATA not allowed in record-only mode\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } - obuf = LIST_FIRST(&f->pipe.file.rproc->outs); - if (f->pstate == SOCK_START && !ABUF_WOK(obuf)) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": DATA client violates flow control\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } - size = ntohl(m->u.data.size); - if (size % obuf->bpf != 0) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": unaligned data chunk\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } - f->rstate = SOCK_RDATA; - f->rtodo = size / obuf->bpf; -#ifdef DEBUG - if (debug_level >= 2 && - f->pstate != SOCK_MIDI && f->rtodo > f->rmax) { - sock_dbg(f); - dbg_puts(": received past current position, rtodo = "); - dbg_putu(f->rtodo); - dbg_puts(", rmax = "); - dbg_putu(f->rmax); - dbg_puts("\n"); - aproc_del(f->pipe.file.rproc); - return 0; - } -#endif - if (f->pstate != SOCK_MIDI) - f->rmax -= f->rtodo; - else - f->fillpending += f->rtodo; - if (f->rtodo == 0) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": zero-length data chunk\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } - break; - case AMSG_START: -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": START message\n"); - } -#endif - if (f->pstate != SOCK_INIT) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": START, bad state\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } - sock_allocbuf(f); - f->rstate = SOCK_RMSG; - f->rtodo = sizeof(struct amsg); - break; - case AMSG_STOP: -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": STOP message\n"); - } -#endif - if (f->pstate != SOCK_RUN && - f->pstate != SOCK_START && f->pstate != SOCK_READY) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": STOP, bad state\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } - /* - * XXX: device could have desappeared at this point, - * see how this is fixed in wav.c - */ - if ((f->pstate == SOCK_START || f->pstate == SOCK_READY) && - dev_slotstart(f->dev, f->slot)) - (void)sock_attach(f, 1); - if (f->wstate != SOCK_WDATA || f->wtodo == 0) - sock_freebuf(f); - else - f->pstate = SOCK_STOP; - AMSG_INIT(m); - m->cmd = htonl(AMSG_STOP); - f->rstate = SOCK_RRET; - f->rtodo = sizeof(struct amsg); - break; - case AMSG_SETPAR: -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": SETPAR message\n"); - } -#endif - if (f->pstate != SOCK_INIT) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": SETPAR, bad state\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } - if (!sock_setpar(f)) { - aproc_del(f->pipe.file.rproc); - return 0; - } - f->rtodo = sizeof(struct amsg); - f->rstate = SOCK_RMSG; - break; - case AMSG_GETPAR: -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": GETPAR message\n"); - } -#endif - if (f->pstate != SOCK_INIT) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": GETPAR, bad state\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } - AMSG_INIT(m); - m->cmd = htonl(AMSG_GETPAR); - m->u.par.legacy_mode = f->mode; - if (f->mode & MODE_PLAY) { - m->u.par.bits = f->rpar.bits; - m->u.par.bps = f->rpar.bps; - m->u.par.sig = f->rpar.sig; - m->u.par.le = f->rpar.le; - m->u.par.msb = f->rpar.msb; - m->u.par.rate = htonl(f->rpar.rate); - m->u.par.pchan = htons(f->rpar.cmax - f->rpar.cmin + 1); - } - if (f->mode & MODE_RECMASK) { - m->u.par.bits = f->wpar.bits; - m->u.par.bps = f->wpar.bps; - m->u.par.sig = f->wpar.sig; - m->u.par.le = f->wpar.le; - m->u.par.msb = f->wpar.msb; - m->u.par.rate = htonl(f->wpar.rate); - m->u.par.rchan = htons(f->wpar.cmax - f->wpar.cmin + 1); - } - m->u.par.appbufsz = htonl(f->bufsz); - m->u.par.bufsz = htonl( - f->bufsz + (f->dev->bufsz / f->dev->round) * f->round); - m->u.par.round = htonl(f->round); - f->rstate = SOCK_RRET; - f->rtodo = sizeof(struct amsg); - break; - case AMSG_SETVOL: -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": SETVOL message\n"); - } -#endif - if (f->pstate != SOCK_RUN && f->pstate != SOCK_START && - f->pstate != SOCK_INIT && f->pstate != SOCK_READY) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": SETVOL, bad state\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } - ctl = ntohl(m->u.vol.ctl); - if (ctl > MIDI_MAXCTL) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": SETVOL, volume out of range\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } - sock_setvol(f, ctl); - if (f->slot >= 0) - dev_slotvol(f->dev, f->slot, ctl); - f->rtodo = sizeof(struct amsg); - f->rstate = SOCK_RMSG; - break; - case AMSG_AUTH: -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": AUTH message\n"); - } -#endif - if (f->pstate != SOCK_AUTH) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": AUTH, bad state\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } - if (!sock_auth(f)) { - aproc_del(f->pipe.file.rproc); - return 0; - } - f->rstate = SOCK_RMSG; - f->rtodo = sizeof(struct amsg); - break; - case AMSG_HELLO: -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": HELLO message\n"); - } -#endif - if (f->pstate != SOCK_HELLO) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": HELLO, bad state\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } - if (!sock_hello(f)) { - aproc_del(f->pipe.file.rproc); - return 0; - } - AMSG_INIT(m); - m->cmd = htonl(AMSG_ACK); - f->rstate = SOCK_RRET; - f->rtodo = sizeof(struct amsg); - break; - case AMSG_BYE: -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": BYE message\n"); - } -#endif - if (f->pstate != SOCK_INIT && f->pstate != SOCK_MIDI) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": BYE, bad state\n"); - } -#endif - } - aproc_del(f->pipe.file.rproc); - return 0; - default: -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": unknown command in message\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } - return 1; -} - -/* - * Create a new data/pos message. - */ -int -sock_buildmsg(struct sock *f) -{ - struct aproc *p; - struct abuf *ibuf; - unsigned int size, max; - - /* - * If pos changed, build a MOVE message. - */ - if (f->tickpending && f->delta >= 0) { -#ifdef DEBUG - if (debug_level >= 4) { - sock_dbg(f); - dbg_puts(": building MOVE message, delta = "); - dbg_puti(f->delta); - dbg_puts("\n"); - } -#endif - AMSG_INIT(&f->wmsg); - f->wmsg.cmd = htonl(AMSG_MOVE); - f->wmsg.u.ts.delta = htonl(f->delta); - f->wtodo = sizeof(struct amsg); - f->wstate = SOCK_WMSG; - f->wmax += f->delta; - f->fillpending += f->delta; - f->delta = 0; - f->tickpending = 0; - return 1; - } - - if (f->fillpending > 0) { -#ifdef DEBUG - if (debug_level >= 4) { - sock_dbg(f); - dbg_puts(": building FLOWCTL message, count = "); - dbg_puti(f->fillpending); - dbg_puts("\n"); - } -#endif - AMSG_INIT(&f->wmsg); - f->wmsg.cmd = htonl(AMSG_FLOWCTL); - f->wmsg.u.ts.delta = htonl(f->fillpending); - f->wtodo = sizeof(struct amsg); - f->wstate = SOCK_WMSG; - f->rmax += f->fillpending; - f->fillpending = 0; - return 1; - } - - /* - * if volume changed build a SETVOL message - */ - if (f->pstate >= SOCK_START && f->vol != f->lastvol) { -#ifdef DEBUG - if (debug_level >= 4) { - sock_dbg(f); - dbg_puts(": building SETVOL message, vol = "); - dbg_puti(f->vol); - dbg_puts("\n"); - } -#endif - AMSG_INIT(&f->wmsg); - f->wmsg.cmd = htonl(AMSG_SETVOL); - f->wmsg.u.vol.ctl = htonl(f->vol); - f->wtodo = sizeof(struct amsg); - f->wstate = SOCK_WMSG; - f->lastvol = f->vol; - return 1; - } - - /* - * If data available, build a DATA message. - */ - p = f->pipe.file.wproc; - ibuf = LIST_FIRST(&p->ins); - if (ibuf && ABUF_ROK(ibuf)) { -#ifdef DEBUG - if (debug_level >= 3 && - f->pstate != SOCK_MIDI && ibuf->used > f->wmax) { - sock_dbg(f); - dbg_puts(": attempt to send past current position: used = "); - dbg_putu(ibuf->used); - dbg_puts(" wmax = "); - dbg_putu(f->wmax); - dbg_puts("\n"); - } -#endif - size = ibuf->used; - if (f->pstate == SOCK_MIDI) { - if (size > AMSG_DATAMAX) - size = AMSG_DATAMAX; - if (size == 0) - return 0; - } else { - max = AMSG_DATAMAX / ibuf->bpf; - if (size > max) - size = max; - if (size > f->walign) - size = f->walign; - if (size > f->wmax) - size = f->wmax; - if (size == 0) - return 0; - f->walign -= size; - f->wmax -= size; - if (f->walign == 0) - f->walign = f->round; - size *= ibuf->bpf; - } - AMSG_INIT(&f->wmsg); - f->wmsg.cmd = htonl(AMSG_DATA); - f->wmsg.u.data.size = htonl(size); - f->wtodo = sizeof(struct amsg); - f->wstate = SOCK_WMSG; - return 1; - } -#ifdef DEBUG - if (debug_level >= 4) { - sock_dbg(f); - dbg_puts(": no messages to build anymore, idling...\n"); - } -#endif - f->wstate = SOCK_WIDLE; - return 0; -} - -/* - * Read from the socket file descriptor, fill input buffer and update - * the state. Return 1 if at least one message or 1 data byte was - * processed, 0 if something blocked. - */ -int -sock_read(struct sock *f) -{ - int rc; - -#ifdef DEBUG - if (debug_level >= 4) { - sock_dbg(f); - dbg_puts(": reading "); - dbg_putu(f->rtodo); - dbg_puts(" todo\n"); - } -#endif - switch (f->rstate) { - case SOCK_RMSG: - if (!sock_rmsg(f)) - return 0; - if (!sock_execmsg(f)) - return 0; - break; - case SOCK_RDATA: - if (!sock_rdata(f)) - return 0; - if (f->rtodo == 0) { - f->rstate = SOCK_RMSG; - f->rtodo = sizeof(struct amsg); - } - /* - * XXX: sock_attach() may not start if there's not enough - * samples queued, if so dev_slotstart() will trigger - * other streams, but this one won't start. - */ - if (f->pstate == SOCK_READY && dev_slotstart(f->dev, f->slot)) - (void)sock_attach(f, 0); - break; - case SOCK_RRET: -#ifdef DEBUG - if (debug_level >= 4) { - sock_dbg(f); - dbg_puts(": blocked by pending RRET message\n"); - } -#endif - return 0; - } - for (;;) { - /* - * send pending ACKs, initial positions, initial volumes - */ - f->pipe.file.state |= FILE_WINUSE; - rc = sock_write(f); - f->pipe.file.state &= ~FILE_WINUSE; - if (f->pipe.file.state & FILE_ZOMB) { - file_del(&f->pipe.file); - return 0; - } - if (!rc) - break; - } - return 1; -} - -/* - * Process messages to return. - */ -int -sock_return(struct sock *f) -{ - struct aproc *rp; - - while (f->rstate == SOCK_RRET) { - if (!sock_wmsg(f, &f->rmsg, &f->rtodo)) - return 0; -#ifdef DEBUG - if (debug_level >= 4) { - sock_dbg(f); - dbg_puts(": sent RRET message\n"); - } -#endif - f->rstate = SOCK_RMSG; - f->rtodo = sizeof(struct amsg); - if (f->pipe.file.state & FILE_RINUSE) - break; - f->pipe.file.state |= FILE_RINUSE; - for (;;) { - /* - * in() may trigger rsock_done and destroy the - * wsock. - */ - rp = f->pipe.file.rproc; - if (!rp) - break; -#ifdef DEBUG - if (debug_level >= 4) { - aproc_dbg(rp); - dbg_puts(": in\n"); - } -#endif - if (!rp->ops->in(rp, NULL)) { - break; - } - } - f->pipe.file.state &= ~FILE_RINUSE; - if (f->pipe.file.state & FILE_ZOMB) { - file_del(&f->pipe.file); - return 0; - } - } - return 1; -} - -/* - * Write messages and data on the socket file descriptor. Return 1 if - * at least one message or one data byte was processed, 0 if something - * blocked. - */ -int -sock_write(struct sock *f) -{ -#ifdef DEBUG - if (debug_level >= 4) { - sock_dbg(f); - dbg_puts(": writing"); - if (f->wstate != SOCK_WIDLE) { - dbg_puts(" todo = "); - dbg_putu(f->wtodo); - } - dbg_puts("\n"); - } -#endif - switch (f->wstate) { - case SOCK_WMSG: - if (!sock_wmsg(f, &f->wmsg, &f->wtodo)) - return 0; - if (ntohl(f->wmsg.cmd) != AMSG_DATA) { - f->wstate = SOCK_WIDLE; - f->wtodo = 0xdeadbeef; - break; - } - /* - * XXX: why not set f->wtodo in sock_wmsg() ? - */ - f->wstate = SOCK_WDATA; - f->wtodo = ntohl(f->wmsg.u.data.size) / - LIST_FIRST(&f->pipe.file.wproc->ins)->bpf; - /* PASSTHROUGH */ - case SOCK_WDATA: - if (!sock_wdata(f)) - return 0; - if (f->wtodo > 0) - break; - f->wstate = SOCK_WIDLE; - f->wtodo = 0xdeadbeef; - if (f->pstate == SOCK_STOP) - sock_freebuf(f); - /* PASSTHROUGH */ - case SOCK_WIDLE: - if (!sock_return(f)) - return 0; - if (!sock_buildmsg(f)) - return 0; - break; -#ifdef DEBUG - default: - sock_dbg(f); - dbg_puts(": bad writing end state\n"); - dbg_panic(); -#endif - } - return 1; -} diff --git a/usr.bin/aucat/sock.h b/usr.bin/aucat/sock.h deleted file mode 100644 index 3d7d5cc6958..00000000000 --- a/usr.bin/aucat/sock.h +++ /dev/null @@ -1,75 +0,0 @@ -/* $OpenBSD: sock.h,v 1.21 2012/11/02 10:24:58 ratchov Exp $ */ -/* - * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef SOCK_H -#define SOCK_H - -#include "amsg.h" -#include "aparams.h" -#include "pipe.h" - -struct opt; - -struct sock { - struct pipe pipe; - /* - * Socket and protocol specific stuff, mainly used - * to decode/encode messages in the stream. - */ - struct amsg rmsg, wmsg; /* messages being sent/received */ - unsigned int wmax; /* max frames we're allowed to write */ - unsigned int rmax; /* max frames we're allowed to read */ - unsigned int rtodo; /* input bytes not read yet */ - unsigned int wtodo; /* output bytes not written yet */ -#define SOCK_RDATA 0 /* data chunk being read */ -#define SOCK_RMSG 1 /* amsg query being processed */ -#define SOCK_RRET 2 /* amsg reply being returned */ - unsigned int rstate; /* state of the read-end FSM */ -#define SOCK_WIDLE 0 /* nothing to do */ -#define SOCK_WMSG 1 /* amsg being written */ -#define SOCK_WDATA 2 /* data chunk being written */ - unsigned int wstate; /* state of the write-end FSM */ -#define SOCK_AUTH 0 /* waiting for AUTH message */ -#define SOCK_HELLO 1 /* waiting for HELLO message */ -#define SOCK_INIT 2 /* parameter negotiation */ -#define SOCK_START 3 /* filling play buffers */ -#define SOCK_READY 4 /* play buffers full */ -#define SOCK_RUN 5 /* attached to the mix / sub */ -#define SOCK_STOP 6 /* draining rec buffers */ -#define SOCK_MIDI 7 /* raw byte stream (midi) */ - unsigned int pstate; /* one of the above */ - unsigned int mode; /* bitmask of MODE_XXX */ - struct aparams rpar; /* read (ie play) parameters */ - struct aparams wpar; /* write (ie rec) parameters */ - int delta; /* pos. change to send */ - int tickpending; /* delta waiting to be transmitted */ - int fillpending; /* pending buffer fill request */ - unsigned int walign; /* align data packets to this */ - unsigned int bufsz; /* total buffer size */ - unsigned int round; /* block size */ - unsigned int xrun; /* one of AMSG_IGNORE, ... */ - int vol; /* requested volume */ - 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 */ -}; - -struct sock *sock_new(struct fileops *, int fd); -extern struct fileops sock_ops; - -#endif /* !defined(SOCK_H) */ diff --git a/usr.bin/aucat/wav.c b/usr.bin/aucat/wav.c index 3963d9aa283..7e1df95c01b 100644 --- a/usr.bin/aucat/wav.c +++ b/usr.bin/aucat/wav.c @@ -26,7 +26,6 @@ #include "dev.h" #include "midi.h" #include "wav.h" -#include "opt.h" #ifdef DEBUG #include "dbg.h" #endif |