[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.18

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:         */
        !           326:        dev_wakeup(0);
        !           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: