Annotation of src/usr.bin/aucat/wav.c, Revision 1.32
1.7 ratchov 1: /*
2: * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
3: *
4: * Permission to use, copy, modify, and distribute this software for any
5: * purpose with or without fee is hereby granted, provided that the above
6: * copyright notice and this permission notice appear in all copies.
7: *
8: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15: */
16:
1.26 ratchov 17: #include <fcntl.h>
1.1 ratchov 18: #include <stdlib.h>
1.10 ratchov 19: #include <stdio.h>
1.26 ratchov 20: #include <string.h>
1.10 ratchov 21: #include <unistd.h>
1.1 ratchov 22:
1.10 ratchov 23: #include "abuf.h"
24: #include "aproc.h"
1.1 ratchov 25: #include "conf.h"
1.10 ratchov 26: #include "dev.h"
1.15 ratchov 27: #include "midi.h"
1.1 ratchov 28: #include "wav.h"
1.15 ratchov 29: #include "opt.h"
1.11 ratchov 30: #ifdef DEBUG
31: #include "dbg.h"
32: #endif
1.1 ratchov 33:
1.6 ratchov 34: short wav_ulawmap[256] = {
35: -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
36: -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
37: -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
38: -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
39: -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
40: -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
41: -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
42: -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
43: -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
44: -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
45: -876, -844, -812, -780, -748, -716, -684, -652,
46: -620, -588, -556, -524, -492, -460, -428, -396,
47: -372, -356, -340, -324, -308, -292, -276, -260,
48: -244, -228, -212, -196, -180, -164, -148, -132,
49: -120, -112, -104, -96, -88, -80, -72, -64,
50: -56, -48, -40, -32, -24, -16, -8, 0,
51: 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
52: 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
53: 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
54: 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
55: 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
56: 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
57: 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
58: 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
59: 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
60: 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
61: 876, 844, 812, 780, 748, 716, 684, 652,
62: 620, 588, 556, 524, 492, 460, 428, 396,
63: 372, 356, 340, 324, 308, 292, 276, 260,
64: 244, 228, 212, 196, 180, 164, 148, 132,
65: 120, 112, 104, 96, 88, 80, 72, 64,
66: 56, 48, 40, 32, 24, 16, 8, 0
67: };
68:
69: short wav_alawmap[256] = {
70: -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
71: -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
72: -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
73: -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
74: -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
75: -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
76: -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472,
77: -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
78: -344, -328, -376, -360, -280, -264, -312, -296,
79: -472, -456, -504, -488, -408, -392, -440, -424,
80: -88, -72, -120, -104, -24, -8, -56, -40,
81: -216, -200, -248, -232, -152, -136, -184, -168,
82: -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
83: -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
84: -688, -656, -752, -720, -560, -528, -624, -592,
85: -944, -912, -1008, -976, -816, -784, -880, -848,
86: 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
87: 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
88: 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
89: 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
90: 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
91: 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
92: 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
93: 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
94: 344, 328, 376, 360, 280, 264, 312, 296,
95: 472, 456, 504, 488, 408, 392, 440, 424,
96: 88, 72, 120, 104, 24, 8, 56, 40,
97: 216, 200, 248, 232, 152, 136, 184, 168,
98: 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
99: 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
100: 688, 656, 752, 720, 560, 528, 624, 592,
101: 944, 912, 1008, 976, 816, 784, 880, 848
102: };
103:
1.1 ratchov 104: /*
1.7 ratchov 105: * Max data of a .wav file. The total file size must be smaller than
1.1 ratchov 106: * 2^31, and we also have to leave some space for the headers (around 40
1.7 ratchov 107: * bytes).
1.3 ratchov 108: */
1.1 ratchov 109: #define WAV_DATAMAX (0x7fff0000)
110:
111: struct fileops wav_ops = {
112: "wav",
113: sizeof(struct wav),
114: wav_close,
115: wav_read,
116: wav_write,
117: NULL, /* start */
118: NULL, /* stop */
119: pipe_nfds,
120: pipe_pollfd,
121: pipe_revents
122: };
123:
1.27 ratchov 124: struct wav *wav_list = NULL;
125:
1.10 ratchov 126: int rwav_in(struct aproc *, struct abuf *);
127: int rwav_out(struct aproc *, struct abuf *);
128: void rwav_eof(struct aproc *, struct abuf *);
129: void rwav_hup(struct aproc *, struct abuf *);
130: void rwav_done(struct aproc *);
1.15 ratchov 131: struct aproc *rwav_new(struct file *);
1.10 ratchov 132:
133: int wwav_in(struct aproc *, struct abuf *);
134: int wwav_out(struct aproc *, struct abuf *);
135: void wwav_eof(struct aproc *, struct abuf *);
136: void wwav_hup(struct aproc *, struct abuf *);
137: void wwav_done(struct aproc *);
1.15 ratchov 138: struct aproc *wwav_new(struct file *);
139:
1.30 ratchov 140: void wav_setvol(void *, unsigned int);
1.15 ratchov 141: void wav_startreq(void *);
142: void wav_stopreq(void *);
1.30 ratchov 143: void wav_locreq(void *, unsigned int);
1.20 ratchov 144: void wav_quitreq(void *);
1.15 ratchov 145:
146: struct ctl_ops ctl_wavops = {
147: wav_setvol,
148: wav_startreq,
149: wav_stopreq,
1.20 ratchov 150: wav_locreq,
151: wav_quitreq
1.15 ratchov 152: };
1.10 ratchov 153:
154: struct aproc_ops rwav_ops = {
155: "rwav",
156: rwav_in,
157: rwav_out,
1.15 ratchov 158: rfile_eof,
159: rfile_hup,
1.10 ratchov 160: NULL, /* newin */
161: NULL, /* newout */
162: NULL, /* ipos */
163: NULL, /* opos */
164: rwav_done
165: };
166:
167: struct aproc_ops wwav_ops = {
168: "wwav",
169: wwav_in,
170: wwav_out,
1.15 ratchov 171: wfile_eof,
172: wfile_hup,
1.10 ratchov 173: NULL, /* newin */
174: NULL, /* newout */
175: NULL, /* ipos */
176: NULL, /* opos */
177: wwav_done
178: };
179:
1.15 ratchov 180: #ifdef DEBUG
181: /*
182: * print the given wav structure
183: */
184: void
185: wav_dbg(struct wav *f)
186: {
1.27 ratchov 187: static char *pstates[] = { "cfg", "ini", "sta", "rdy", "run", "mid" };
1.15 ratchov 188:
189: dbg_puts("wav(");
1.28 ratchov 190: if (f->slot >= 0) {
191: dbg_puts(f->dev->slot[f->slot].name);
192: dbg_putu(f->dev->slot[f->slot].unit);
1.15 ratchov 193: } else
194: dbg_puts(f->pipe.file.name);
195: dbg_puts(")/");
196: dbg_puts(pstates[f->pstate]);
197: }
198: #endif
199:
200: /*
201: * convert ``count'' samples using the given char->short map
202: */
203: void
1.30 ratchov 204: wav_conv(unsigned char *data, unsigned int count, short *map)
1.13 ratchov 205: {
1.30 ratchov 206: unsigned int i;
1.15 ratchov 207: unsigned char *iptr;
1.23 ratchov 208: adata_t *optr;
1.13 ratchov 209:
1.15 ratchov 210: iptr = data + count;
1.23 ratchov 211: optr = (adata_t *)data + count;
1.15 ratchov 212: for (i = count; i > 0; i--) {
213: --optr;
214: --iptr;
1.23 ratchov 215: *optr = (adata_t)(map[*iptr]) << (ADATA_BITS - 16);
1.15 ratchov 216: }
1.13 ratchov 217: }
218:
1.15 ratchov 219: /*
220: * read method of the file structure
221: */
1.30 ratchov 222: unsigned int
223: wav_read(struct file *file, unsigned char *data, unsigned int count)
1.10 ratchov 224: {
1.15 ratchov 225: struct wav *f = (struct wav *)file;
1.30 ratchov 226: unsigned int n;
1.15 ratchov 227:
228: if (f->map)
1.23 ratchov 229: count /= sizeof(adata_t);
1.15 ratchov 230: if (f->rbytes >= 0 && count > f->rbytes) {
231: count = f->rbytes; /* file->rbytes fits in count */
232: if (count == 0) {
233: #ifdef DEBUG
234: if (debug_level >= 3) {
235: wav_dbg(f);
236: dbg_puts(": read complete\n");
237: }
238: #endif
1.20 ratchov 239: if (!f->mmc)
1.15 ratchov 240: file_eof(&f->pipe.file);
241: return 0;
242: }
243: }
244: n = pipe_read(file, data, count);
245: if (n == 0)
1.14 ratchov 246: return 0;
1.15 ratchov 247: if (f->rbytes >= 0)
248: f->rbytes -= n;
249: if (f->map) {
250: wav_conv(data, n, f->map);
1.23 ratchov 251: n *= sizeof(adata_t);
1.15 ratchov 252: }
253: return n;
254: }
255:
256: /*
257: * write method of the file structure
258: */
1.30 ratchov 259: unsigned int
260: wav_write(struct file *file, unsigned char *data, unsigned int count)
1.15 ratchov 261: {
262: struct wav *f = (struct wav *)file;
1.30 ratchov 263: unsigned int n;
1.15 ratchov 264:
265: if (f->wbytes >= 0 && count > f->wbytes) {
266: count = f->wbytes; /* wbytes fits in count */
267: if (count == 0) {
268: #ifdef DEBUG
269: if (debug_level >= 3) {
270: wav_dbg(f);
271: dbg_puts(": write complete\n");
272: }
273: #endif
274: file_hup(&f->pipe.file);
275: return 0;
276: }
277: }
278: n = pipe_write(file, data, count);
279: if (f->wbytes >= 0)
280: f->wbytes -= n;
281: f->endpos += n;
282: return n;
283: }
284:
285: /*
286: * close method of the file structure
287: */
288: void
289: wav_close(struct file *file)
290: {
1.27 ratchov 291: struct wav *f = (struct wav *)file, **pf;
1.15 ratchov 292:
293: if (f->mode & MODE_RECMASK) {
294: pipe_trunc(&f->pipe.file, f->endpos);
295: if (f->hdr == HDR_WAV) {
296: wav_writehdr(f->pipe.fd,
297: &f->hpar,
298: &f->startpos,
299: f->endpos - f->startpos);
300: }
301: }
302: pipe_close(file);
1.27 ratchov 303: if (f->pstate != WAV_CFG)
1.20 ratchov 304: dev_unref(f->dev);
1.27 ratchov 305: for (pf = &wav_list; *pf != f; pf = &(*pf)->next) {
306: #ifdef DEBUG
307: if (*pf == NULL) {
308: dbg_puts("wav_close: not on list\n");
309: dbg_panic();
310: }
311: #endif
1.20 ratchov 312: }
1.27 ratchov 313: *pf = f->next;
1.10 ratchov 314: }
315:
1.15 ratchov 316: /*
317: * attach play (rec) abuf structure to the device and
318: * switch to the ``RUN'' state; the play abug must not be empty
319: */
1.14 ratchov 320: int
1.15 ratchov 321: wav_attach(struct wav *f, int force)
1.10 ratchov 322: {
1.15 ratchov 323: struct abuf *rbuf = NULL, *wbuf = NULL;
1.20 ratchov 324: struct dev *d = f->dev;
1.13 ratchov 325:
1.15 ratchov 326: if (f->mode & MODE_PLAY)
1.17 ratchov 327: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.15 ratchov 328: if (f->mode & MODE_RECMASK)
1.17 ratchov 329: wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
1.15 ratchov 330: f->pstate = WAV_RUN;
331: #ifdef DEBUG
332: if (debug_level >= 3) {
333: wav_dbg(f);
334: dbg_puts(": attaching\n");
335: }
336: #endif
1.18 ratchov 337:
338: /*
339: * start the device (dev_getpos() and dev_attach() must
340: * be called on a started device
341: */
1.20 ratchov 342: dev_wakeup(d);
1.18 ratchov 343:
1.20 ratchov 344: dev_attach(d, f->pipe.file.name, f->mode,
345: rbuf, &f->hpar, f->join ? d->opar.cmax - d->opar.cmin + 1 : 0,
346: wbuf, &f->hpar, f->join ? d->ipar.cmax - d->ipar.cmin + 1 : 0,
1.16 ratchov 347: f->xrun, f->maxweight);
1.15 ratchov 348: if (f->mode & MODE_PLAY)
1.20 ratchov 349: dev_setvol(d, rbuf, MIDI_TO_ADATA(f->vol));
1.14 ratchov 350: return 1;
1.13 ratchov 351: }
352:
1.15 ratchov 353: /*
1.27 ratchov 354: * allocate buffers, so client can start filling write-end.
355: */
356: void
357: wav_midiattach(struct wav *f)
358: {
359: struct abuf *rbuf = NULL, *wbuf = NULL;
360:
361: if (f->mode & MODE_MIDIOUT) {
362: rbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
363: aproc_setout(f->pipe.file.rproc, rbuf);
364: }
365: if (f->mode & MODE_MIDIIN) {
366: wbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
367: aproc_setin(f->pipe.file.wproc, wbuf);
368: }
369: f->pstate = WAV_MIDI;
370: dev_midiattach(f->dev, rbuf, wbuf);
371: }
372:
373: /*
1.15 ratchov 374: * allocate the play (rec) abuf structure; if this is a
375: * file to record, then attach it to the device
376: *
377: * XXX: buffer size should be larger than dev_bufsz, because
378: * in non-server mode we don't prime play buffers with
379: * silence
380: */
1.14 ratchov 381: void
1.15 ratchov 382: wav_allocbuf(struct wav *f)
1.13 ratchov 383: {
1.15 ratchov 384: struct abuf *buf;
1.20 ratchov 385: struct dev *d = f->dev;
1.30 ratchov 386: unsigned int nfr;
1.13 ratchov 387:
1.15 ratchov 388: f->pstate = WAV_START;
389: if (f->mode & MODE_PLAY) {
1.20 ratchov 390: nfr = 2 * d->bufsz * f->hpar.rate / d->rate;
1.15 ratchov 391: buf = abuf_new(nfr, &f->hpar);
392: aproc_setout(f->pipe.file.rproc, buf);
393: abuf_fill(buf);
394: if (!ABUF_WOK(buf) || (f->pipe.file.state & FILE_EOF))
395: f->pstate = WAV_READY;
396: }
397: if (f->mode & MODE_RECMASK) {
1.20 ratchov 398: nfr = 2 * d->bufsz * f->hpar.rate / d->rate;
1.15 ratchov 399: buf = abuf_new(nfr, &f->hpar);
400: aproc_setin(f->pipe.file.wproc, buf);
401: f->pstate = WAV_READY;
402: }
403: #ifdef DEBUG
404: if (debug_level >= 3) {
405: wav_dbg(f);
406: dbg_puts(": allocating buffers\n");
407: }
408: #endif
1.28 ratchov 409: if (f->pstate == WAV_READY && dev_slotstart(d, f->slot))
1.15 ratchov 410: (void)wav_attach(f, 0);
1.13 ratchov 411: }
412:
1.15 ratchov 413: /*
414: * free abuf structure and switch to the ``INIT'' state
415: */
1.13 ratchov 416: void
1.15 ratchov 417: wav_freebuf(struct wav *f)
1.10 ratchov 418: {
1.15 ratchov 419: struct abuf *rbuf = NULL, *wbuf = NULL;
420:
421: if (f->mode & MODE_PLAY)
1.17 ratchov 422: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.15 ratchov 423: if (f->mode & MODE_RECMASK)
1.17 ratchov 424: wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
1.15 ratchov 425: f->pstate = WAV_INIT;
426: #ifdef DEBUG
427: if (debug_level >= 3) {
428: wav_dbg(f);
429: dbg_puts(": freeing buffers\n");
430: }
431: #endif
432: if (rbuf || wbuf)
1.28 ratchov 433: dev_slotstop(f->dev, f->slot);
1.15 ratchov 434: if (rbuf)
435: abuf_eof(rbuf);
436: if (wbuf)
437: abuf_hup(wbuf);
1.10 ratchov 438: }
439:
1.15 ratchov 440: /*
441: * switch to the ``INIT'' state performing
442: * necessary actions to reach it
443: */
1.10 ratchov 444: void
1.15 ratchov 445: wav_reset(struct wav *f)
1.10 ratchov 446: {
1.15 ratchov 447: switch (f->pstate) {
448: case WAV_START:
449: case WAV_READY:
1.28 ratchov 450: if (dev_slotstart(f->dev, f->slot))
1.15 ratchov 451: (void)wav_attach(f, 1);
452: /* PASSTHROUGH */
453: case WAV_RUN:
454: wav_freebuf(f);
455: /* PASSTHROUGH */
456: case WAV_INIT:
457: /* nothing yet */
458: break;
1.31 ratchov 459: #ifdef DEBUG
1.27 ratchov 460: case WAV_MIDI:
461: dbg_puts("wav_reset: in midi mode\n");
462: dbg_panic();
1.31 ratchov 463: #endif
1.15 ratchov 464: }
1.10 ratchov 465: }
466:
1.15 ratchov 467: /*
468: * terminate the wav reader/writer
469: */
470: void
471: wav_exit(struct wav *f)
1.10 ratchov 472: {
1.20 ratchov 473: /* XXX: call file_close() ? */
1.27 ratchov 474: if (f->mode & (MODE_PLAY | MODE_MIDIOUT)) {
1.15 ratchov 475: aproc_del(f->pipe.file.rproc);
1.27 ratchov 476: } else if (f->mode & (MODE_RECMASK | MODE_MIDIIN)) {
1.15 ratchov 477: aproc_del(f->pipe.file.wproc);
478: }
1.10 ratchov 479: }
480:
1.15 ratchov 481: /*
1.27 ratchov 482: * allocate the device
483: */
484: int
485: wav_init(struct wav *f)
486: {
487: if (!dev_ref(f->dev)) {
488: wav_exit(f);
489: return 0;
490: }
491: if (!f->mmc)
492: f->dev->autostart = 1;
493: if (f->mode & MODE_MIDIMASK) {
494: wav_midiattach(f);
495: return 1;
496: }
1.28 ratchov 497: f->slot = dev_slotnew(f->dev, "wav", &ctl_wavops, f, 1);
1.27 ratchov 498: f->pstate = WAV_INIT;
499: if ((f->mode & f->dev->mode) != f->mode) {
500: #ifdef DEBUG
501: if (debug_level >= 1) {
502: wav_dbg(f);
503: dbg_puts(": ");
504: dbg_puts(": operation not supported by device\n");
505: }
506: #endif
507: wav_exit(f);
508: return 0;
509: }
510: wav_allocbuf(f);
511: return 1;
512: }
513:
514: /*
1.15 ratchov 515: * seek to f->mmcpos and prepare to start, close
516: * the file on error.
517: */
518: int
519: wav_seekmmc(struct wav *f)
1.10 ratchov 520: {
521: /*
1.15 ratchov 522: * don't go beyond the end-of-file, if so
523: * put it in INIT state so it dosn't start
1.10 ratchov 524: */
1.27 ratchov 525: if (f->mmcpos > f->endpos && !(f->mode & MODE_RECMASK)) {
1.15 ratchov 526: wav_reset(f);
527: /*
528: * don't make other stream wait for us
529: */
530: if (f->slot >= 0)
1.28 ratchov 531: dev_slotstart(f->dev, f->slot);
1.15 ratchov 532: return 0;
533: }
534: if (!pipe_seek(&f->pipe.file, f->mmcpos)) {
535: wav_exit(f);
536: return 0;
537: }
1.28 ratchov 538: if ((f->mode & MODE_RECMASK) && f->mmcpos > f->endpos)
1.27 ratchov 539: f->endpos = f->mmcpos;
1.15 ratchov 540: if (f->hdr == HDR_WAV)
541: f->wbytes = WAV_DATAMAX - f->mmcpos;
542: f->rbytes = f->endpos - f->mmcpos;
543: wav_reset(f);
544: wav_allocbuf(f);
545: return 1;
1.10 ratchov 546: }
547:
1.15 ratchov 548: /*
549: * read samples from the file and possibly start it
550: */
1.10 ratchov 551: int
1.15 ratchov 552: wav_rdata(struct wav *f)
1.10 ratchov 553: {
1.15 ratchov 554: struct aproc *p;
555: struct abuf *obuf;
1.10 ratchov 556:
1.15 ratchov 557: p = f->pipe.file.rproc;
1.17 ratchov 558: obuf = LIST_FIRST(&p->outs);
1.15 ratchov 559: if (obuf == NULL)
1.10 ratchov 560: return 0;
1.15 ratchov 561: if (!ABUF_WOK(obuf) || !(f->pipe.file.state & FILE_ROK))
1.10 ratchov 562: return 0;
1.15 ratchov 563: if (!rfile_do(p, obuf->len, NULL))
1.10 ratchov 564: return 0;
1.15 ratchov 565: switch (f->pstate) {
566: case WAV_START:
567: if (!ABUF_WOK(obuf) || (f->pipe.file.state & FILE_EOF))
568: f->pstate = WAV_READY;
569: /* PASSTHROUGH */
570: case WAV_READY:
1.28 ratchov 571: if (dev_slotstart(f->dev, f->slot))
1.15 ratchov 572: (void)wav_attach(f, 0);
573: break;
574: case WAV_RUN:
575: break;
1.27 ratchov 576: case WAV_MIDI:
577: return 1;
578: #ifdef DEBUG
1.15 ratchov 579: default:
580: wav_dbg(f);
581: dbg_puts(": bad state\n");
582: dbg_panic();
583: #endif
584: }
1.20 ratchov 585: if (f->rbytes == 0 && f->mmc) {
1.15 ratchov 586: #ifdef DEBUG
587: if (debug_level >= 3) {
588: wav_dbg(f);
589: dbg_puts(": trying to restart\n");
590: }
591: #endif
592: if (!wav_seekmmc(f))
593: return 0;
594: }
1.10 ratchov 595: return 1;
596: }
597:
598: int
1.15 ratchov 599: wav_wdata(struct wav *f)
1.10 ratchov 600: {
1.15 ratchov 601: struct aproc *p;
602: struct abuf *ibuf;
1.10 ratchov 603:
1.15 ratchov 604: if (!(f->pipe.file.state & FILE_WOK))
1.10 ratchov 605: return 0;
1.15 ratchov 606: p = f->pipe.file.wproc;
1.17 ratchov 607: ibuf = LIST_FIRST(&p->ins);
1.15 ratchov 608: if (ibuf == NULL)
1.10 ratchov 609: return 0;
1.15 ratchov 610: if (!ABUF_ROK(ibuf))
1.10 ratchov 611: return 0;
1.15 ratchov 612: if (!wfile_do(p, ibuf->len, NULL))
1.10 ratchov 613: return 0;
614: return 1;
615: }
616:
1.15 ratchov 617: /*
618: * callback to set the volume, invoked by the MIDI control code
619: */
620: void
1.30 ratchov 621: wav_setvol(void *arg, unsigned int vol)
1.15 ratchov 622: {
623: struct wav *f = (struct wav *)arg;
624: struct abuf *rbuf;
625:
626: f->vol = vol;
627: if ((f->mode & MODE_PLAY) && f->pstate == WAV_RUN) {
1.17 ratchov 628: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.20 ratchov 629: dev_setvol(f->dev, rbuf, MIDI_TO_ADATA(vol));
1.15 ratchov 630: }
631: }
632:
633: /*
634: * callback to start the stream, invoked by the MIDI control code
635: */
636: void
637: wav_startreq(void *arg)
638: {
639: struct wav *f = (struct wav *)arg;
640:
641: switch (f->pstate) {
1.27 ratchov 642: case WAV_INIT:
1.15 ratchov 643: #ifdef DEBUG
644: if (debug_level >= 2) {
645: wav_dbg(f);
646: dbg_puts(": skipped (failed to seek)\n");
647: }
648: #endif
649: return;
650: case WAV_READY:
651: if (f->mode & MODE_RECMASK)
1.27 ratchov 652: f->endpos = f->mmcpos + f->startpos;
1.15 ratchov 653: (void)wav_attach(f, 0);
654: break;
655: #ifdef DEBUG
656: default:
657: wav_dbg(f);
658: dbg_puts(": not in READY state\n");
659: dbg_panic();
660: break;
661: #endif
662: }
663: }
664:
665: /*
666: * callback to stop the stream, invoked by the MIDI control code
667: */
1.10 ratchov 668: void
1.15 ratchov 669: wav_stopreq(void *arg)
1.10 ratchov 670: {
1.15 ratchov 671: struct wav *f = (struct wav *)arg;
672:
673: #ifdef DEBUG
674: if (debug_level >= 2) {
675: wav_dbg(f);
676: dbg_puts(": stopping");
1.27 ratchov 677: if (f->pstate != WAV_INIT && (f->mode & MODE_RECMASK)) {
1.15 ratchov 678: dbg_puts(", ");
679: dbg_putu(f->endpos);
680: dbg_puts(" bytes recorded");
681: }
682: dbg_puts("\n");
683: }
684: #endif
1.20 ratchov 685: if (!f->mmc) {
1.15 ratchov 686: wav_exit(f);
687: return;
688: }
689: (void)wav_seekmmc(f);
1.10 ratchov 690: }
691:
1.15 ratchov 692: /*
693: * callback to relocate the stream, invoked by the MIDI control code
694: * on a stopped stream
695: */
1.10 ratchov 696: void
1.30 ratchov 697: wav_locreq(void *arg, unsigned int mmc)
1.10 ratchov 698: {
1.15 ratchov 699: struct wav *f = (struct wav *)arg;
700:
701: #ifdef DEBUG
702: if (f->pstate == WAV_RUN) {
703: wav_dbg(f);
704: dbg_puts(": in RUN state\n");
705: dbg_panic();
706: }
707: #endif
708: f->mmcpos = f->startpos +
709: ((off_t)mmc * f->hpar.rate / MTC_SEC) * aparams_bpf(&f->hpar);
710: (void)wav_seekmmc(f);
1.10 ratchov 711: }
712:
1.15 ratchov 713: /*
1.20 ratchov 714: * Callback invoked when slot is gone
715: */
716: void
717: wav_quitreq(void *arg)
718: {
719: struct wav *f = (struct wav *)arg;
720:
721: #ifdef DEBUG
722: if (debug_level >= 3) {
723: wav_dbg(f);
724: dbg_puts(": slot gone\n");
725: }
726: #endif
727: if (f->pstate != WAV_RUN)
728: wav_exit(f);
729: }
730:
731: /*
1.26 ratchov 732: * determine the header by the file name
733: */
1.27 ratchov 734: int
1.30 ratchov 735: wav_autohdr(char *name, struct dev *dev, unsigned int *hdr, unsigned int *mode)
1.26 ratchov 736: {
1.27 ratchov 737: char *ext;
1.26 ratchov 738:
1.27 ratchov 739: if (dev->reqmode & MODE_THRU)
740: *mode &= MODE_MIDIMASK;
741: if (*hdr == HDR_AUTO) {
742: ext = strrchr(name, '.');
743: if (ext != NULL) {
744: ext++;
745: if (strcasecmp(ext, "wav") == 0) {
746: *hdr = HDR_WAV;
747: *mode &= ~MODE_MIDIMASK;
748: } else if (strcasecmp(ext, "syx") == 0) {
1.29 ratchov 749: *hdr = HDR_RAW;
1.27 ratchov 750: *mode &= ~MODE_AUDIOMASK;
751: }
752: } else
753: *hdr = HDR_RAW;
754: }
755: if (*mode & MODE_AUDIOMASK)
756: *mode &= ~MODE_MIDIMASK;
757: if (*mode == 0) {
758: #ifdef DEBUG
759: if (debug_level >= 1) {
760: dbg_puts(name);
761: dbg_puts(": requested mode not supported\n");
762: }
763: #endif
764: return 0;
765: }
766: return 1;
1.26 ratchov 767: }
768:
769: /*
1.15 ratchov 770: * create a file reader in the ``INIT'' state
771: */
1.1 ratchov 772: struct wav *
1.27 ratchov 773: wav_new_in(struct fileops *ops, struct dev *dev,
1.30 ratchov 774: unsigned int mode, char *name, unsigned int hdr,
775: struct aparams *par, unsigned int xrun,
776: unsigned int volctl, int mmc, int join)
1.1 ratchov 777: {
1.10 ratchov 778: int fd;
1.1 ratchov 779: struct wav *f;
1.10 ratchov 780:
1.27 ratchov 781: if (!wav_autohdr(name, dev, &hdr, &mode))
782: return NULL;
783: if (strcmp(name, "-") == 0) {
784: fd = STDIN_FILENO;
785: if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
786: perror(name);
787: } else {
1.10 ratchov 788: fd = open(name, O_RDONLY | O_NONBLOCK, 0666);
789: if (fd < 0) {
790: perror(name);
791: return NULL;
792: }
793: }
1.1 ratchov 794: f = (struct wav *)pipe_new(ops, fd, name);
1.18 ratchov 795: if (f == NULL) {
796: close(fd);
797: return NULL;
798: }
1.32 ! ratchov 799: f->mode = mode;
1.27 ratchov 800: f->pstate = WAV_CFG;
1.32 ! ratchov 801: f->endpos = f->startpos = 0;
! 802: f->next = wav_list;
! 803: wav_list = f;
1.1 ratchov 804: if (hdr == HDR_WAV) {
1.27 ratchov 805: if (!wav_readhdr(f->pipe.fd, par,
806: &f->startpos, &f->rbytes, &f->map)) {
1.10 ratchov 807: file_del((struct file *)f);
808: return NULL;
809: }
1.15 ratchov 810: f->endpos = f->startpos + f->rbytes;
1.6 ratchov 811: } else {
1.15 ratchov 812: f->endpos = pipe_endpos(&f->pipe.file);
813: if (f->endpos > 0) {
814: if (!pipe_seek(&f->pipe.file, 0)) {
815: file_del((struct file *)f);
816: return NULL;
817: }
818: f->rbytes = f->endpos;
819: } else
820: f->rbytes = -1;
1.6 ratchov 821: f->map = NULL;
822: }
1.27 ratchov 823: f->dev = dev;
824: f->mmc = mmc;
1.16 ratchov 825: f->join = join;
1.15 ratchov 826: f->mode = mode;
827: f->hpar = *par;
1.26 ratchov 828: f->hdr = hdr;
1.15 ratchov 829: f->xrun = xrun;
830: f->maxweight = MIDI_TO_ADATA(volctl);
1.27 ratchov 831: f->slot = -1;
1.15 ratchov 832: rwav_new((struct file *)f);
1.12 ratchov 833: #ifdef DEBUG
834: if (debug_level >= 2) {
835: dbg_puts(name);
1.27 ratchov 836: dbg_puts(":");
837: if (f->mode & MODE_PLAY) {
838: dbg_puts(" playing ");
839: aparams_dbg(par);
840: dbg_puts(" ");
841: dbg_putu(f->startpos);
842: dbg_puts("..");
843: dbg_putu(f->endpos);
844: if (f->mmc)
845: dbg_puts(", mmc");
846: }
847: if (f->mode & MODE_MIDIOUT)
848: dbg_puts(" midi/out");
1.12 ratchov 849: dbg_puts("\n");
850: }
851: #endif
1.1 ratchov 852: return f;
853: }
854:
1.15 ratchov 855: /*
856: * create a file writer in the ``INIT'' state
857: */
1.1 ratchov 858: struct wav *
1.27 ratchov 859: wav_new_out(struct fileops *ops, struct dev *dev,
1.30 ratchov 860: unsigned int mode, char *name, unsigned int hdr,
861: struct aparams *par, unsigned int xrun, int mmc, int join)
1.1 ratchov 862: {
1.10 ratchov 863: int fd;
1.1 ratchov 864: struct wav *f;
1.10 ratchov 865:
1.27 ratchov 866: if (!wav_autohdr(name, dev, &hdr, &mode))
867: return NULL;
868: if (strcmp(name, "-") == 0) {
1.10 ratchov 869: fd = STDOUT_FILENO;
870: if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
871: perror(name);
872: } else {
873: fd = open(name,
874: O_WRONLY | O_TRUNC | O_CREAT | O_NONBLOCK, 0666);
875: if (fd < 0) {
876: perror(name);
877: return NULL;
878: }
879: }
1.1 ratchov 880: f = (struct wav *)pipe_new(ops, fd, name);
1.18 ratchov 881: if (f == NULL) {
882: close(fd);
1.4 ratchov 883: return NULL;
1.18 ratchov 884: }
1.32 ! ratchov 885: f->mode = mode;
1.27 ratchov 886: f->pstate = WAV_CFG;
1.32 ! ratchov 887: f->endpos = f->startpos = 0;
! 888: f->next = wav_list;
! 889: wav_list = f;
1.1 ratchov 890: if (hdr == HDR_WAV) {
1.2 ratchov 891: par->le = 1;
1.3 ratchov 892: par->sig = (par->bits <= 8) ? 0 : 1;
1.2 ratchov 893: par->bps = (par->bits + 7) / 8;
1.15 ratchov 894: if (!wav_writehdr(f->pipe.fd, par, &f->startpos, 0)) {
1.10 ratchov 895: file_del((struct file *)f);
896: return NULL;
897: }
1.1 ratchov 898: f->wbytes = WAV_DATAMAX;
1.15 ratchov 899: f->endpos = f->startpos;
1.32 ! ratchov 900: } else
1.1 ratchov 901: f->wbytes = -1;
1.27 ratchov 902: f->dev = dev;
903: f->mmc = mmc;
1.16 ratchov 904: f->join = join;
1.15 ratchov 905: f->hpar = *par;
1.1 ratchov 906: f->hdr = hdr;
1.15 ratchov 907: f->xrun = xrun;
908: wwav_new((struct file *)f);
1.12 ratchov 909: #ifdef DEBUG
910: if (debug_level >= 2) {
911: dbg_puts(name);
1.27 ratchov 912: dbg_puts(":");
913: if (f->mode & MODE_RECMASK) {
914: dbg_puts(" recording ");
915: aparams_dbg(par);
916: if (f->mmc)
917: dbg_puts(", mmc");
918: }
919: if (f->mode & MODE_MIDIIN)
920: dbg_puts(" midi/in");
1.12 ratchov 921: dbg_puts("\n");
922: }
923: #endif
1.27 ratchov 924: f->next = wav_list;
925: wav_list = f;
1.1 ratchov 926: return f;
927: }
928:
1.6 ratchov 929: void
1.15 ratchov 930: rwav_done(struct aproc *p)
931: {
932: struct wav *f = (struct wav *)p->u.io.file;
933:
934: if (f->slot >= 0)
1.28 ratchov 935: dev_slotdel(f->dev, f->slot);
1.15 ratchov 936: f->slot = -1;
937: rfile_done(p);
938: }
939:
940: int
941: rwav_in(struct aproc *p, struct abuf *ibuf_dummy)
1.13 ratchov 942: {
1.15 ratchov 943: struct wav *f = (struct wav *)p->u.io.file;
944: struct abuf *obuf;
1.13 ratchov 945:
1.15 ratchov 946: if (!wav_rdata(f))
947: return 0;
1.17 ratchov 948: obuf = LIST_FIRST(&p->outs);
1.15 ratchov 949: if (obuf && f->pstate >= WAV_RUN) {
950: if (!abuf_flush(obuf))
951: return 0;
1.6 ratchov 952: }
1.15 ratchov 953: return 1;
1.6 ratchov 954: }
955:
1.15 ratchov 956: int
957: rwav_out(struct aproc *p, struct abuf *obuf)
1.1 ratchov 958: {
1.15 ratchov 959: struct wav *f = (struct wav *)p->u.io.file;
1.1 ratchov 960:
1.15 ratchov 961: if (f->pipe.file.state & FILE_RINUSE)
962: return 0;
963: for (;;) {
964: if (!wav_rdata(f))
1.1 ratchov 965: return 0;
966: }
1.15 ratchov 967: return 1;
968: }
969:
970: struct aproc *
971: rwav_new(struct file *f)
972: {
973: struct aproc *p;
974:
975: p = aproc_new(&rwav_ops, f->name);
976: p->u.io.file = f;
1.24 deraadt 977: p->u.io.partial = 0;
1.15 ratchov 978: f->rproc = p;
979: return p;
980: }
981:
982: void
983: wwav_done(struct aproc *p)
984: {
985: struct wav *f = (struct wav *)p->u.io.file;
986:
987: if (f->slot >= 0)
1.28 ratchov 988: dev_slotdel(f->dev, f->slot);
1.15 ratchov 989: f->slot = -1;
990: wfile_done(p);
991: }
992:
993: int
994: wwav_in(struct aproc *p, struct abuf *ibuf)
995: {
996: struct wav *f = (struct wav *)p->u.io.file;
997:
998: if (f->pipe.file.state & FILE_WINUSE)
1.8 jakemsr 999: return 0;
1.15 ratchov 1000: for (;;) {
1001: if (!wav_wdata(f))
1002: return 0;
1.6 ratchov 1003: }
1.15 ratchov 1004: return 1;
1.1 ratchov 1005: }
1006:
1.15 ratchov 1007: int
1008: wwav_out(struct aproc *p, struct abuf *obuf_dummy)
1.1 ratchov 1009: {
1.17 ratchov 1010: struct abuf *ibuf = LIST_FIRST(&p->ins);
1.15 ratchov 1011: struct wav *f = (struct wav *)p->u.io.file;
1.3 ratchov 1012:
1.15 ratchov 1013: if (ibuf && f->pstate == WAV_RUN) {
1014: if (!abuf_fill(ibuf))
1.1 ratchov 1015: return 0;
1016: }
1.15 ratchov 1017: if (!wav_wdata(f))
1018: return 0;
1019: return 1;
1.1 ratchov 1020: }
1021:
1.15 ratchov 1022: struct aproc *
1023: wwav_new(struct file *f)
1.1 ratchov 1024: {
1.15 ratchov 1025: struct aproc *p;
1.1 ratchov 1026:
1.15 ratchov 1027: p = aproc_new(&wwav_ops, f->name);
1028: p->u.io.file = f;
1.24 deraadt 1029: p->u.io.partial = 0;
1.15 ratchov 1030: f->wproc = p;
1031: return p;
1.1 ratchov 1032: }