Annotation of src/usr.bin/aucat/safile.c, Revision 1.20
1.20 ! ratchov 1: /* $OpenBSD: safile.c,v 1.19 2009/11/05 08:36:48 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"
1.20 ! ratchov 33: #ifdef DEBUG
! 34: #include "dbg.h"
! 35: #endif
1.1 ratchov 36:
37: struct safile {
38: struct file file;
1.2 ratchov 39: struct sio_hdl *hdl;
1.15 ratchov 40: int started;
1.1 ratchov 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.18 ratchov 53: "sio",
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.19 ratchov 149: if (path == NULL)
150: path = "default";
151: f = (struct safile *)file_new(ops, path, sio_nfds(hdl));
1.11 ratchov 152: if (f == NULL)
153: goto bad_close;
1.1 ratchov 154: f->hdl = hdl;
1.15 ratchov 155: f->started = 0;
1.2 ratchov 156: sio_onmove(f->hdl, safile_cb, f);
1.1 ratchov 157: return f;
1.11 ratchov 158: bad_close:
159: sio_close(hdl);
160: return NULL;
1.1 ratchov 161: }
162:
163: void
164: safile_start(struct file *file)
1.10 ratchov 165: {
1.1 ratchov 166: struct safile *f = (struct safile *)file;
167:
1.2 ratchov 168: if (!sio_start(f->hdl)) {
1.20 ! ratchov 169: #ifdef DEBUG
! 170: dbg_puts(f->file.name);
! 171: dbg_puts(": failed to start device\n");
! 172: #endif
1.9 ratchov 173: file_close(file);
1.8 ratchov 174: return;
1.1 ratchov 175: }
1.15 ratchov 176: f->started = 1;
1.20 ! ratchov 177: #ifdef DEBUG
! 178: if (debug_level >= 3) {
! 179: file_dbg(&f->file);
! 180: dbg_puts(": started\n");
! 181: }
! 182: #endif
1.1 ratchov 183: }
184:
185: void
186: safile_stop(struct file *file)
187: {
188: struct safile *f = (struct safile *)file;
189:
1.16 ratchov 190: f->started = 0;
1.17 ratchov 191: if (!sio_eof(f->hdl) && !sio_stop(f->hdl)) {
1.20 ! ratchov 192: #ifdef DEBUG
! 193: dbg_puts(f->file.name);
! 194: dbg_puts(": failed to stop device\n");
! 195: #endif
1.9 ratchov 196: file_close(file);
1.8 ratchov 197: return;
1.1 ratchov 198: }
1.20 ! ratchov 199: #ifdef DEBUG
! 200: if (debug_level >= 3) {
! 201: file_dbg(&f->file);
! 202: dbg_puts(": stopped\n");
! 203: }
! 204: #endif
1.1 ratchov 205: }
206:
207: unsigned
208: safile_read(struct file *file, unsigned char *data, unsigned count)
209: {
210: struct safile *f = (struct safile *)file;
211: unsigned n;
1.18 ratchov 212:
1.2 ratchov 213: n = sio_read(f->hdl, data, count);
1.1 ratchov 214: if (n == 0) {
215: f->file.state &= ~FILE_ROK;
1.2 ratchov 216: if (sio_eof(f->hdl)) {
1.20 ! ratchov 217: #ifdef DEBUG
! 218: dbg_puts(f->file.name);
! 219: dbg_puts(": failed to read from device\n");
! 220: #endif
1.1 ratchov 221: file_eof(&f->file);
222: } else {
1.20 ! ratchov 223: #ifdef DEBUG
! 224: if (debug_level >= 4) {
! 225: file_dbg(&f->file);
! 226: dbg_puts(": reading blocked\n");
! 227: }
! 228: #endif
1.1 ratchov 229: }
230: return 0;
231: }
232: return n;
233:
234: }
235:
236: unsigned
237: safile_write(struct file *file, unsigned char *data, unsigned count)
238: {
239: struct safile *f = (struct safile *)file;
240: unsigned n;
1.18 ratchov 241:
1.2 ratchov 242: n = sio_write(f->hdl, data, count);
1.1 ratchov 243: if (n == 0) {
244: f->file.state &= ~FILE_WOK;
1.2 ratchov 245: if (sio_eof(f->hdl)) {
1.20 ! ratchov 246: #ifdef DEBUG
! 247: dbg_puts(f->file.name);
! 248: dbg_puts(": failed to write on device\n");
! 249: #endif
1.1 ratchov 250: file_hup(&f->file);
251: } else {
1.20 ! ratchov 252: #ifdef DEBUG
! 253: if (debug_level >= 4) {
! 254: file_dbg(&f->file);
! 255: dbg_puts(": writing blocked\n");
! 256: }
! 257: #endif
1.1 ratchov 258: }
259: return 0;
260: }
261: return n;
262: }
263:
264: int
265: safile_nfds(struct file *file)
266: {
1.2 ratchov 267: return sio_nfds(((struct safile *)file)->hdl);
1.1 ratchov 268: }
269:
270: int
271: safile_pollfd(struct file *file, struct pollfd *pfd, int events)
272: {
1.2 ratchov 273: return sio_pollfd(((struct safile *)file)->hdl, pfd, events);
1.1 ratchov 274: }
275:
276: int
277: safile_revents(struct file *file, struct pollfd *pfd)
278: {
1.2 ratchov 279: return sio_revents(((struct safile *)file)->hdl, pfd);
1.1 ratchov 280: }
281:
282: void
283: safile_close(struct file *file)
284: {
1.15 ratchov 285: struct safile *f = (struct safile *)file;
286:
287: if (f->started)
288: safile_stop(&f->file);
1.2 ratchov 289: return sio_close(((struct safile *)file)->hdl);
1.1 ratchov 290: }