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

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.10      ratchov   298: }
                    299:
1.15      ratchov   300: /*
                    301:  * attach play (rec) abuf structure to the device and
                    302:  * switch to the ``RUN'' state; the play abug must not be empty
                    303:  */
1.14      ratchov   304: int
1.15      ratchov   305: wav_attach(struct wav *f, int force)
1.10      ratchov   306: {
1.15      ratchov   307:        struct abuf *rbuf = NULL, *wbuf = NULL;
1.13      ratchov   308:
1.15      ratchov   309:        if (f->mode & MODE_PLAY)
1.17    ! ratchov   310:                rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.15      ratchov   311:        if (f->mode & MODE_RECMASK)
1.17    ! ratchov   312:                wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
1.15      ratchov   313:        f->pstate = WAV_RUN;
                    314: #ifdef DEBUG
                    315:        if (debug_level >= 3) {
                    316:                wav_dbg(f);
                    317:                dbg_puts(": attaching\n");
                    318:        }
                    319: #endif
                    320:        dev_attach(f->pipe.file.name, f->mode,
1.16      ratchov   321:            rbuf, &f->hpar, f->join ? dev_opar.cmax - dev_opar.cmin + 1 : 0,
                    322:            wbuf, &f->hpar, f->join ? dev_ipar.cmax - dev_ipar.cmin + 1 : 0,
                    323:            f->xrun, f->maxweight);
1.15      ratchov   324:        if (f->mode & MODE_PLAY)
                    325:                dev_setvol(rbuf, MIDI_TO_ADATA(f->vol));
1.14      ratchov   326:        return 1;
1.13      ratchov   327: }
                    328:
1.15      ratchov   329: /*
                    330:  * allocate the play (rec) abuf structure; if this is a
                    331:  * file to record, then attach it to the device
                    332:  *
                    333:  * XXX: buffer size should be larger than dev_bufsz, because
                    334:  *     in non-server mode we don't prime play buffers with
                    335:  *     silence
                    336:  */
1.14      ratchov   337: void
1.15      ratchov   338: wav_allocbuf(struct wav *f)
1.13      ratchov   339: {
1.15      ratchov   340:        struct abuf *buf;
                    341:        unsigned nfr;
1.13      ratchov   342:
1.15      ratchov   343:        f->pstate = WAV_START;
                    344:        if (f->mode & MODE_PLAY) {
                    345:                nfr = 2 * dev_bufsz * f->hpar.rate / dev_rate;
                    346:                buf = abuf_new(nfr, &f->hpar);
                    347:                aproc_setout(f->pipe.file.rproc, buf);
                    348:                abuf_fill(buf);
                    349:                if (!ABUF_WOK(buf) || (f->pipe.file.state & FILE_EOF))
                    350:                        f->pstate = WAV_READY;
                    351:        }
                    352:        if (f->mode & MODE_RECMASK) {
                    353:                nfr = 2 * dev_bufsz * f->hpar.rate / dev_rate;
                    354:                buf = abuf_new(nfr, &f->hpar);
                    355:                aproc_setin(f->pipe.file.wproc, buf);
                    356:                f->pstate = WAV_READY;
                    357:        }
                    358: #ifdef DEBUG
                    359:        if (debug_level >= 3) {
                    360:                wav_dbg(f);
                    361:                dbg_puts(": allocating buffers\n");
                    362:        }
                    363: #endif
                    364:        if (f->pstate == WAV_READY && ctl_slotstart(dev_midi, f->slot))
                    365:                (void)wav_attach(f, 0);
1.13      ratchov   366: }
                    367:
1.15      ratchov   368: /*
                    369:  * free abuf structure and switch to the ``INIT'' state
                    370:  */
1.13      ratchov   371: void
1.15      ratchov   372: wav_freebuf(struct wav *f)
1.10      ratchov   373: {
1.15      ratchov   374:        struct abuf *rbuf = NULL, *wbuf = NULL;
                    375:
                    376:        if (f->mode & MODE_PLAY)
1.17    ! ratchov   377:                rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.15      ratchov   378:        if (f->mode & MODE_RECMASK)
1.17    ! ratchov   379:                wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
1.15      ratchov   380:        f->pstate = WAV_INIT;
                    381: #ifdef DEBUG
                    382:        if (debug_level >= 3) {
                    383:                wav_dbg(f);
                    384:                dbg_puts(": freeing buffers\n");
                    385:        }
                    386: #endif
                    387:        if (rbuf || wbuf)
                    388:                ctl_slotstop(dev_midi, f->slot);
                    389:        if (rbuf)
                    390:                abuf_eof(rbuf);
                    391:        if (wbuf)
                    392:                abuf_hup(wbuf);
1.10      ratchov   393: }
                    394:
1.15      ratchov   395: /*
                    396:  * switch to the ``INIT'' state performing
                    397:  * necessary actions to reach it
                    398:  */
1.10      ratchov   399: void
1.15      ratchov   400: wav_reset(struct wav *f)
1.10      ratchov   401: {
1.15      ratchov   402:        switch (f->pstate) {
                    403:        case WAV_START:
                    404:        case WAV_READY:
                    405:                if (ctl_slotstart(dev_midi, f->slot))
                    406:                        (void)wav_attach(f, 1);
                    407:                /* PASSTHROUGH */
                    408:        case WAV_RUN:
                    409:                wav_freebuf(f);
                    410:                f->pstate = WAV_INIT;
                    411:                /* PASSTHROUGH */
                    412:        case WAV_INIT:
                    413:        case WAV_FAILED:
                    414:                /* nothing yet */
                    415:                break;
                    416:        }
1.10      ratchov   417: }
                    418:
1.15      ratchov   419: /*
                    420:  * terminate the wav reader/writer
                    421:  */
                    422: void
                    423: wav_exit(struct wav *f)
1.10      ratchov   424: {
1.15      ratchov   425:        if (f->mode & MODE_PLAY) {
                    426:                aproc_del(f->pipe.file.rproc);
                    427:        } else if (f->mode & MODE_RECMASK) {
                    428:                aproc_del(f->pipe.file.wproc);
                    429:        }
1.10      ratchov   430: }
                    431:
1.15      ratchov   432: /*
                    433:  * seek to f->mmcpos and prepare to start, close
                    434:  * the file on error.
                    435:  */
                    436: int
                    437: wav_seekmmc(struct wav *f)
1.10      ratchov   438: {
                    439:        /*
1.15      ratchov   440:         * don't go beyond the end-of-file, if so
                    441:         * put it in INIT state so it dosn't start
1.10      ratchov   442:         */
1.15      ratchov   443:        if (f->mmcpos > f->endpos) {
                    444:                wav_reset(f);
                    445:                f->pstate = WAV_FAILED;
                    446:                /*
                    447:                 * don't make other stream wait for us
                    448:                 */
                    449:                if (f->slot >= 0)
                    450:                        ctl_slotstart(dev_midi, f->slot);
                    451:                return 0;
                    452:        }
                    453:        if (!pipe_seek(&f->pipe.file, f->mmcpos)) {
                    454:                wav_exit(f);
                    455:                return 0;
                    456:        }
                    457:        if (f->hdr == HDR_WAV)
                    458:                f->wbytes = WAV_DATAMAX - f->mmcpos;
                    459:        f->rbytes = f->endpos - f->mmcpos;
                    460:        wav_reset(f);
                    461:        wav_allocbuf(f);
                    462:        return 1;
1.10      ratchov   463: }
                    464:
1.15      ratchov   465: /*
                    466:  * read samples from the file and possibly start it
                    467:  */
1.10      ratchov   468: int
1.15      ratchov   469: wav_rdata(struct wav *f)
1.10      ratchov   470: {
1.15      ratchov   471:        struct aproc *p;
                    472:        struct abuf *obuf;
1.10      ratchov   473:
1.15      ratchov   474:        p = f->pipe.file.rproc;
1.17    ! ratchov   475:        obuf = LIST_FIRST(&p->outs);
1.15      ratchov   476:        if (obuf == NULL)
1.10      ratchov   477:                return 0;
1.15      ratchov   478:        if (!ABUF_WOK(obuf) || !(f->pipe.file.state & FILE_ROK))
1.10      ratchov   479:                return 0;
1.15      ratchov   480:        if (!rfile_do(p, obuf->len, NULL))
1.10      ratchov   481:                return 0;
1.15      ratchov   482:        switch (f->pstate) {
                    483:        case WAV_START:
                    484:                if (!ABUF_WOK(obuf) || (f->pipe.file.state & FILE_EOF))
                    485:                        f->pstate = WAV_READY;
                    486:                /* PASSTHROUGH */
                    487:        case WAV_READY:
                    488:                if (ctl_slotstart(dev_midi, f->slot))
                    489:                        (void)wav_attach(f, 0);
                    490:                break;
                    491: #ifdef DEBUG
                    492:        case WAV_RUN:
                    493:                break;
                    494:        default:
                    495:                wav_dbg(f);
                    496:                dbg_puts(": bad state\n");
                    497:                dbg_panic();
                    498: #endif
                    499:        }
                    500:        if (f->rbytes == 0 && f->tr) {
                    501: #ifdef DEBUG
                    502:                if (debug_level >= 3) {
                    503:                        wav_dbg(f);
                    504:                        dbg_puts(": trying to restart\n");
                    505:                }
                    506: #endif
                    507:                if (!wav_seekmmc(f))
                    508:                        return 0;
                    509:        }
1.10      ratchov   510:        return 1;
                    511: }
                    512:
                    513: int
1.15      ratchov   514: wav_wdata(struct wav *f)
1.10      ratchov   515: {
1.15      ratchov   516:        struct aproc *p;
                    517:        struct abuf *ibuf;
1.10      ratchov   518:
1.15      ratchov   519:        if (!(f->pipe.file.state & FILE_WOK))
1.10      ratchov   520:                return 0;
1.15      ratchov   521:        p = f->pipe.file.wproc;
1.17    ! ratchov   522:        ibuf = LIST_FIRST(&p->ins);
1.15      ratchov   523:        if (ibuf == NULL)
1.10      ratchov   524:                return 0;
1.15      ratchov   525:        if (!ABUF_ROK(ibuf))
1.10      ratchov   526:                return 0;
1.15      ratchov   527:        if (!wfile_do(p, ibuf->len, NULL))
1.10      ratchov   528:                return 0;
                    529:        return 1;
                    530: }
                    531:
1.15      ratchov   532: /*
                    533:  * callback to set the volume, invoked by the MIDI control code
                    534:  */
                    535: void
                    536: wav_setvol(void *arg, unsigned vol)
                    537: {
                    538:        struct wav *f = (struct wav *)arg;
                    539:        struct abuf *rbuf;
                    540:
                    541:        f->vol = vol;
                    542:        if ((f->mode & MODE_PLAY) && f->pstate == WAV_RUN) {
1.17    ! ratchov   543:                rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.15      ratchov   544:                dev_setvol(rbuf, MIDI_TO_ADATA(vol));
                    545:        }
                    546: }
                    547:
                    548: /*
                    549:  * callback to start the stream, invoked by the MIDI control code
                    550:  */
                    551: void
                    552: wav_startreq(void *arg)
                    553: {
                    554:        struct wav *f = (struct wav *)arg;
                    555:
                    556:        switch (f->pstate) {
                    557:        case WAV_FAILED:
                    558: #ifdef DEBUG
                    559:                if (debug_level >= 2) {
                    560:                        wav_dbg(f);
                    561:                        dbg_puts(": skipped (failed to seek)\n");
                    562:                }
                    563: #endif
                    564:                return;
                    565:        case WAV_READY:
                    566:                if (f->mode & MODE_RECMASK)
                    567:                        f->endpos = f->startpos;
                    568:                (void)wav_attach(f, 0);
                    569:                break;
                    570: #ifdef DEBUG
                    571:        default:
                    572:                wav_dbg(f);
                    573:                dbg_puts(": not in READY state\n");
                    574:                dbg_panic();
                    575:                break;
                    576: #endif
                    577:        }
                    578: }
                    579:
                    580: /*
                    581:  * callback to stop the stream, invoked by the MIDI control code
                    582:  */
1.10      ratchov   583: void
1.15      ratchov   584: wav_stopreq(void *arg)
1.10      ratchov   585: {
1.15      ratchov   586:        struct wav *f = (struct wav *)arg;
                    587:
                    588: #ifdef DEBUG
                    589:        if (debug_level >= 2) {
                    590:                wav_dbg(f);
                    591:                dbg_puts(": stopping");
                    592:                if (f->pstate != WAV_FAILED && (f->mode & MODE_RECMASK)) {
                    593:                        dbg_puts(", ");
                    594:                        dbg_putu(f->endpos);
                    595:                        dbg_puts(" bytes recorded");
                    596:                }
                    597:                dbg_puts("\n");
                    598:        }
                    599: #endif
                    600:        if (!f->tr) {
                    601:                wav_exit(f);
                    602:                return;
                    603:        }
                    604:        (void)wav_seekmmc(f);
1.10      ratchov   605: }
                    606:
1.15      ratchov   607: /*
                    608:  * callback to relocate the stream, invoked by the MIDI control code
                    609:  * on a stopped stream
                    610:  */
1.10      ratchov   611: void
1.15      ratchov   612: wav_locreq(void *arg, unsigned mmc)
1.10      ratchov   613: {
1.15      ratchov   614:        struct wav *f = (struct wav *)arg;
                    615:
                    616: #ifdef DEBUG
                    617:        if (f->pstate == WAV_RUN) {
                    618:                wav_dbg(f);
                    619:                dbg_puts(": in RUN state\n");
                    620:                dbg_panic();
                    621:        }
                    622: #endif
                    623:        f->mmcpos = f->startpos +
                    624:            ((off_t)mmc * f->hpar.rate / MTC_SEC) * aparams_bpf(&f->hpar);
                    625:        (void)wav_seekmmc(f);
1.10      ratchov   626: }
                    627:
1.15      ratchov   628: /*
                    629:  * create a file reader in the ``INIT'' state
                    630:  */
1.1       ratchov   631: struct wav *
1.15      ratchov   632: wav_new_in(struct fileops *ops, unsigned mode, char *name, unsigned hdr,
1.16      ratchov   633:     struct aparams *par, unsigned xrun, unsigned volctl, int tr, int join)
1.1       ratchov   634: {
1.10      ratchov   635:        int fd;
1.1       ratchov   636:        struct wav *f;
1.10      ratchov   637:
                    638:        if (name != NULL) {
                    639:                fd = open(name, O_RDONLY | O_NONBLOCK, 0666);
                    640:                if (fd < 0) {
                    641:                        perror(name);
                    642:                        return NULL;
                    643:                }
                    644:        } else {
                    645:                name = "stdin";
                    646:                fd = STDIN_FILENO;
                    647:                if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
                    648:                        perror(name);
                    649:        }
1.1       ratchov   650:        f = (struct wav *)pipe_new(ops, fd, name);
1.4       ratchov   651:        if (f == NULL)
                    652:                return NULL;
1.1       ratchov   653:        if (hdr == HDR_WAV) {
1.15      ratchov   654:                if (!wav_readhdr(f->pipe.fd, par, &f->startpos, &f->rbytes, &f->map)) {
1.10      ratchov   655:                        file_del((struct file *)f);
                    656:                        return NULL;
                    657:                }
1.15      ratchov   658:                f->endpos = f->startpos + f->rbytes;
1.6       ratchov   659:        } else {
1.15      ratchov   660:                f->startpos = 0;
                    661:                f->endpos = pipe_endpos(&f->pipe.file);
                    662:                if (f->endpos > 0) {
                    663:                        if (!pipe_seek(&f->pipe.file, 0)) {
                    664:                                file_del((struct file *)f);
                    665:                                return NULL;
                    666:                        }
                    667:                        f->rbytes = f->endpos;
                    668:                } else
                    669:                        f->rbytes = -1;
1.6       ratchov   670:                f->map = NULL;
                    671:        }
1.15      ratchov   672:        f->tr = tr;
1.16      ratchov   673:        f->join = join;
1.15      ratchov   674:        f->mode = mode;
                    675:        f->hpar = *par;
1.1       ratchov   676:        f->hdr = 0;
1.15      ratchov   677:        f->xrun = xrun;
                    678:        f->maxweight = MIDI_TO_ADATA(volctl);
                    679:        f->slot = ctl_slotnew(dev_midi, "play", &ctl_wavops, f, 1);
                    680:        rwav_new((struct file *)f);
                    681:        wav_allocbuf(f);
1.12      ratchov   682: #ifdef DEBUG
                    683:        if (debug_level >= 2) {
                    684:                dbg_puts(name);
                    685:                dbg_puts(": playing ");
1.15      ratchov   686:                dbg_putu(f->startpos);
                    687:                dbg_puts("..");
                    688:                dbg_putu(f->endpos);
                    689:                dbg_puts(": playing ");
1.12      ratchov   690:                aparams_dbg(par);
1.15      ratchov   691:                if (f->tr)
                    692:                        dbg_puts(", mmc");
1.12      ratchov   693:                dbg_puts("\n");
                    694:        }
                    695: #endif
1.1       ratchov   696:        return f;
                    697: }
                    698:
1.15      ratchov   699: /*
                    700:  * create a file writer in the ``INIT'' state
                    701:  */
1.1       ratchov   702: struct wav *
1.15      ratchov   703: wav_new_out(struct fileops *ops, unsigned mode, char *name, unsigned hdr,
1.16      ratchov   704:     struct aparams *par, unsigned xrun, int tr, int join)
1.1       ratchov   705: {
1.10      ratchov   706:        int fd;
1.1       ratchov   707:        struct wav *f;
1.10      ratchov   708:
                    709:        if (name == NULL) {
                    710:                name = "stdout";
                    711:                fd = STDOUT_FILENO;
                    712:                if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
                    713:                        perror(name);
                    714:        } else {
                    715:                fd = open(name,
                    716:                    O_WRONLY | O_TRUNC | O_CREAT | O_NONBLOCK, 0666);
                    717:                if (fd < 0) {
                    718:                        perror(name);
                    719:                        return NULL;
                    720:                }
                    721:        }
1.1       ratchov   722:        f = (struct wav *)pipe_new(ops, fd, name);
1.4       ratchov   723:        if (f == NULL)
                    724:                return NULL;
1.1       ratchov   725:        if (hdr == HDR_WAV) {
1.2       ratchov   726:                par->le = 1;
1.3       ratchov   727:                par->sig = (par->bits <= 8) ? 0 : 1;
1.2       ratchov   728:                par->bps = (par->bits + 7) / 8;
1.15      ratchov   729:                if (!wav_writehdr(f->pipe.fd, par, &f->startpos, 0)) {
1.10      ratchov   730:                        file_del((struct file *)f);
                    731:                        return NULL;
                    732:                }
1.1       ratchov   733:                f->wbytes = WAV_DATAMAX;
1.15      ratchov   734:                f->endpos = f->startpos;
                    735:        } else {
1.1       ratchov   736:                f->wbytes = -1;
1.15      ratchov   737:                f->startpos = f->endpos = 0;
                    738:        }
                    739:        f->tr = tr;
1.16      ratchov   740:        f->join = join;
1.15      ratchov   741:        f->mode = mode;
                    742:        f->hpar = *par;
1.1       ratchov   743:        f->hdr = hdr;
1.15      ratchov   744:        f->xrun = xrun;
                    745:        f->slot = ctl_slotnew(dev_midi, "rec", &ctl_wavops, f, 1);
                    746:        wwav_new((struct file *)f);
                    747:        wav_allocbuf(f);
1.12      ratchov   748: #ifdef DEBUG
                    749:        if (debug_level >= 2) {
                    750:                dbg_puts(name);
                    751:                dbg_puts(": recording ");
                    752:                aparams_dbg(par);
                    753:                dbg_puts("\n");
                    754:        }
                    755: #endif
1.1       ratchov   756:        return f;
                    757: }
                    758:
1.6       ratchov   759: void
1.15      ratchov   760: rwav_done(struct aproc *p)
                    761: {
                    762:        struct wav *f = (struct wav *)p->u.io.file;
                    763:
                    764:        if (f->slot >= 0)
                    765:                ctl_slotdel(dev_midi, f->slot);
                    766:        f->slot = -1;
                    767:        rfile_done(p);
                    768: }
                    769:
                    770: int
                    771: rwav_in(struct aproc *p, struct abuf *ibuf_dummy)
1.13      ratchov   772: {
1.15      ratchov   773:        struct wav *f = (struct wav *)p->u.io.file;
                    774:        struct abuf *obuf;
1.13      ratchov   775:
1.15      ratchov   776:        if (!wav_rdata(f))
                    777:                return 0;
1.17    ! ratchov   778:        obuf = LIST_FIRST(&p->outs);
1.15      ratchov   779:        if (obuf && f->pstate >= WAV_RUN) {
                    780:                if (!abuf_flush(obuf))
                    781:                        return 0;
1.6       ratchov   782:        }
1.15      ratchov   783:        return 1;
1.6       ratchov   784: }
                    785:
1.15      ratchov   786: int
                    787: rwav_out(struct aproc *p, struct abuf *obuf)
1.1       ratchov   788: {
1.15      ratchov   789:        struct wav *f = (struct wav *)p->u.io.file;
1.1       ratchov   790:
1.15      ratchov   791:        if (f->pipe.file.state & FILE_RINUSE)
                    792:                return 0;
                    793:        for (;;) {
                    794:                if (!wav_rdata(f))
1.1       ratchov   795:                        return 0;
                    796:        }
1.15      ratchov   797:        return 1;
                    798: }
                    799:
                    800: struct aproc *
                    801: rwav_new(struct file *f)
                    802: {
                    803:        struct aproc *p;
                    804:
                    805:        p = aproc_new(&rwav_ops, f->name);
                    806:        p->u.io.file = f;
                    807:        p->u.io.partial = 0;;
                    808:        f->rproc = p;
                    809:        return p;
                    810: }
                    811:
                    812: void
                    813: wwav_done(struct aproc *p)
                    814: {
                    815:        struct wav *f = (struct wav *)p->u.io.file;
                    816:
                    817:        if (f->slot >= 0)
                    818:                ctl_slotdel(dev_midi, f->slot);
                    819:        f->slot = -1;
                    820:        wfile_done(p);
                    821: }
                    822:
                    823: int
                    824: wwav_in(struct aproc *p, struct abuf *ibuf)
                    825: {
                    826:        struct wav *f = (struct wav *)p->u.io.file;
                    827:
                    828:        if (f->pipe.file.state & FILE_WINUSE)
1.8       jakemsr   829:                return 0;
1.15      ratchov   830:        for (;;) {
                    831:                if (!wav_wdata(f))
                    832:                        return 0;
1.6       ratchov   833:        }
1.15      ratchov   834:        return 1;
1.1       ratchov   835: }
                    836:
1.15      ratchov   837: int
                    838: wwav_out(struct aproc *p, struct abuf *obuf_dummy)
1.1       ratchov   839: {
1.17    ! ratchov   840:        struct abuf *ibuf = LIST_FIRST(&p->ins);
1.15      ratchov   841:        struct wav *f = (struct wav *)p->u.io.file;
1.3       ratchov   842:
1.15      ratchov   843:        if (ibuf && f->pstate == WAV_RUN) {
                    844:                if (!abuf_fill(ibuf))
1.1       ratchov   845:                        return 0;
                    846:        }
1.15      ratchov   847:        if (!wav_wdata(f))
                    848:                return 0;
                    849:        return 1;
1.1       ratchov   850: }
                    851:
1.15      ratchov   852: struct aproc *
                    853: wwav_new(struct file *f)
1.1       ratchov   854: {
1.15      ratchov   855:        struct aproc *p;
1.1       ratchov   856:
1.15      ratchov   857:        p = aproc_new(&wwav_ops, f->name);
                    858:        p->u.io.file = f;
                    859:        p->u.io.partial = 0;;
                    860:        f->wproc = p;
                    861:        return p;
1.1       ratchov   862: }
1.10      ratchov   863: