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

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