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