Annotation of src/usr.bin/aucat/wav.c, Revision 1.19
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);
141:
142: struct ctl_ops ctl_wavops = {
143: wav_setvol,
144: wav_startreq,
145: wav_stopreq,
146: wav_locreq
147: };
1.10 ratchov 148:
149: struct aproc_ops rwav_ops = {
150: "rwav",
151: rwav_in,
152: rwav_out,
1.15 ratchov 153: rfile_eof,
154: rfile_hup,
1.10 ratchov 155: NULL, /* newin */
156: NULL, /* newout */
157: NULL, /* ipos */
158: NULL, /* opos */
159: rwav_done
160: };
161:
162: struct aproc_ops wwav_ops = {
163: "wwav",
164: wwav_in,
165: wwav_out,
1.15 ratchov 166: wfile_eof,
167: wfile_hup,
1.10 ratchov 168: NULL, /* newin */
169: NULL, /* newout */
170: NULL, /* ipos */
171: NULL, /* opos */
172: wwav_done
173: };
174:
1.15 ratchov 175: #ifdef DEBUG
176: /*
177: * print the given wav structure
178: */
179: void
180: wav_dbg(struct wav *f)
181: {
182: static char *pstates[] = { "ini", "sta", "rdy", "run", "fai" };
183:
184: dbg_puts("wav(");
185: if (f->slot >= 0 && APROC_OK(dev_midi)) {
186: dbg_puts(dev_midi->u.ctl.slot[f->slot].name);
187: dbg_putu(dev_midi->u.ctl.slot[f->slot].unit);
188: } else
189: dbg_puts(f->pipe.file.name);
190: dbg_puts(")/");
191: dbg_puts(pstates[f->pstate]);
192: }
193: #endif
194:
195: /*
196: * convert ``count'' samples using the given char->short map
197: */
198: void
199: wav_conv(unsigned char *data, unsigned count, short *map)
1.13 ratchov 200: {
1.15 ratchov 201: unsigned i;
202: unsigned char *iptr;
203: short *optr;
1.13 ratchov 204:
1.15 ratchov 205: iptr = data + count;
206: optr = (short *)data + count;
207: for (i = count; i > 0; i--) {
208: --optr;
209: --iptr;
210: *optr = map[*iptr];
211: }
1.13 ratchov 212: }
213:
1.15 ratchov 214: /*
215: * read method of the file structure
216: */
217: unsigned
218: wav_read(struct file *file, unsigned char *data, unsigned count)
1.10 ratchov 219: {
1.15 ratchov 220: struct wav *f = (struct wav *)file;
221: unsigned n;
222:
223: if (f->map)
224: count /= sizeof(short);
225: if (f->rbytes >= 0 && count > f->rbytes) {
226: count = f->rbytes; /* file->rbytes fits in count */
227: if (count == 0) {
228: #ifdef DEBUG
229: if (debug_level >= 3) {
230: wav_dbg(f);
231: dbg_puts(": read complete\n");
232: }
233: #endif
234: if (!f->tr)
235: file_eof(&f->pipe.file);
236: return 0;
237: }
238: }
239: n = pipe_read(file, data, count);
240: if (n == 0)
1.14 ratchov 241: return 0;
1.15 ratchov 242: if (f->rbytes >= 0)
243: f->rbytes -= n;
244: if (f->map) {
245: wav_conv(data, n, f->map);
246: n *= sizeof(short);
247: }
248: return n;
249: }
250:
251: /*
252: * write method of the file structure
253: */
254: unsigned
255: wav_write(struct file *file, unsigned char *data, unsigned count)
256: {
257: struct wav *f = (struct wav *)file;
258: unsigned n;
259:
260: if (f->wbytes >= 0 && count > f->wbytes) {
261: count = f->wbytes; /* wbytes fits in count */
262: if (count == 0) {
263: #ifdef DEBUG
264: if (debug_level >= 3) {
265: wav_dbg(f);
266: dbg_puts(": write complete\n");
267: }
268: #endif
269: file_hup(&f->pipe.file);
270: return 0;
271: }
272: }
273: n = pipe_write(file, data, count);
274: if (f->wbytes >= 0)
275: f->wbytes -= n;
276: f->endpos += n;
277: return n;
278: }
279:
280: /*
281: * close method of the file structure
282: */
283: void
284: wav_close(struct file *file)
285: {
286: struct wav *f = (struct wav *)file;
287:
288: if (f->mode & MODE_RECMASK) {
289: pipe_trunc(&f->pipe.file, f->endpos);
290: if (f->hdr == HDR_WAV) {
291: wav_writehdr(f->pipe.fd,
292: &f->hpar,
293: &f->startpos,
294: f->endpos - f->startpos);
295: }
296: }
297: pipe_close(file);
1.18 ratchov 298: dev_unref();
1.10 ratchov 299: }
300:
1.15 ratchov 301: /*
302: * attach play (rec) abuf structure to the device and
303: * switch to the ``RUN'' state; the play abug must not be empty
304: */
1.14 ratchov 305: int
1.15 ratchov 306: wav_attach(struct wav *f, int force)
1.10 ratchov 307: {
1.15 ratchov 308: struct abuf *rbuf = NULL, *wbuf = NULL;
1.13 ratchov 309:
1.15 ratchov 310: if (f->mode & MODE_PLAY)
1.17 ratchov 311: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.15 ratchov 312: if (f->mode & MODE_RECMASK)
1.17 ratchov 313: wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
1.15 ratchov 314: f->pstate = WAV_RUN;
315: #ifdef DEBUG
316: if (debug_level >= 3) {
317: wav_dbg(f);
318: dbg_puts(": attaching\n");
319: }
320: #endif
1.18 ratchov 321:
322: /*
323: * start the device (dev_getpos() and dev_attach() must
324: * be called on a started device
325: */
1.19 ! ratchov 326: dev_wakeup();
1.18 ratchov 327:
1.15 ratchov 328: dev_attach(f->pipe.file.name, f->mode,
1.16 ratchov 329: rbuf, &f->hpar, f->join ? dev_opar.cmax - dev_opar.cmin + 1 : 0,
330: wbuf, &f->hpar, f->join ? dev_ipar.cmax - dev_ipar.cmin + 1 : 0,
331: f->xrun, f->maxweight);
1.15 ratchov 332: if (f->mode & MODE_PLAY)
333: dev_setvol(rbuf, MIDI_TO_ADATA(f->vol));
1.14 ratchov 334: return 1;
1.13 ratchov 335: }
336:
1.15 ratchov 337: /*
338: * allocate the play (rec) abuf structure; if this is a
339: * file to record, then attach it to the device
340: *
341: * XXX: buffer size should be larger than dev_bufsz, because
342: * in non-server mode we don't prime play buffers with
343: * silence
344: */
1.14 ratchov 345: void
1.15 ratchov 346: wav_allocbuf(struct wav *f)
1.13 ratchov 347: {
1.15 ratchov 348: struct abuf *buf;
349: unsigned nfr;
1.13 ratchov 350:
1.15 ratchov 351: f->pstate = WAV_START;
352: if (f->mode & MODE_PLAY) {
353: nfr = 2 * dev_bufsz * f->hpar.rate / dev_rate;
354: buf = abuf_new(nfr, &f->hpar);
355: aproc_setout(f->pipe.file.rproc, buf);
356: abuf_fill(buf);
357: if (!ABUF_WOK(buf) || (f->pipe.file.state & FILE_EOF))
358: f->pstate = WAV_READY;
359: }
360: if (f->mode & MODE_RECMASK) {
361: nfr = 2 * dev_bufsz * f->hpar.rate / dev_rate;
362: buf = abuf_new(nfr, &f->hpar);
363: aproc_setin(f->pipe.file.wproc, buf);
364: f->pstate = WAV_READY;
365: }
366: #ifdef DEBUG
367: if (debug_level >= 3) {
368: wav_dbg(f);
369: dbg_puts(": allocating buffers\n");
370: }
371: #endif
372: if (f->pstate == WAV_READY && ctl_slotstart(dev_midi, f->slot))
373: (void)wav_attach(f, 0);
1.13 ratchov 374: }
375:
1.15 ratchov 376: /*
377: * free abuf structure and switch to the ``INIT'' state
378: */
1.13 ratchov 379: void
1.15 ratchov 380: wav_freebuf(struct wav *f)
1.10 ratchov 381: {
1.15 ratchov 382: struct abuf *rbuf = NULL, *wbuf = NULL;
383:
384: if (f->mode & MODE_PLAY)
1.17 ratchov 385: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.15 ratchov 386: if (f->mode & MODE_RECMASK)
1.17 ratchov 387: wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
1.15 ratchov 388: f->pstate = WAV_INIT;
389: #ifdef DEBUG
390: if (debug_level >= 3) {
391: wav_dbg(f);
392: dbg_puts(": freeing buffers\n");
393: }
394: #endif
395: if (rbuf || wbuf)
396: ctl_slotstop(dev_midi, f->slot);
397: if (rbuf)
398: abuf_eof(rbuf);
399: if (wbuf)
400: abuf_hup(wbuf);
1.10 ratchov 401: }
402:
1.15 ratchov 403: /*
404: * switch to the ``INIT'' state performing
405: * necessary actions to reach it
406: */
1.10 ratchov 407: void
1.15 ratchov 408: wav_reset(struct wav *f)
1.10 ratchov 409: {
1.15 ratchov 410: switch (f->pstate) {
411: case WAV_START:
412: case WAV_READY:
413: if (ctl_slotstart(dev_midi, f->slot))
414: (void)wav_attach(f, 1);
415: /* PASSTHROUGH */
416: case WAV_RUN:
417: wav_freebuf(f);
418: f->pstate = WAV_INIT;
419: /* PASSTHROUGH */
420: case WAV_INIT:
421: case WAV_FAILED:
422: /* nothing yet */
423: break;
424: }
1.10 ratchov 425: }
426:
1.15 ratchov 427: /*
428: * terminate the wav reader/writer
429: */
430: void
431: wav_exit(struct wav *f)
1.10 ratchov 432: {
1.15 ratchov 433: if (f->mode & MODE_PLAY) {
434: aproc_del(f->pipe.file.rproc);
435: } else if (f->mode & MODE_RECMASK) {
436: aproc_del(f->pipe.file.wproc);
437: }
1.10 ratchov 438: }
439:
1.15 ratchov 440: /*
441: * seek to f->mmcpos and prepare to start, close
442: * the file on error.
443: */
444: int
445: wav_seekmmc(struct wav *f)
1.10 ratchov 446: {
447: /*
1.15 ratchov 448: * don't go beyond the end-of-file, if so
449: * put it in INIT state so it dosn't start
1.10 ratchov 450: */
1.15 ratchov 451: if (f->mmcpos > f->endpos) {
452: wav_reset(f);
453: f->pstate = WAV_FAILED;
454: /*
455: * don't make other stream wait for us
456: */
457: if (f->slot >= 0)
458: ctl_slotstart(dev_midi, f->slot);
459: return 0;
460: }
461: if (!pipe_seek(&f->pipe.file, f->mmcpos)) {
462: wav_exit(f);
463: return 0;
464: }
465: if (f->hdr == HDR_WAV)
466: f->wbytes = WAV_DATAMAX - f->mmcpos;
467: f->rbytes = f->endpos - f->mmcpos;
468: wav_reset(f);
469: wav_allocbuf(f);
470: return 1;
1.10 ratchov 471: }
472:
1.15 ratchov 473: /*
474: * read samples from the file and possibly start it
475: */
1.10 ratchov 476: int
1.15 ratchov 477: wav_rdata(struct wav *f)
1.10 ratchov 478: {
1.15 ratchov 479: struct aproc *p;
480: struct abuf *obuf;
1.10 ratchov 481:
1.15 ratchov 482: p = f->pipe.file.rproc;
1.17 ratchov 483: obuf = LIST_FIRST(&p->outs);
1.15 ratchov 484: if (obuf == NULL)
1.10 ratchov 485: return 0;
1.15 ratchov 486: if (!ABUF_WOK(obuf) || !(f->pipe.file.state & FILE_ROK))
1.10 ratchov 487: return 0;
1.15 ratchov 488: if (!rfile_do(p, obuf->len, NULL))
1.10 ratchov 489: return 0;
1.15 ratchov 490: switch (f->pstate) {
491: case WAV_START:
492: if (!ABUF_WOK(obuf) || (f->pipe.file.state & FILE_EOF))
493: f->pstate = WAV_READY;
494: /* PASSTHROUGH */
495: case WAV_READY:
496: if (ctl_slotstart(dev_midi, f->slot))
497: (void)wav_attach(f, 0);
498: break;
499: #ifdef DEBUG
500: case WAV_RUN:
501: break;
502: default:
503: wav_dbg(f);
504: dbg_puts(": bad state\n");
505: dbg_panic();
506: #endif
507: }
508: if (f->rbytes == 0 && f->tr) {
509: #ifdef DEBUG
510: if (debug_level >= 3) {
511: wav_dbg(f);
512: dbg_puts(": trying to restart\n");
513: }
514: #endif
515: if (!wav_seekmmc(f))
516: return 0;
517: }
1.10 ratchov 518: return 1;
519: }
520:
521: int
1.15 ratchov 522: wav_wdata(struct wav *f)
1.10 ratchov 523: {
1.15 ratchov 524: struct aproc *p;
525: struct abuf *ibuf;
1.10 ratchov 526:
1.15 ratchov 527: if (!(f->pipe.file.state & FILE_WOK))
1.10 ratchov 528: return 0;
1.15 ratchov 529: p = f->pipe.file.wproc;
1.17 ratchov 530: ibuf = LIST_FIRST(&p->ins);
1.15 ratchov 531: if (ibuf == NULL)
1.10 ratchov 532: return 0;
1.15 ratchov 533: if (!ABUF_ROK(ibuf))
1.10 ratchov 534: return 0;
1.15 ratchov 535: if (!wfile_do(p, ibuf->len, NULL))
1.10 ratchov 536: return 0;
537: return 1;
538: }
539:
1.15 ratchov 540: /*
541: * callback to set the volume, invoked by the MIDI control code
542: */
543: void
544: wav_setvol(void *arg, unsigned vol)
545: {
546: struct wav *f = (struct wav *)arg;
547: struct abuf *rbuf;
548:
549: f->vol = vol;
550: if ((f->mode & MODE_PLAY) && f->pstate == WAV_RUN) {
1.17 ratchov 551: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.15 ratchov 552: dev_setvol(rbuf, MIDI_TO_ADATA(vol));
553: }
554: }
555:
556: /*
557: * callback to start the stream, invoked by the MIDI control code
558: */
559: void
560: wav_startreq(void *arg)
561: {
562: struct wav *f = (struct wav *)arg;
563:
564: switch (f->pstate) {
565: case WAV_FAILED:
566: #ifdef DEBUG
567: if (debug_level >= 2) {
568: wav_dbg(f);
569: dbg_puts(": skipped (failed to seek)\n");
570: }
571: #endif
572: return;
573: case WAV_READY:
574: if (f->mode & MODE_RECMASK)
575: f->endpos = f->startpos;
576: (void)wav_attach(f, 0);
577: break;
578: #ifdef DEBUG
579: default:
580: wav_dbg(f);
581: dbg_puts(": not in READY state\n");
582: dbg_panic();
583: break;
584: #endif
585: }
586: }
587:
588: /*
589: * callback to stop the stream, invoked by the MIDI control code
590: */
1.10 ratchov 591: void
1.15 ratchov 592: wav_stopreq(void *arg)
1.10 ratchov 593: {
1.15 ratchov 594: struct wav *f = (struct wav *)arg;
595:
596: #ifdef DEBUG
597: if (debug_level >= 2) {
598: wav_dbg(f);
599: dbg_puts(": stopping");
600: if (f->pstate != WAV_FAILED && (f->mode & MODE_RECMASK)) {
601: dbg_puts(", ");
602: dbg_putu(f->endpos);
603: dbg_puts(" bytes recorded");
604: }
605: dbg_puts("\n");
606: }
607: #endif
608: if (!f->tr) {
609: wav_exit(f);
610: return;
611: }
612: (void)wav_seekmmc(f);
1.10 ratchov 613: }
614:
1.15 ratchov 615: /*
616: * callback to relocate the stream, invoked by the MIDI control code
617: * on a stopped stream
618: */
1.10 ratchov 619: void
1.15 ratchov 620: wav_locreq(void *arg, unsigned mmc)
1.10 ratchov 621: {
1.15 ratchov 622: struct wav *f = (struct wav *)arg;
623:
624: #ifdef DEBUG
625: if (f->pstate == WAV_RUN) {
626: wav_dbg(f);
627: dbg_puts(": in RUN state\n");
628: dbg_panic();
629: }
630: #endif
631: f->mmcpos = f->startpos +
632: ((off_t)mmc * f->hpar.rate / MTC_SEC) * aparams_bpf(&f->hpar);
633: (void)wav_seekmmc(f);
1.10 ratchov 634: }
635:
1.15 ratchov 636: /*
637: * create a file reader in the ``INIT'' state
638: */
1.1 ratchov 639: struct wav *
1.15 ratchov 640: wav_new_in(struct fileops *ops, unsigned mode, char *name, unsigned hdr,
1.16 ratchov 641: struct aparams *par, unsigned xrun, unsigned volctl, int tr, int join)
1.1 ratchov 642: {
1.10 ratchov 643: int fd;
1.1 ratchov 644: struct wav *f;
1.10 ratchov 645:
646: if (name != NULL) {
647: fd = open(name, O_RDONLY | O_NONBLOCK, 0666);
648: if (fd < 0) {
649: perror(name);
650: return NULL;
651: }
652: } else {
653: name = "stdin";
654: fd = STDIN_FILENO;
655: if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
656: perror(name);
657: }
1.1 ratchov 658: f = (struct wav *)pipe_new(ops, fd, name);
1.18 ratchov 659: if (f == NULL) {
660: close(fd);
661: return NULL;
662: }
663: if (!dev_ref()) {
664: close(fd);
1.4 ratchov 665: return NULL;
1.18 ratchov 666: }
1.1 ratchov 667: if (hdr == HDR_WAV) {
1.15 ratchov 668: if (!wav_readhdr(f->pipe.fd, par, &f->startpos, &f->rbytes, &f->map)) {
1.10 ratchov 669: file_del((struct file *)f);
670: return NULL;
671: }
1.15 ratchov 672: f->endpos = f->startpos + f->rbytes;
1.6 ratchov 673: } else {
1.15 ratchov 674: f->startpos = 0;
675: f->endpos = pipe_endpos(&f->pipe.file);
676: if (f->endpos > 0) {
677: if (!pipe_seek(&f->pipe.file, 0)) {
678: file_del((struct file *)f);
679: return NULL;
680: }
681: f->rbytes = f->endpos;
682: } else
683: f->rbytes = -1;
1.6 ratchov 684: f->map = NULL;
685: }
1.15 ratchov 686: f->tr = tr;
1.16 ratchov 687: f->join = join;
1.15 ratchov 688: f->mode = mode;
689: f->hpar = *par;
1.1 ratchov 690: f->hdr = 0;
1.15 ratchov 691: f->xrun = xrun;
692: f->maxweight = MIDI_TO_ADATA(volctl);
693: f->slot = ctl_slotnew(dev_midi, "play", &ctl_wavops, f, 1);
694: rwav_new((struct file *)f);
695: wav_allocbuf(f);
1.12 ratchov 696: #ifdef DEBUG
697: if (debug_level >= 2) {
698: dbg_puts(name);
699: dbg_puts(": playing ");
1.15 ratchov 700: dbg_putu(f->startpos);
701: dbg_puts("..");
702: dbg_putu(f->endpos);
703: dbg_puts(": playing ");
1.12 ratchov 704: aparams_dbg(par);
1.15 ratchov 705: if (f->tr)
706: dbg_puts(", mmc");
1.12 ratchov 707: dbg_puts("\n");
708: }
709: #endif
1.1 ratchov 710: return f;
711: }
712:
1.15 ratchov 713: /*
714: * create a file writer in the ``INIT'' state
715: */
1.1 ratchov 716: struct wav *
1.15 ratchov 717: wav_new_out(struct fileops *ops, unsigned mode, char *name, unsigned hdr,
1.16 ratchov 718: struct aparams *par, unsigned xrun, int tr, int join)
1.1 ratchov 719: {
1.10 ratchov 720: int fd;
1.1 ratchov 721: struct wav *f;
1.10 ratchov 722:
723: if (name == NULL) {
724: name = "stdout";
725: fd = STDOUT_FILENO;
726: if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
727: perror(name);
728: } else {
729: fd = open(name,
730: O_WRONLY | O_TRUNC | O_CREAT | O_NONBLOCK, 0666);
731: if (fd < 0) {
732: perror(name);
733: return NULL;
734: }
735: }
1.1 ratchov 736: f = (struct wav *)pipe_new(ops, fd, name);
1.18 ratchov 737: if (f == NULL) {
738: close(fd);
1.4 ratchov 739: return NULL;
1.18 ratchov 740: }
741: if (!dev_ref()) {
742: close(fd);
743: return NULL;
744: }
1.1 ratchov 745: if (hdr == HDR_WAV) {
1.2 ratchov 746: par->le = 1;
1.3 ratchov 747: par->sig = (par->bits <= 8) ? 0 : 1;
1.2 ratchov 748: par->bps = (par->bits + 7) / 8;
1.15 ratchov 749: if (!wav_writehdr(f->pipe.fd, par, &f->startpos, 0)) {
1.10 ratchov 750: file_del((struct file *)f);
751: return NULL;
752: }
1.1 ratchov 753: f->wbytes = WAV_DATAMAX;
1.15 ratchov 754: f->endpos = f->startpos;
755: } else {
1.1 ratchov 756: f->wbytes = -1;
1.15 ratchov 757: f->startpos = f->endpos = 0;
758: }
759: f->tr = tr;
1.16 ratchov 760: f->join = join;
1.15 ratchov 761: f->mode = mode;
762: f->hpar = *par;
1.1 ratchov 763: f->hdr = hdr;
1.15 ratchov 764: f->xrun = xrun;
765: f->slot = ctl_slotnew(dev_midi, "rec", &ctl_wavops, f, 1);
766: wwav_new((struct file *)f);
767: wav_allocbuf(f);
1.12 ratchov 768: #ifdef DEBUG
769: if (debug_level >= 2) {
770: dbg_puts(name);
771: dbg_puts(": recording ");
772: aparams_dbg(par);
773: dbg_puts("\n");
774: }
775: #endif
1.1 ratchov 776: return f;
777: }
778:
1.6 ratchov 779: void
1.15 ratchov 780: rwav_done(struct aproc *p)
781: {
782: struct wav *f = (struct wav *)p->u.io.file;
783:
784: if (f->slot >= 0)
785: ctl_slotdel(dev_midi, f->slot);
786: f->slot = -1;
787: rfile_done(p);
788: }
789:
790: int
791: rwav_in(struct aproc *p, struct abuf *ibuf_dummy)
1.13 ratchov 792: {
1.15 ratchov 793: struct wav *f = (struct wav *)p->u.io.file;
794: struct abuf *obuf;
1.13 ratchov 795:
1.15 ratchov 796: if (!wav_rdata(f))
797: return 0;
1.17 ratchov 798: obuf = LIST_FIRST(&p->outs);
1.15 ratchov 799: if (obuf && f->pstate >= WAV_RUN) {
800: if (!abuf_flush(obuf))
801: return 0;
1.6 ratchov 802: }
1.15 ratchov 803: return 1;
1.6 ratchov 804: }
805:
1.15 ratchov 806: int
807: rwav_out(struct aproc *p, struct abuf *obuf)
1.1 ratchov 808: {
1.15 ratchov 809: struct wav *f = (struct wav *)p->u.io.file;
1.1 ratchov 810:
1.15 ratchov 811: if (f->pipe.file.state & FILE_RINUSE)
812: return 0;
813: for (;;) {
814: if (!wav_rdata(f))
1.1 ratchov 815: return 0;
816: }
1.15 ratchov 817: return 1;
818: }
819:
820: struct aproc *
821: rwav_new(struct file *f)
822: {
823: struct aproc *p;
824:
825: p = aproc_new(&rwav_ops, f->name);
826: p->u.io.file = f;
827: p->u.io.partial = 0;;
828: f->rproc = p;
829: return p;
830: }
831:
832: void
833: wwav_done(struct aproc *p)
834: {
835: struct wav *f = (struct wav *)p->u.io.file;
836:
837: if (f->slot >= 0)
838: ctl_slotdel(dev_midi, f->slot);
839: f->slot = -1;
840: wfile_done(p);
841: }
842:
843: int
844: wwav_in(struct aproc *p, struct abuf *ibuf)
845: {
846: struct wav *f = (struct wav *)p->u.io.file;
847:
848: if (f->pipe.file.state & FILE_WINUSE)
1.8 jakemsr 849: return 0;
1.15 ratchov 850: for (;;) {
851: if (!wav_wdata(f))
852: return 0;
1.6 ratchov 853: }
1.15 ratchov 854: return 1;
1.1 ratchov 855: }
856:
1.15 ratchov 857: int
858: wwav_out(struct aproc *p, struct abuf *obuf_dummy)
1.1 ratchov 859: {
1.17 ratchov 860: struct abuf *ibuf = LIST_FIRST(&p->ins);
1.15 ratchov 861: struct wav *f = (struct wav *)p->u.io.file;
1.3 ratchov 862:
1.15 ratchov 863: if (ibuf && f->pstate == WAV_RUN) {
864: if (!abuf_fill(ibuf))
1.1 ratchov 865: return 0;
866: }
1.15 ratchov 867: if (!wav_wdata(f))
868: return 0;
869: return 1;
1.1 ratchov 870: }
871:
1.15 ratchov 872: struct aproc *
873: wwav_new(struct file *f)
1.1 ratchov 874: {
1.15 ratchov 875: struct aproc *p;
1.1 ratchov 876:
1.15 ratchov 877: p = aproc_new(&wwav_ops, f->name);
878: p->u.io.file = f;
879: p->u.io.partial = 0;;
880: f->wproc = p;
881: return p;
1.1 ratchov 882: }
1.10 ratchov 883: