[BACK]Return to wav.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / aucat

Annotation of src/usr.bin/aucat/wav.c, Revision 1.22

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;
                    206:        short *optr;
1.13      ratchov   207:
1.15      ratchov   208:        iptr = data + count;
                    209:        optr = (short *)data + count;
                    210:        for (i = count; i > 0; i--) {
                    211:                --optr;
                    212:                --iptr;
                    213:                *optr = map[*iptr];
                    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)
                    227:                count /= sizeof(short);
                    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);
                    249:                n *= sizeof(short);
                    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: