Annotation of src/usr.bin/aucat/safile.c, Revision 1.11
1.11 ! ratchov 1: /* $OpenBSD: safile.c,v 1.10 2009/01/23 17:38:15 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:
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>
1.2 ratchov 25: #include <sndio.h>
1.1 ratchov 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;
1.2 ratchov 36: struct sio_hdl *hdl;
1.10 ratchov 37: #ifdef DEBUG
1.1 ratchov 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 = {
1.3 ratchov 52: "sndio",
1.1 ratchov 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,
1.5 ratchov 88: unsigned *bufsz, unsigned *round)
1.1 ratchov 89: {
1.2 ratchov 90: struct sio_par par;
91: struct sio_hdl *hdl;
1.1 ratchov 92: struct safile *f;
93: int mode;
94:
95: mode = 0;
96: if (ipar)
1.2 ratchov 97: mode |= SIO_REC;
1.1 ratchov 98: if (opar)
1.2 ratchov 99: mode |= SIO_PLAY;
1.4 ratchov 100: if (!mode) {
101: fprintf(stderr, "select at least play or record mode\n");
102: return NULL;
103: }
1.2 ratchov 104: hdl = sio_open(path, mode, 1);
1.1 ratchov 105: if (hdl == NULL) {
106: fprintf(stderr, "safile_new: can't open device\n");
107: return NULL;
108: }
1.2 ratchov 109: sio_initpar(&par);
1.1 ratchov 110: if (ipar) {
111: par.bits = ipar->bits;
112: par.bps = ipar->bps;
113: par.sig = ipar->sig;
114: par.le = ipar->le;
115: par.msb = ipar->msb;
116: par.rate = ipar->rate;
117: par.rchan = ipar->cmax - ipar->cmin + 1;
118: } else {
119: par.bits = opar->bits;
120: par.bps = opar->bps;
121: par.sig = opar->sig;
122: par.le = opar->le;
123: par.msb = opar->msb;
124: par.rate = opar->rate;
125: }
126: if (opar)
127: par.pchan = opar->cmax - opar->cmin + 1;
1.6 ratchov 128: par.appbufsz = *bufsz;
1.3 ratchov 129: par.round = *round;
1.5 ratchov 130: if (!sio_setpar(hdl, &par))
1.11 ! ratchov 131: goto bad_close;
1.5 ratchov 132: if (!sio_getpar(hdl, &par))
1.11 ! ratchov 133: goto bad_close;
1.1 ratchov 134: if (ipar) {
135: ipar->bits = par.bits;
136: ipar->bps = par.bps;
137: ipar->sig = par.sig;
138: ipar->le = par.le;
139: ipar->msb = par.msb;
140: ipar->rate = par.rate;
1.7 ratchov 141: ipar->cmax = ipar->cmin + par.rchan - 1;
1.1 ratchov 142: }
143: if (opar) {
144: opar->bits = par.bits;
145: opar->bps = par.bps;
146: opar->sig = par.sig;
147: opar->le = par.le;
148: opar->msb = par.msb;
149: opar->rate = par.rate;
1.7 ratchov 150: opar->cmax = opar->cmin + par.pchan - 1;
1.1 ratchov 151: }
152: *bufsz = par.bufsz;
153: *round = par.round;
1.3 ratchov 154: DPRINTF("safile_new: using %u(%u) fpb\n", *bufsz, *round);
1.2 ratchov 155: f = (struct safile *)file_new(ops, "hdl", sio_nfds(hdl));
1.11 ! ratchov 156: if (f == NULL)
! 157: goto bad_close;
1.1 ratchov 158: f->hdl = hdl;
1.2 ratchov 159: sio_onmove(f->hdl, safile_cb, f);
1.1 ratchov 160: return f;
1.11 ! ratchov 161: bad_close:
! 162: sio_close(hdl);
! 163: return NULL;
1.1 ratchov 164: }
165:
166: void
167: safile_start(struct file *file)
1.10 ratchov 168: {
1.1 ratchov 169: struct safile *f = (struct safile *)file;
170:
1.2 ratchov 171: if (!sio_start(f->hdl)) {
1.8 ratchov 172: DPRINTF("safile_start: sio_start() failed\n");
1.9 ratchov 173: file_close(file);
1.8 ratchov 174: return;
1.1 ratchov 175: }
176: DPRINTF("safile_start: play/rec started\n");
177: }
178:
179: void
180: safile_stop(struct file *file)
181: {
182: struct safile *f = (struct safile *)file;
183:
1.2 ratchov 184: if (!sio_stop(f->hdl)) {
1.8 ratchov 185: DPRINTF("safile_stop: sio_stop() filed\n");
1.9 ratchov 186: file_close(file);
1.8 ratchov 187: return;
1.1 ratchov 188: }
189: DPRINTF("safile_stop: play/rec stopped\n");
190: }
191:
192: unsigned
193: safile_read(struct file *file, unsigned char *data, unsigned count)
194: {
195: struct safile *f = (struct safile *)file;
196: unsigned n;
197: #ifdef DEBUG
198: struct timeval tv0, tv1, dtv;
199: unsigned us;
200:
201: if (!(f->file.state & FILE_ROK)) {
202: DPRINTF("file_read: %s: bad state\n", f->file.name);
203: abort();
204: }
205: gettimeofday(&tv0, NULL);
206: #endif
1.2 ratchov 207: n = sio_read(f->hdl, data, count);
1.1 ratchov 208: if (n == 0) {
209: f->file.state &= ~FILE_ROK;
1.2 ratchov 210: if (sio_eof(f->hdl)) {
1.1 ratchov 211: fprintf(stderr, "safile_read: eof\n");
212: file_eof(&f->file);
213: } else {
214: DPRINTFN(3, "safile_read: %s: blocking...\n",
215: f->file.name);
216: }
217: return 0;
218: }
219: #ifdef DEBUG
220: gettimeofday(&tv1, NULL);
221: timersub(&tv1, &tv0, &dtv);
1.10 ratchov 222: us = dtv.tv_sec * 1000000 + dtv.tv_usec;
1.1 ratchov 223: DPRINTFN(us < 5000 ? 4 : 1,
1.10 ratchov 224: "safile_read: %s: got %d bytes in %uus\n",
1.1 ratchov 225: f->file.name, n, us);
226: #endif
227: return n;
228:
229: }
230:
231: unsigned
232: safile_write(struct file *file, unsigned char *data, unsigned count)
233: {
234: struct safile *f = (struct safile *)file;
235: unsigned n;
236: #ifdef DEBUG
237: struct timeval tv0, tv1, dtv;
238: unsigned us;
1.10 ratchov 239:
1.1 ratchov 240: if (!(f->file.state & FILE_WOK)) {
241: DPRINTF("safile_write: %s: bad state\n", f->file.name);
242: abort();
243: }
244: gettimeofday(&tv0, NULL);
245: #endif
1.2 ratchov 246: n = sio_write(f->hdl, data, count);
1.1 ratchov 247: if (n == 0) {
248: f->file.state &= ~FILE_WOK;
1.2 ratchov 249: if (sio_eof(f->hdl)) {
1.1 ratchov 250: fprintf(stderr, "safile_write: %s: hup\n", f->file.name);
251: file_hup(&f->file);
252: } else {
253: DPRINTFN(3, "safile_write: %s: blocking...\n",
254: f->file.name);
255: }
256: return 0;
257: }
258: #ifdef DEBUG
259: gettimeofday(&tv1, NULL);
260: timersub(&tv1, &tv0, &dtv);
1.10 ratchov 261: us = dtv.tv_sec * 1000000 + dtv.tv_usec;
1.1 ratchov 262: DPRINTFN(us < 5000 ? 4 : 1,
263: "safile_write: %s: wrote %d bytes in %uus\n",
264: f->file.name, n, us);
265: #endif
266: return n;
267: }
268:
269: int
270: safile_nfds(struct file *file)
271: {
1.2 ratchov 272: return sio_nfds(((struct safile *)file)->hdl);
1.1 ratchov 273: }
274:
275: int
276: safile_pollfd(struct file *file, struct pollfd *pfd, int events)
277: {
1.2 ratchov 278: return sio_pollfd(((struct safile *)file)->hdl, pfd, events);
1.1 ratchov 279: }
280:
281: int
282: safile_revents(struct file *file, struct pollfd *pfd)
283: {
1.2 ratchov 284: return sio_revents(((struct safile *)file)->hdl, pfd);
1.1 ratchov 285: }
286:
287: void
288: safile_close(struct file *file)
289: {
1.2 ratchov 290: return sio_close(((struct safile *)file)->hdl);
1.1 ratchov 291: }