Annotation of src/usr.bin/aucat/safile.c, Revision 1.1
1.1 ! ratchov 1: /* $OpenBSD$ */
! 2: /*
! 3: * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
! 4: *
! 5: * Permission to use, copy, modify, and distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17:
! 18: #include <sys/types.h>
! 19: #include <sys/time.h>
! 20:
! 21: #include <poll.h>
! 22: #include <stdio.h>
! 23: #include <stdlib.h>
! 24: #include <string.h>
! 25: #include <libsa.h>
! 26:
! 27: #include "conf.h"
! 28: #include "file.h"
! 29: #include "aproc.h"
! 30: #include "aparams.h"
! 31: #include "safile.h"
! 32: #include "dev.h"
! 33:
! 34: struct safile {
! 35: struct file file;
! 36: struct sa_hdl *hdl;
! 37: #ifdef DEBUG
! 38: struct timeval itv, otv;
! 39: #endif
! 40: };
! 41:
! 42: void safile_close(struct file *);
! 43: unsigned safile_read(struct file *, unsigned char *, unsigned);
! 44: unsigned safile_write(struct file *, unsigned char *, unsigned);
! 45: void safile_start(struct file *);
! 46: void safile_stop(struct file *);
! 47: int safile_nfds(struct file *);
! 48: int safile_pollfd(struct file *, struct pollfd *, int);
! 49: int safile_revents(struct file *, struct pollfd *);
! 50:
! 51: struct fileops safile_ops = {
! 52: "libsa",
! 53: sizeof(struct safile),
! 54: safile_close,
! 55: safile_read,
! 56: safile_write,
! 57: safile_start,
! 58: safile_stop,
! 59: safile_nfds,
! 60: safile_pollfd,
! 61: safile_revents
! 62: };
! 63:
! 64: void
! 65: safile_cb(void *addr, int delta)
! 66: {
! 67: struct safile *f = (struct safile *)addr;
! 68: struct aproc *p;
! 69:
! 70: if (delta != 0) {
! 71: p = f->file.wproc;
! 72: if (p && p->ops->opos)
! 73: p->ops->opos(p, NULL, delta);
! 74: }
! 75: if (delta != 0) {
! 76: p = f->file.rproc;
! 77: if (p && p->ops->ipos)
! 78: p->ops->ipos(p, NULL, delta);
! 79: }
! 80: }
! 81:
! 82: /*
! 83: * open the device
! 84: */
! 85: struct safile *
! 86: safile_new(struct fileops *ops, char *path,
! 87: struct aparams *ipar, struct aparams *opar,
! 88: unsigned *bufsz, unsigned *round)
! 89: {
! 90: struct sa_par par;
! 91: struct sa_hdl *hdl;
! 92: struct safile *f;
! 93: int mode;
! 94:
! 95: mode = 0;
! 96: if (ipar)
! 97: mode |= SA_REC;
! 98: if (opar)
! 99: mode |= SA_PLAY;
! 100: if (!mode)
! 101: fprintf(stderr, "%s: must at least play or record", path);
! 102: hdl = sa_open(path, mode, 1);
! 103: if (hdl == NULL) {
! 104: fprintf(stderr, "safile_new: can't open device\n");
! 105: return NULL;
! 106: }
! 107: sa_initpar(&par);
! 108: if (ipar) {
! 109: par.bits = ipar->bits;
! 110: par.bps = ipar->bps;
! 111: par.sig = ipar->sig;
! 112: par.le = ipar->le;
! 113: par.msb = ipar->msb;
! 114: par.rate = ipar->rate;
! 115: par.rchan = ipar->cmax - ipar->cmin + 1;
! 116: } else {
! 117: par.bits = opar->bits;
! 118: par.bps = opar->bps;
! 119: par.sig = opar->sig;
! 120: par.le = opar->le;
! 121: par.msb = opar->msb;
! 122: par.rate = opar->rate;
! 123: }
! 124: if (opar)
! 125: par.pchan = opar->cmax - opar->cmin + 1;
! 126: if (*bufsz)
! 127: par.bufsz = *bufsz;
! 128: if (!sa_setpar(hdl, &par)) {
! 129: fprintf(stderr, "safile_new: sa_setpar failed\n");
! 130: exit(1);
! 131: }
! 132: if (!sa_getpar(hdl, &par)) {
! 133: fprintf(stderr, "safile_new: sa_getpar failed\n");
! 134: exit(1);
! 135: }
! 136: if (ipar) {
! 137: ipar->bits = par.bits;
! 138: ipar->bps = par.bps;
! 139: ipar->sig = par.sig;
! 140: ipar->le = par.le;
! 141: ipar->msb = par.msb;
! 142: ipar->rate = par.rate;
! 143: ipar->cmax = par.rchan - 1;
! 144: ipar->cmin = 0;
! 145: }
! 146: if (opar) {
! 147: opar->bits = par.bits;
! 148: opar->bps = par.bps;
! 149: opar->sig = par.sig;
! 150: opar->le = par.le;
! 151: opar->msb = par.msb;
! 152: opar->rate = par.rate;
! 153: opar->cmax = par.pchan - 1;
! 154: opar->cmin = 0;
! 155: }
! 156: *bufsz = par.bufsz;
! 157: *round = par.round;
! 158: DPRINTF("safile_open: using %u(%u) fpb\n", *bufsz, *round);
! 159: f = (struct safile *)file_new(ops, "hdl", sa_nfds(hdl));
! 160: f->hdl = hdl;
! 161: sa_onmove(f->hdl, safile_cb, f);
! 162: return f;
! 163: }
! 164:
! 165: void
! 166: safile_start(struct file *file)
! 167: {
! 168: struct safile *f = (struct safile *)file;
! 169:
! 170: if (!sa_start(f->hdl)) {
! 171: fprintf(stderr, "safile_start: sa_start() failed\n");
! 172: exit(1);
! 173: }
! 174: DPRINTF("safile_start: play/rec started\n");
! 175: }
! 176:
! 177: void
! 178: safile_stop(struct file *file)
! 179: {
! 180: struct safile *f = (struct safile *)file;
! 181:
! 182: if (!sa_stop(f->hdl)) {
! 183: fprintf(stderr, "safile_stop: sa_start() filed\n");
! 184: exit(1);
! 185: }
! 186: DPRINTF("safile_stop: play/rec stopped\n");
! 187: }
! 188:
! 189: unsigned
! 190: safile_read(struct file *file, unsigned char *data, unsigned count)
! 191: {
! 192: struct safile *f = (struct safile *)file;
! 193: unsigned n;
! 194: #ifdef DEBUG
! 195: struct timeval tv0, tv1, dtv;
! 196: unsigned us;
! 197:
! 198: if (!(f->file.state & FILE_ROK)) {
! 199: DPRINTF("file_read: %s: bad state\n", f->file.name);
! 200: abort();
! 201: }
! 202: gettimeofday(&tv0, NULL);
! 203: #endif
! 204: n = sa_read(f->hdl, data, count);
! 205: if (n == 0) {
! 206: f->file.state &= ~FILE_ROK;
! 207: if (sa_eof(f->hdl)) {
! 208: fprintf(stderr, "safile_read: eof\n");
! 209: file_eof(&f->file);
! 210: } else {
! 211: DPRINTFN(3, "safile_read: %s: blocking...\n",
! 212: f->file.name);
! 213: }
! 214: return 0;
! 215: }
! 216: #ifdef DEBUG
! 217: gettimeofday(&tv1, NULL);
! 218: timersub(&tv1, &tv0, &dtv);
! 219: us = dtv.tv_sec * 1000000 + dtv.tv_usec;
! 220: DPRINTFN(us < 5000 ? 4 : 1,
! 221: "safile_read: %s: got %d bytes in %uus\n",
! 222: f->file.name, n, us);
! 223: #endif
! 224: return n;
! 225:
! 226: }
! 227:
! 228: unsigned
! 229: safile_write(struct file *file, unsigned char *data, unsigned count)
! 230: {
! 231: struct safile *f = (struct safile *)file;
! 232: unsigned n;
! 233: #ifdef DEBUG
! 234: struct timeval tv0, tv1, dtv;
! 235: unsigned us;
! 236:
! 237: if (!(f->file.state & FILE_WOK)) {
! 238: DPRINTF("safile_write: %s: bad state\n", f->file.name);
! 239: abort();
! 240: }
! 241: gettimeofday(&tv0, NULL);
! 242: #endif
! 243: n = sa_write(f->hdl, data, count);
! 244: if (n == 0) {
! 245: f->file.state &= ~FILE_WOK;
! 246: if (sa_eof(f->hdl)) {
! 247: fprintf(stderr, "safile_write: %s: hup\n", f->file.name);
! 248: file_hup(&f->file);
! 249: } else {
! 250: DPRINTFN(3, "safile_write: %s: blocking...\n",
! 251: f->file.name);
! 252: }
! 253: return 0;
! 254: }
! 255: #ifdef DEBUG
! 256: gettimeofday(&tv1, NULL);
! 257: timersub(&tv1, &tv0, &dtv);
! 258: us = dtv.tv_sec * 1000000 + dtv.tv_usec;
! 259: DPRINTFN(us < 5000 ? 4 : 1,
! 260: "safile_write: %s: wrote %d bytes in %uus\n",
! 261: f->file.name, n, us);
! 262: #endif
! 263: return n;
! 264: }
! 265:
! 266: int
! 267: safile_nfds(struct file *file)
! 268: {
! 269: return sa_nfds(((struct safile *)file)->hdl);
! 270: }
! 271:
! 272: int
! 273: safile_pollfd(struct file *file, struct pollfd *pfd, int events)
! 274: {
! 275: return sa_pollfd(((struct safile *)file)->hdl, pfd, events);
! 276: }
! 277:
! 278: int
! 279: safile_revents(struct file *file, struct pollfd *pfd)
! 280: {
! 281: return sa_revents(((struct safile *)file)->hdl, pfd);
! 282: }
! 283:
! 284: void
! 285: safile_close(struct file *file)
! 286: {
! 287: return sa_close(((struct safile *)file)->hdl);
! 288: }