Annotation of src/usr.bin/aucat/safile.c, Revision 1.16
1.16 ! ratchov 1: /* $OpenBSD: safile.c,v 1.15 2009/08/28 06:30:17 ratchov Exp $ */
1.1 ratchov 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:
1.14 ratchov 18: #include <sys/time.h>
1.1 ratchov 19: #include <sys/types.h>
20:
21: #include <poll.h>
1.14 ratchov 22: #include <sndio.h>
1.1 ratchov 23: #include <stdio.h>
24: #include <stdlib.h>
25: #include <string.h>
26:
1.14 ratchov 27: #include "aparams.h"
28: #include "aproc.h"
1.1 ratchov 29: #include "conf.h"
1.14 ratchov 30: #include "dev.h"
1.1 ratchov 31: #include "file.h"
32: #include "safile.h"
33:
34: struct safile {
35: struct file file;
1.2 ratchov 36: struct sio_hdl *hdl;
1.15 ratchov 37: int started;
1.10 ratchov 38: #ifdef DEBUG
1.1 ratchov 39: struct timeval itv, otv;
40: #endif
41: };
42:
43: void safile_close(struct file *);
44: unsigned safile_read(struct file *, unsigned char *, unsigned);
45: unsigned safile_write(struct file *, unsigned char *, unsigned);
46: void safile_start(struct file *);
47: void safile_stop(struct file *);
48: int safile_nfds(struct file *);
49: int safile_pollfd(struct file *, struct pollfd *, int);
50: int safile_revents(struct file *, struct pollfd *);
51:
52: struct fileops safile_ops = {
1.3 ratchov 53: "sndio",
1.1 ratchov 54: sizeof(struct safile),
55: safile_close,
56: safile_read,
57: safile_write,
58: safile_start,
59: safile_stop,
60: safile_nfds,
61: safile_pollfd,
62: safile_revents
63: };
64:
65: void
66: safile_cb(void *addr, int delta)
67: {
68: struct safile *f = (struct safile *)addr;
69: struct aproc *p;
70:
71: if (delta != 0) {
72: p = f->file.wproc;
73: if (p && p->ops->opos)
74: p->ops->opos(p, NULL, delta);
75: }
76: if (delta != 0) {
77: p = f->file.rproc;
78: if (p && p->ops->ipos)
79: p->ops->ipos(p, NULL, delta);
80: }
81: }
82:
83: /*
1.14 ratchov 84: * Open the device.
1.1 ratchov 85: */
86: struct safile *
87: safile_new(struct fileops *ops, char *path,
88: struct aparams *ipar, struct aparams *opar,
1.5 ratchov 89: unsigned *bufsz, unsigned *round)
1.1 ratchov 90: {
1.2 ratchov 91: struct sio_par par;
92: struct sio_hdl *hdl;
1.1 ratchov 93: struct safile *f;
94: int mode;
95:
96: mode = 0;
97: if (ipar)
1.2 ratchov 98: mode |= SIO_REC;
1.1 ratchov 99: if (opar)
1.2 ratchov 100: mode |= SIO_PLAY;
101: hdl = sio_open(path, mode, 1);
1.12 ratchov 102: if (hdl == NULL)
1.1 ratchov 103: return NULL;
1.2 ratchov 104: sio_initpar(&par);
1.1 ratchov 105: if (ipar) {
106: par.bits = ipar->bits;
107: par.bps = ipar->bps;
108: par.sig = ipar->sig;
109: par.le = ipar->le;
110: par.msb = ipar->msb;
111: par.rate = ipar->rate;
112: par.rchan = ipar->cmax - ipar->cmin + 1;
113: } else {
114: par.bits = opar->bits;
115: par.bps = opar->bps;
116: par.sig = opar->sig;
117: par.le = opar->le;
118: par.msb = opar->msb;
119: par.rate = opar->rate;
120: }
121: if (opar)
122: par.pchan = opar->cmax - opar->cmin + 1;
1.6 ratchov 123: par.appbufsz = *bufsz;
1.3 ratchov 124: par.round = *round;
1.5 ratchov 125: if (!sio_setpar(hdl, &par))
1.11 ratchov 126: goto bad_close;
1.5 ratchov 127: if (!sio_getpar(hdl, &par))
1.11 ratchov 128: goto bad_close;
1.1 ratchov 129: if (ipar) {
130: ipar->bits = par.bits;
131: ipar->bps = par.bps;
132: ipar->sig = par.sig;
133: ipar->le = par.le;
134: ipar->msb = par.msb;
135: ipar->rate = par.rate;
1.7 ratchov 136: ipar->cmax = ipar->cmin + par.rchan - 1;
1.1 ratchov 137: }
138: if (opar) {
139: opar->bits = par.bits;
140: opar->bps = par.bps;
141: opar->sig = par.sig;
142: opar->le = par.le;
143: opar->msb = par.msb;
144: opar->rate = par.rate;
1.7 ratchov 145: opar->cmax = opar->cmin + par.pchan - 1;
1.1 ratchov 146: }
147: *bufsz = par.bufsz;
148: *round = par.round;
1.3 ratchov 149: DPRINTF("safile_new: using %u(%u) fpb\n", *bufsz, *round);
1.2 ratchov 150: f = (struct safile *)file_new(ops, "hdl", sio_nfds(hdl));
1.11 ratchov 151: if (f == NULL)
152: goto bad_close;
1.1 ratchov 153: f->hdl = hdl;
1.15 ratchov 154: f->started = 0;
1.2 ratchov 155: sio_onmove(f->hdl, safile_cb, f);
1.1 ratchov 156: return f;
1.11 ratchov 157: bad_close:
158: sio_close(hdl);
159: return NULL;
1.1 ratchov 160: }
161:
162: void
163: safile_start(struct file *file)
1.10 ratchov 164: {
1.1 ratchov 165: struct safile *f = (struct safile *)file;
166:
1.2 ratchov 167: if (!sio_start(f->hdl)) {
1.8 ratchov 168: DPRINTF("safile_start: sio_start() failed\n");
1.9 ratchov 169: file_close(file);
1.8 ratchov 170: return;
1.1 ratchov 171: }
1.15 ratchov 172: f->started = 1;
1.1 ratchov 173: DPRINTF("safile_start: play/rec started\n");
174: }
175:
176: void
177: safile_stop(struct file *file)
178: {
179: struct safile *f = (struct safile *)file;
180:
1.16 ! ratchov 181: f->started = 0;
1.2 ratchov 182: if (!sio_stop(f->hdl)) {
1.8 ratchov 183: DPRINTF("safile_stop: sio_stop() filed\n");
1.9 ratchov 184: file_close(file);
1.8 ratchov 185: return;
1.1 ratchov 186: }
187: DPRINTF("safile_stop: play/rec stopped\n");
188: }
189:
190: unsigned
191: safile_read(struct file *file, unsigned char *data, unsigned count)
192: {
193: struct safile *f = (struct safile *)file;
194: unsigned n;
195: #ifdef DEBUG
196: struct timeval tv0, tv1, dtv;
197: unsigned us;
198:
199: if (!(f->file.state & FILE_ROK)) {
1.14 ratchov 200: DPRINTF("safile_read: %s: bad state\n", f->file.name);
1.1 ratchov 201: abort();
202: }
203: gettimeofday(&tv0, NULL);
204: #endif
1.2 ratchov 205: n = sio_read(f->hdl, data, count);
1.1 ratchov 206: if (n == 0) {
207: f->file.state &= ~FILE_ROK;
1.2 ratchov 208: if (sio_eof(f->hdl)) {
1.1 ratchov 209: fprintf(stderr, "safile_read: eof\n");
210: file_eof(&f->file);
211: } else {
212: DPRINTFN(3, "safile_read: %s: blocking...\n",
213: f->file.name);
214: }
215: return 0;
216: }
217: #ifdef DEBUG
218: gettimeofday(&tv1, NULL);
219: timersub(&tv1, &tv0, &dtv);
1.10 ratchov 220: us = dtv.tv_sec * 1000000 + dtv.tv_usec;
1.13 ratchov 221: DPRINTFN(us < 5000 ? 4 : 2,
1.10 ratchov 222: "safile_read: %s: got %d bytes in %uus\n",
1.1 ratchov 223: f->file.name, n, us);
224: #endif
225: return n;
226:
227: }
228:
229: unsigned
230: safile_write(struct file *file, unsigned char *data, unsigned count)
231: {
232: struct safile *f = (struct safile *)file;
233: unsigned n;
234: #ifdef DEBUG
235: struct timeval tv0, tv1, dtv;
236: unsigned us;
1.10 ratchov 237:
1.1 ratchov 238: if (!(f->file.state & FILE_WOK)) {
239: DPRINTF("safile_write: %s: bad state\n", f->file.name);
240: abort();
241: }
242: gettimeofday(&tv0, NULL);
243: #endif
1.2 ratchov 244: n = sio_write(f->hdl, data, count);
1.1 ratchov 245: if (n == 0) {
246: f->file.state &= ~FILE_WOK;
1.2 ratchov 247: if (sio_eof(f->hdl)) {
1.1 ratchov 248: fprintf(stderr, "safile_write: %s: hup\n", f->file.name);
249: file_hup(&f->file);
250: } else {
251: DPRINTFN(3, "safile_write: %s: blocking...\n",
252: f->file.name);
253: }
254: return 0;
255: }
256: #ifdef DEBUG
257: gettimeofday(&tv1, NULL);
258: timersub(&tv1, &tv0, &dtv);
1.10 ratchov 259: us = dtv.tv_sec * 1000000 + dtv.tv_usec;
1.13 ratchov 260: DPRINTFN(us < 5000 ? 4 : 2,
1.1 ratchov 261: "safile_write: %s: wrote %d bytes in %uus\n",
262: f->file.name, n, us);
263: #endif
264: return n;
265: }
266:
267: int
268: safile_nfds(struct file *file)
269: {
1.2 ratchov 270: return sio_nfds(((struct safile *)file)->hdl);
1.1 ratchov 271: }
272:
273: int
274: safile_pollfd(struct file *file, struct pollfd *pfd, int events)
275: {
1.2 ratchov 276: return sio_pollfd(((struct safile *)file)->hdl, pfd, events);
1.1 ratchov 277: }
278:
279: int
280: safile_revents(struct file *file, struct pollfd *pfd)
281: {
1.2 ratchov 282: return sio_revents(((struct safile *)file)->hdl, pfd);
1.1 ratchov 283: }
284:
285: void
286: safile_close(struct file *file)
287: {
1.15 ratchov 288: struct safile *f = (struct safile *)file;
289:
290: if (f->started)
291: safile_stop(&f->file);
1.2 ratchov 292: return sio_close(((struct safile *)file)->hdl);
1.1 ratchov 293: }