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