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

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.20      ratchov   188:        struct aproc *midi = f->dev ? f->dev->midi : NULL;
1.15      ratchov   189:
                    190:        dbg_puts("wav(");
1.20      ratchov   191:        if (f->slot >= 0 && APROC_OK(midi)) {
                    192:                dbg_puts(midi->u.ctl.slot[f->slot].name);
                    193:                dbg_putu(midi->u.ctl.slot[f->slot].unit);
1.15      ratchov   194:        } else
                    195:                dbg_puts(f->pipe.file.name);
                    196:        dbg_puts(")/");
                    197:        dbg_puts(pstates[f->pstate]);
                    198: }
                    199: #endif
                    200:
                    201: /*
                    202:  * convert ``count'' samples using the given char->short map
                    203:  */
                    204: void
                    205: wav_conv(unsigned char *data, unsigned count, short *map)
1.13      ratchov   206: {
1.15      ratchov   207:        unsigned i;
                    208:        unsigned char *iptr;
1.23      ratchov   209:        adata_t *optr;
1.13      ratchov   210:
1.15      ratchov   211:        iptr = data + count;
1.23      ratchov   212:        optr = (adata_t *)data + count;
1.15      ratchov   213:        for (i = count; i > 0; i--) {
                    214:                --optr;
                    215:                --iptr;
1.23      ratchov   216:                *optr = (adata_t)(map[*iptr]) << (ADATA_BITS - 16);
1.15      ratchov   217:        }
1.13      ratchov   218: }
                    219:
1.15      ratchov   220: /*
                    221:  * read method of the file structure
                    222:  */
                    223: unsigned
                    224: wav_read(struct file *file, unsigned char *data, unsigned count)
1.10      ratchov   225: {
1.15      ratchov   226:        struct wav *f = (struct wav *)file;
                    227:        unsigned n;
                    228:
                    229:        if (f->map)
1.23      ratchov   230:                count /= sizeof(adata_t);
1.15      ratchov   231:        if (f->rbytes >= 0 && count > f->rbytes) {
                    232:                count = f->rbytes; /* file->rbytes fits in count */
                    233:                if (count == 0) {
                    234: #ifdef DEBUG
                    235:                        if (debug_level >= 3) {
                    236:                                wav_dbg(f);
                    237:                                dbg_puts(": read complete\n");
                    238:                        }
                    239: #endif
1.20      ratchov   240:                        if (!f->mmc)
1.15      ratchov   241:                                file_eof(&f->pipe.file);
                    242:                        return 0;
                    243:                }
                    244:        }
                    245:        n = pipe_read(file, data, count);
                    246:        if (n == 0)
1.14      ratchov   247:                return 0;
1.15      ratchov   248:        if (f->rbytes >= 0)
                    249:                f->rbytes -= n;
                    250:        if (f->map) {
                    251:                wav_conv(data, n, f->map);
1.23      ratchov   252:                n *= sizeof(adata_t);
1.15      ratchov   253:        }
                    254:        return n;
                    255: }
                    256:
                    257: /*
                    258:  * write method of the file structure
                    259:  */
                    260: unsigned
                    261: wav_write(struct file *file, unsigned char *data, unsigned count)
                    262: {
                    263:        struct wav *f = (struct wav *)file;
                    264:        unsigned n;
                    265:
                    266:        if (f->wbytes >= 0 && count > f->wbytes) {
                    267:                count = f->wbytes; /* wbytes fits in count */
                    268:                if (count == 0) {
                    269: #ifdef DEBUG
                    270:                        if (debug_level >= 3) {
                    271:                                wav_dbg(f);
                    272:                                dbg_puts(": write complete\n");
                    273:                        }
                    274: #endif
                    275:                        file_hup(&f->pipe.file);
                    276:                        return 0;
                    277:                }
                    278:        }
                    279:        n = pipe_write(file, data, count);
                    280:        if (f->wbytes >= 0)
                    281:                f->wbytes -= n;
                    282:        f->endpos += n;
                    283:        return n;
                    284: }
                    285:
                    286: /*
                    287:  * close method of the file structure
                    288:  */
                    289: void
                    290: wav_close(struct file *file)
                    291: {
1.27    ! ratchov   292:        struct wav *f = (struct wav *)file, **pf;
1.15      ratchov   293:
                    294:        if (f->mode & MODE_RECMASK) {
                    295:                pipe_trunc(&f->pipe.file, f->endpos);
                    296:                if (f->hdr == HDR_WAV) {
                    297:                        wav_writehdr(f->pipe.fd,
                    298:                            &f->hpar,
                    299:                            &f->startpos,
                    300:                            f->endpos - f->startpos);
                    301:                }
                    302:        }
                    303:        pipe_close(file);
1.27    ! ratchov   304:        if (f->pstate != WAV_CFG)
1.20      ratchov   305:                dev_unref(f->dev);
1.27    ! ratchov   306:        for (pf = &wav_list; *pf != f; pf = &(*pf)->next) {
        !           307: #ifdef DEBUG
        !           308:                if (*pf == NULL) {
        !           309:                        dbg_puts("wav_close: not on list\n");
        !           310:                        dbg_panic();
        !           311:                }
        !           312: #endif
1.20      ratchov   313:        }
1.27    ! ratchov   314:        *pf = f->next;
1.10      ratchov   315: }
                    316:
1.15      ratchov   317: /*
                    318:  * attach play (rec) abuf structure to the device and
                    319:  * switch to the ``RUN'' state; the play abug must not be empty
                    320:  */
1.14      ratchov   321: int
1.15      ratchov   322: wav_attach(struct wav *f, int force)
1.10      ratchov   323: {
1.15      ratchov   324:        struct abuf *rbuf = NULL, *wbuf = NULL;
1.20      ratchov   325:        struct dev *d = f->dev;
1.13      ratchov   326:
1.15      ratchov   327:        if (f->mode & MODE_PLAY)
1.17      ratchov   328:                rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.15      ratchov   329:        if (f->mode & MODE_RECMASK)
1.17      ratchov   330:                wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
1.15      ratchov   331:        f->pstate = WAV_RUN;
                    332: #ifdef DEBUG
                    333:        if (debug_level >= 3) {
                    334:                wav_dbg(f);
                    335:                dbg_puts(": attaching\n");
                    336:        }
                    337: #endif
1.18      ratchov   338:
                    339:        /*
                    340:         * start the device (dev_getpos() and dev_attach() must
                    341:         * be called on a started device
                    342:         */
1.20      ratchov   343:        dev_wakeup(d);
1.18      ratchov   344:
1.20      ratchov   345:        dev_attach(d, f->pipe.file.name, f->mode,
                    346:            rbuf, &f->hpar, f->join ? d->opar.cmax - d->opar.cmin + 1 : 0,
                    347:            wbuf, &f->hpar, f->join ? d->ipar.cmax - d->ipar.cmin + 1 : 0,
1.16      ratchov   348:            f->xrun, f->maxweight);
1.15      ratchov   349:        if (f->mode & MODE_PLAY)
1.20      ratchov   350:                dev_setvol(d, rbuf, MIDI_TO_ADATA(f->vol));
1.14      ratchov   351:        return 1;
1.13      ratchov   352: }
                    353:
1.15      ratchov   354: /*
1.27    ! ratchov   355:  * allocate buffers, so client can start filling write-end.
        !           356:  */
        !           357: void
        !           358: wav_midiattach(struct wav *f)
        !           359: {
        !           360:        struct abuf *rbuf = NULL, *wbuf = NULL;
        !           361:
        !           362:        if (f->mode & MODE_MIDIOUT) {
        !           363:                rbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
        !           364:                aproc_setout(f->pipe.file.rproc, rbuf);
        !           365:        }
        !           366:        if (f->mode & MODE_MIDIIN) {
        !           367:                wbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
        !           368:                aproc_setin(f->pipe.file.wproc, wbuf);
        !           369:        }
        !           370:        f->pstate = WAV_MIDI;
        !           371:        dev_midiattach(f->dev, rbuf, wbuf);
        !           372: }
        !           373:
        !           374: /*
1.15      ratchov   375:  * allocate the play (rec) abuf structure; if this is a
                    376:  * file to record, then attach it to the device
                    377:  *
                    378:  * XXX: buffer size should be larger than dev_bufsz, because
                    379:  *     in non-server mode we don't prime play buffers with
                    380:  *     silence
                    381:  */
1.14      ratchov   382: void
1.15      ratchov   383: wav_allocbuf(struct wav *f)
1.13      ratchov   384: {
1.15      ratchov   385:        struct abuf *buf;
1.20      ratchov   386:        struct dev *d = f->dev;
1.15      ratchov   387:        unsigned nfr;
1.13      ratchov   388:
1.15      ratchov   389:        f->pstate = WAV_START;
                    390:        if (f->mode & MODE_PLAY) {
1.20      ratchov   391:                nfr = 2 * d->bufsz * f->hpar.rate / d->rate;
1.15      ratchov   392:                buf = abuf_new(nfr, &f->hpar);
                    393:                aproc_setout(f->pipe.file.rproc, buf);
                    394:                abuf_fill(buf);
                    395:                if (!ABUF_WOK(buf) || (f->pipe.file.state & FILE_EOF))
                    396:                        f->pstate = WAV_READY;
                    397:        }
                    398:        if (f->mode & MODE_RECMASK) {
1.20      ratchov   399:                nfr = 2 * d->bufsz * f->hpar.rate / d->rate;
1.15      ratchov   400:                buf = abuf_new(nfr, &f->hpar);
                    401:                aproc_setin(f->pipe.file.wproc, buf);
                    402:                f->pstate = WAV_READY;
                    403:        }
                    404: #ifdef DEBUG
                    405:        if (debug_level >= 3) {
                    406:                wav_dbg(f);
                    407:                dbg_puts(": allocating buffers\n");
                    408:        }
                    409: #endif
1.20      ratchov   410:        if (f->pstate == WAV_READY && ctl_slotstart(d->midi, f->slot))
1.15      ratchov   411:                (void)wav_attach(f, 0);
1.13      ratchov   412: }
                    413:
1.15      ratchov   414: /*
                    415:  * free abuf structure and switch to the ``INIT'' state
                    416:  */
1.13      ratchov   417: void
1.15      ratchov   418: wav_freebuf(struct wav *f)
1.10      ratchov   419: {
1.15      ratchov   420:        struct abuf *rbuf = NULL, *wbuf = NULL;
                    421:
                    422:        if (f->mode & MODE_PLAY)
1.17      ratchov   423:                rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.15      ratchov   424:        if (f->mode & MODE_RECMASK)
1.17      ratchov   425:                wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
1.15      ratchov   426:        f->pstate = WAV_INIT;
                    427: #ifdef DEBUG
                    428:        if (debug_level >= 3) {
                    429:                wav_dbg(f);
                    430:                dbg_puts(": freeing buffers\n");
                    431:        }
                    432: #endif
                    433:        if (rbuf || wbuf)
1.20      ratchov   434:                ctl_slotstop(f->dev->midi, f->slot);
1.15      ratchov   435:        if (rbuf)
                    436:                abuf_eof(rbuf);
                    437:        if (wbuf)
                    438:                abuf_hup(wbuf);
1.10      ratchov   439: }
                    440:
1.15      ratchov   441: /*
                    442:  * switch to the ``INIT'' state performing
                    443:  * necessary actions to reach it
                    444:  */
1.10      ratchov   445: void
1.15      ratchov   446: wav_reset(struct wav *f)
1.10      ratchov   447: {
1.15      ratchov   448:        switch (f->pstate) {
                    449:        case WAV_START:
                    450:        case WAV_READY:
1.20      ratchov   451:                if (ctl_slotstart(f->dev->midi, f->slot))
1.15      ratchov   452:                        (void)wav_attach(f, 1);
                    453:                /* PASSTHROUGH */
                    454:        case WAV_RUN:
                    455:                wav_freebuf(f);
                    456:                /* PASSTHROUGH */
                    457:        case WAV_INIT:
                    458:                /* nothing yet */
                    459:                break;
1.27    ! ratchov   460:        case WAV_MIDI:
        !           461:                dbg_puts("wav_reset: in midi mode\n");
        !           462:                dbg_panic();
1.15      ratchov   463:        }
1.10      ratchov   464: }
                    465:
1.15      ratchov   466: /*
                    467:  * terminate the wav reader/writer
                    468:  */
                    469: void
                    470: wav_exit(struct wav *f)
1.10      ratchov   471: {
1.20      ratchov   472:        /* XXX: call file_close() ? */
1.27    ! ratchov   473:        if (f->mode & (MODE_PLAY | MODE_MIDIOUT)) {
1.15      ratchov   474:                aproc_del(f->pipe.file.rproc);
1.27    ! ratchov   475:        } else if (f->mode & (MODE_RECMASK | MODE_MIDIIN)) {
1.15      ratchov   476:                aproc_del(f->pipe.file.wproc);
                    477:        }
1.10      ratchov   478: }
                    479:
1.15      ratchov   480: /*
1.27    ! ratchov   481:  * allocate the device
        !           482:  */
        !           483: int
        !           484: wav_init(struct wav *f)
        !           485: {
        !           486:        if (!dev_ref(f->dev)) {
        !           487:                wav_exit(f);
        !           488:                return 0;
        !           489:        }
        !           490:        if (!f->mmc)
        !           491:                f->dev->autostart = 1;
        !           492:        if (f->mode & MODE_MIDIMASK) {
        !           493:                wav_midiattach(f);
        !           494:                return 1;
        !           495:        }
        !           496:        f->slot = ctl_slotnew(f->dev->midi, "wav", &ctl_wavops, f, 1);
        !           497:        f->pstate = WAV_INIT;
        !           498:        if ((f->mode & f->dev->mode) != f->mode) {
        !           499: #ifdef DEBUG
        !           500:                if (debug_level >= 1) {
        !           501:                        wav_dbg(f);
        !           502:                        dbg_puts(": ");
        !           503:                        dbg_puts(": operation not supported by device\n");
        !           504:                }
        !           505: #endif
        !           506:                wav_exit(f);
        !           507:                return 0;
        !           508:        }
        !           509:        wav_allocbuf(f);
        !           510:        return 1;
        !           511: }
        !           512:
        !           513: /*
1.15      ratchov   514:  * seek to f->mmcpos and prepare to start, close
                    515:  * the file on error.
                    516:  */
                    517: int
                    518: wav_seekmmc(struct wav *f)
1.10      ratchov   519: {
                    520:        /*
1.15      ratchov   521:         * don't go beyond the end-of-file, if so
                    522:         * put it in INIT state so it dosn't start
1.10      ratchov   523:         */
1.27    ! ratchov   524:        if (f->mmcpos > f->endpos && !(f->mode & MODE_RECMASK)) {
1.15      ratchov   525:                wav_reset(f);
                    526:                /*
                    527:                 * don't make other stream wait for us
                    528:                 */
                    529:                if (f->slot >= 0)
1.20      ratchov   530:                        ctl_slotstart(f->dev->midi, f->slot);
1.15      ratchov   531:                return 0;
                    532:        }
                    533:        if (!pipe_seek(&f->pipe.file, f->mmcpos)) {
                    534:                wav_exit(f);
                    535:                return 0;
                    536:        }
1.27    ! ratchov   537:        if (f->mode & MODE_RECMASK)
        !           538:                f->endpos = f->mmcpos;
1.15      ratchov   539:        if (f->hdr == HDR_WAV)
                    540:                f->wbytes = WAV_DATAMAX - f->mmcpos;
                    541:        f->rbytes = f->endpos - f->mmcpos;
                    542:        wav_reset(f);
                    543:        wav_allocbuf(f);
                    544:        return 1;
1.10      ratchov   545: }
                    546:
1.15      ratchov   547: /*
                    548:  * read samples from the file and possibly start it
                    549:  */
1.10      ratchov   550: int
1.15      ratchov   551: wav_rdata(struct wav *f)
1.10      ratchov   552: {
1.15      ratchov   553:        struct aproc *p;
                    554:        struct abuf *obuf;
1.10      ratchov   555:
1.15      ratchov   556:        p = f->pipe.file.rproc;
1.17      ratchov   557:        obuf = LIST_FIRST(&p->outs);
1.15      ratchov   558:        if (obuf == NULL)
1.10      ratchov   559:                return 0;
1.15      ratchov   560:        if (!ABUF_WOK(obuf) || !(f->pipe.file.state & FILE_ROK))
1.10      ratchov   561:                return 0;
1.15      ratchov   562:        if (!rfile_do(p, obuf->len, NULL))
1.10      ratchov   563:                return 0;
1.15      ratchov   564:        switch (f->pstate) {
                    565:        case WAV_START:
                    566:                if (!ABUF_WOK(obuf) || (f->pipe.file.state & FILE_EOF))
                    567:                        f->pstate = WAV_READY;
                    568:                /* PASSTHROUGH */
                    569:        case WAV_READY:
1.20      ratchov   570:                if (ctl_slotstart(f->dev->midi, f->slot))
1.15      ratchov   571:                        (void)wav_attach(f, 0);
                    572:                break;
                    573:        case WAV_RUN:
                    574:                break;
1.27    ! ratchov   575:        case WAV_MIDI:
        !           576:                return 1;
        !           577: #ifdef DEBUG
1.15      ratchov   578:        default:
                    579:                wav_dbg(f);
                    580:                dbg_puts(": bad state\n");
                    581:                dbg_panic();
                    582: #endif
                    583:        }
1.20      ratchov   584:        if (f->rbytes == 0 && f->mmc) {
1.15      ratchov   585: #ifdef DEBUG
                    586:                if (debug_level >= 3) {
                    587:                        wav_dbg(f);
                    588:                        dbg_puts(": trying to restart\n");
                    589:                }
                    590: #endif
                    591:                if (!wav_seekmmc(f))
                    592:                        return 0;
                    593:        }
1.10      ratchov   594:        return 1;
                    595: }
                    596:
                    597: int
1.15      ratchov   598: wav_wdata(struct wav *f)
1.10      ratchov   599: {
1.15      ratchov   600:        struct aproc *p;
                    601:        struct abuf *ibuf;
1.10      ratchov   602:
1.15      ratchov   603:        if (!(f->pipe.file.state & FILE_WOK))
1.10      ratchov   604:                return 0;
1.15      ratchov   605:        p = f->pipe.file.wproc;
1.17      ratchov   606:        ibuf = LIST_FIRST(&p->ins);
1.15      ratchov   607:        if (ibuf == NULL)
1.10      ratchov   608:                return 0;
1.15      ratchov   609:        if (!ABUF_ROK(ibuf))
1.10      ratchov   610:                return 0;
1.15      ratchov   611:        if (!wfile_do(p, ibuf->len, NULL))
1.10      ratchov   612:                return 0;
                    613:        return 1;
                    614: }
                    615:
1.15      ratchov   616: /*
                    617:  * callback to set the volume, invoked by the MIDI control code
                    618:  */
                    619: void
                    620: wav_setvol(void *arg, unsigned vol)
                    621: {
                    622:        struct wav *f = (struct wav *)arg;
                    623:        struct abuf *rbuf;
                    624:
                    625:        f->vol = vol;
                    626:        if ((f->mode & MODE_PLAY) && f->pstate == WAV_RUN) {
1.17      ratchov   627:                rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.20      ratchov   628:                dev_setvol(f->dev, rbuf, MIDI_TO_ADATA(vol));
1.15      ratchov   629:        }
                    630: }
                    631:
                    632: /*
                    633:  * callback to start the stream, invoked by the MIDI control code
                    634:  */
                    635: void
                    636: wav_startreq(void *arg)
                    637: {
                    638:        struct wav *f = (struct wav *)arg;
                    639:
                    640:        switch (f->pstate) {
1.27    ! ratchov   641:        case WAV_INIT:
1.15      ratchov   642: #ifdef DEBUG
                    643:                if (debug_level >= 2) {
                    644:                        wav_dbg(f);
                    645:                        dbg_puts(": skipped (failed to seek)\n");
                    646:                }
                    647: #endif
                    648:                return;
                    649:        case WAV_READY:
                    650:                if (f->mode & MODE_RECMASK)
1.27    ! ratchov   651:                        f->endpos = f->mmcpos + f->startpos;
1.15      ratchov   652:                (void)wav_attach(f, 0);
                    653:                break;
                    654: #ifdef DEBUG
                    655:        default:
                    656:                wav_dbg(f);
                    657:                dbg_puts(": not in READY state\n");
                    658:                dbg_panic();
                    659:                break;
                    660: #endif
                    661:        }
                    662: }
                    663:
                    664: /*
                    665:  * callback to stop the stream, invoked by the MIDI control code
                    666:  */
1.10      ratchov   667: void
1.15      ratchov   668: wav_stopreq(void *arg)
1.10      ratchov   669: {
1.15      ratchov   670:        struct wav *f = (struct wav *)arg;
                    671:
                    672: #ifdef DEBUG
                    673:        if (debug_level >= 2) {
                    674:                wav_dbg(f);
                    675:                dbg_puts(": stopping");
1.27    ! ratchov   676:                if (f->pstate != WAV_INIT && (f->mode & MODE_RECMASK)) {
1.15      ratchov   677:                        dbg_puts(", ");
                    678:                        dbg_putu(f->endpos);
                    679:                        dbg_puts(" bytes recorded");
                    680:                }
                    681:                dbg_puts("\n");
                    682:        }
                    683: #endif
1.20      ratchov   684:        if (!f->mmc) {
1.15      ratchov   685:                wav_exit(f);
                    686:                return;
                    687:        }
                    688:        (void)wav_seekmmc(f);
1.10      ratchov   689: }
                    690:
1.15      ratchov   691: /*
                    692:  * callback to relocate the stream, invoked by the MIDI control code
                    693:  * on a stopped stream
                    694:  */
1.10      ratchov   695: void
1.15      ratchov   696: wav_locreq(void *arg, unsigned mmc)
1.10      ratchov   697: {
1.15      ratchov   698:        struct wav *f = (struct wav *)arg;
                    699:
                    700: #ifdef DEBUG
                    701:        if (f->pstate == WAV_RUN) {
                    702:                wav_dbg(f);
                    703:                dbg_puts(": in RUN state\n");
                    704:                dbg_panic();
                    705:        }
                    706: #endif
                    707:        f->mmcpos = f->startpos +
                    708:            ((off_t)mmc * f->hpar.rate / MTC_SEC) * aparams_bpf(&f->hpar);
                    709:        (void)wav_seekmmc(f);
1.10      ratchov   710: }
                    711:
1.15      ratchov   712: /*
1.20      ratchov   713:  * Callback invoked when slot is gone
                    714:  */
                    715: void
                    716: wav_quitreq(void *arg)
                    717: {
                    718:        struct wav *f = (struct wav *)arg;
                    719:
                    720: #ifdef DEBUG
                    721:        if (debug_level >= 3) {
                    722:                wav_dbg(f);
                    723:                dbg_puts(": slot gone\n");
                    724:        }
                    725: #endif
                    726:        if (f->pstate != WAV_RUN)
                    727:                wav_exit(f);
                    728: }
                    729:
                    730: /*
1.26      ratchov   731:  * determine the header by the file name
                    732:  */
1.27    ! ratchov   733: int
        !           734: wav_autohdr(char *name, struct dev *dev, unsigned *hdr, unsigned *mode)
1.26      ratchov   735: {
1.27    ! ratchov   736:        char *ext;
1.26      ratchov   737:
1.27    ! ratchov   738:        if (dev->reqmode & MODE_THRU)
        !           739:                *mode &= MODE_MIDIMASK;
        !           740:        if (*hdr == HDR_AUTO) {
        !           741:                ext = strrchr(name, '.');
        !           742:                if (ext != NULL) {
        !           743:                        ext++;
        !           744:                        if (strcasecmp(ext, "wav") == 0) {
        !           745:                                *hdr = HDR_WAV;
        !           746:                                *mode &= ~MODE_MIDIMASK;
        !           747:                        } else if (strcasecmp(ext, "syx") == 0) {
        !           748:                                *hdr = HDR_WAV;
        !           749:                                *mode &= ~MODE_AUDIOMASK;
        !           750:                        }
        !           751:                } else
        !           752:                        *hdr = HDR_RAW;
        !           753:        }
        !           754:        if (*mode & MODE_AUDIOMASK)
        !           755:                *mode &= ~MODE_MIDIMASK;
        !           756:        if (*mode == 0) {
        !           757: #ifdef DEBUG
        !           758:                if (debug_level >= 1) {
        !           759:                        dbg_puts(name);
        !           760:                        dbg_puts(": requested mode not supported\n");
        !           761:                }
        !           762: #endif
        !           763:                return 0;
        !           764:        }
        !           765:        return 1;
1.26      ratchov   766: }
                    767:
                    768: /*
1.15      ratchov   769:  * create a file reader in the ``INIT'' state
                    770:  */
1.1       ratchov   771: struct wav *
1.27    ! ratchov   772: wav_new_in(struct fileops *ops, struct dev *dev,
        !           773:     unsigned mode, char *name, unsigned hdr,
        !           774:     struct aparams *par, unsigned xrun, unsigned volctl, int mmc, int join)
1.1       ratchov   775: {
1.10      ratchov   776:        int fd;
1.1       ratchov   777:        struct wav *f;
1.10      ratchov   778:
1.27    ! ratchov   779:        if (!wav_autohdr(name, dev, &hdr, &mode))
        !           780:                return NULL;
        !           781:        if (strcmp(name, "-") == 0) {
        !           782:                fd = STDIN_FILENO;
        !           783:                if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
        !           784:                        perror(name);
        !           785:        } else {
1.10      ratchov   786:                fd = open(name, O_RDONLY | O_NONBLOCK, 0666);
                    787:                if (fd < 0) {
                    788:                        perror(name);
                    789:                        return NULL;
                    790:                }
                    791:        }
1.1       ratchov   792:        f = (struct wav *)pipe_new(ops, fd, name);
1.18      ratchov   793:        if (f == NULL) {
                    794:                close(fd);
                    795:                return NULL;
                    796:        }
1.27    ! ratchov   797:        f->pstate = WAV_CFG;
1.1       ratchov   798:        if (hdr == HDR_WAV) {
1.27    ! ratchov   799:                if (!wav_readhdr(f->pipe.fd, par,
        !           800:                        &f->startpos, &f->rbytes, &f->map)) {
1.10      ratchov   801:                        file_del((struct file *)f);
                    802:                        return NULL;
                    803:                }
1.15      ratchov   804:                f->endpos = f->startpos + f->rbytes;
1.6       ratchov   805:        } else {
1.15      ratchov   806:                f->startpos = 0;
                    807:                f->endpos = pipe_endpos(&f->pipe.file);
                    808:                if (f->endpos > 0) {
                    809:                        if (!pipe_seek(&f->pipe.file, 0)) {
                    810:                                file_del((struct file *)f);
                    811:                                return NULL;
                    812:                        }
                    813:                        f->rbytes = f->endpos;
                    814:                } else
                    815:                        f->rbytes = -1;
1.6       ratchov   816:                f->map = NULL;
                    817:        }
1.27    ! ratchov   818:        f->dev = dev;
        !           819:        f->mmc = mmc;
1.16      ratchov   820:        f->join = join;
1.15      ratchov   821:        f->mode = mode;
                    822:        f->hpar = *par;
1.26      ratchov   823:        f->hdr = hdr;
1.15      ratchov   824:        f->xrun = xrun;
                    825:        f->maxweight = MIDI_TO_ADATA(volctl);
1.27    ! ratchov   826:        f->slot = -1;
1.15      ratchov   827:        rwav_new((struct file *)f);
1.12      ratchov   828: #ifdef DEBUG
                    829:        if (debug_level >= 2) {
                    830:                dbg_puts(name);
1.27    ! ratchov   831:                dbg_puts(":");
        !           832:                if (f->mode & MODE_PLAY) {
        !           833:                        dbg_puts(" playing ");
        !           834:                        aparams_dbg(par);
        !           835:                        dbg_puts(" ");
        !           836:                        dbg_putu(f->startpos);
        !           837:                        dbg_puts("..");
        !           838:                        dbg_putu(f->endpos);
        !           839:                        if (f->mmc)
        !           840:                                dbg_puts(", mmc");
        !           841:                }
        !           842:                if (f->mode & MODE_MIDIOUT)
        !           843:                        dbg_puts(" midi/out");
1.12      ratchov   844:                dbg_puts("\n");
                    845:        }
                    846: #endif
1.27    ! ratchov   847:        f->next = wav_list;
        !           848:        wav_list = f;
1.1       ratchov   849:        return f;
                    850: }
                    851:
1.15      ratchov   852: /*
                    853:  * create a file writer in the ``INIT'' state
                    854:  */
1.1       ratchov   855: struct wav *
1.27    ! ratchov   856: wav_new_out(struct fileops *ops, struct dev *dev,
        !           857:     unsigned mode, char *name, unsigned hdr,
        !           858:     struct aparams *par, unsigned xrun, int mmc, int join)
1.1       ratchov   859: {
1.10      ratchov   860:        int fd;
1.1       ratchov   861:        struct wav *f;
1.10      ratchov   862:
1.27    ! ratchov   863:        if (!wav_autohdr(name, dev, &hdr, &mode))
        !           864:                return NULL;
        !           865:        if (strcmp(name, "-") == 0) {
1.10      ratchov   866:                fd = STDOUT_FILENO;
                    867:                if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
                    868:                        perror(name);
                    869:        } else {
                    870:                fd = open(name,
                    871:                    O_WRONLY | O_TRUNC | O_CREAT | O_NONBLOCK, 0666);
                    872:                if (fd < 0) {
                    873:                        perror(name);
                    874:                        return NULL;
                    875:                }
                    876:        }
1.1       ratchov   877:        f = (struct wav *)pipe_new(ops, fd, name);
1.18      ratchov   878:        if (f == NULL) {
                    879:                close(fd);
1.4       ratchov   880:                return NULL;
1.18      ratchov   881:        }
1.27    ! ratchov   882:        f->pstate = WAV_CFG;
1.1       ratchov   883:        if (hdr == HDR_WAV) {
1.2       ratchov   884:                par->le = 1;
1.3       ratchov   885:                par->sig = (par->bits <= 8) ? 0 : 1;
1.2       ratchov   886:                par->bps = (par->bits + 7) / 8;
1.15      ratchov   887:                if (!wav_writehdr(f->pipe.fd, par, &f->startpos, 0)) {
1.10      ratchov   888:                        file_del((struct file *)f);
                    889:                        return NULL;
                    890:                }
1.1       ratchov   891:                f->wbytes = WAV_DATAMAX;
1.15      ratchov   892:                f->endpos = f->startpos;
                    893:        } else {
1.1       ratchov   894:                f->wbytes = -1;
1.15      ratchov   895:                f->startpos = f->endpos = 0;
                    896:        }
1.27    ! ratchov   897:        f->dev = dev;
        !           898:        f->mmc = mmc;
1.16      ratchov   899:        f->join = join;
1.15      ratchov   900:        f->mode = mode;
                    901:        f->hpar = *par;
1.1       ratchov   902:        f->hdr = hdr;
1.15      ratchov   903:        f->xrun = xrun;
                    904:        wwav_new((struct file *)f);
1.12      ratchov   905: #ifdef DEBUG
                    906:        if (debug_level >= 2) {
                    907:                dbg_puts(name);
1.27    ! ratchov   908:                dbg_puts(":");
        !           909:                if (f->mode & MODE_RECMASK) {
        !           910:                        dbg_puts(" recording ");
        !           911:                        aparams_dbg(par);
        !           912:                        if (f->mmc)
        !           913:                                dbg_puts(", mmc");
        !           914:                }
        !           915:                if (f->mode & MODE_MIDIIN)
        !           916:                        dbg_puts(" midi/in");
1.12      ratchov   917:                dbg_puts("\n");
                    918:        }
                    919: #endif
1.27    ! ratchov   920:        f->next = wav_list;
        !           921:        wav_list = f;
1.1       ratchov   922:        return f;
                    923: }
                    924:
1.6       ratchov   925: void
1.15      ratchov   926: rwav_done(struct aproc *p)
                    927: {
                    928:        struct wav *f = (struct wav *)p->u.io.file;
                    929:
                    930:        if (f->slot >= 0)
1.20      ratchov   931:                ctl_slotdel(f->dev->midi, f->slot);
1.15      ratchov   932:        f->slot = -1;
                    933:        rfile_done(p);
                    934: }
                    935:
                    936: int
                    937: rwav_in(struct aproc *p, struct abuf *ibuf_dummy)
1.13      ratchov   938: {
1.15      ratchov   939:        struct wav *f = (struct wav *)p->u.io.file;
                    940:        struct abuf *obuf;
1.13      ratchov   941:
1.15      ratchov   942:        if (!wav_rdata(f))
                    943:                return 0;
1.17      ratchov   944:        obuf = LIST_FIRST(&p->outs);
1.15      ratchov   945:        if (obuf && f->pstate >= WAV_RUN) {
                    946:                if (!abuf_flush(obuf))
                    947:                        return 0;
1.6       ratchov   948:        }
1.15      ratchov   949:        return 1;
1.6       ratchov   950: }
                    951:
1.15      ratchov   952: int
                    953: rwav_out(struct aproc *p, struct abuf *obuf)
1.1       ratchov   954: {
1.15      ratchov   955:        struct wav *f = (struct wav *)p->u.io.file;
1.1       ratchov   956:
1.15      ratchov   957:        if (f->pipe.file.state & FILE_RINUSE)
                    958:                return 0;
                    959:        for (;;) {
                    960:                if (!wav_rdata(f))
1.1       ratchov   961:                        return 0;
                    962:        }
1.15      ratchov   963:        return 1;
                    964: }
                    965:
                    966: struct aproc *
                    967: rwav_new(struct file *f)
                    968: {
                    969:        struct aproc *p;
                    970:
                    971:        p = aproc_new(&rwav_ops, f->name);
                    972:        p->u.io.file = f;
1.24      deraadt   973:        p->u.io.partial = 0;
1.15      ratchov   974:        f->rproc = p;
                    975:        return p;
                    976: }
                    977:
                    978: void
                    979: wwav_done(struct aproc *p)
                    980: {
                    981:        struct wav *f = (struct wav *)p->u.io.file;
                    982:
                    983:        if (f->slot >= 0)
1.20      ratchov   984:                ctl_slotdel(f->dev->midi, f->slot);
1.15      ratchov   985:        f->slot = -1;
                    986:        wfile_done(p);
                    987: }
                    988:
                    989: int
                    990: wwav_in(struct aproc *p, struct abuf *ibuf)
                    991: {
                    992:        struct wav *f = (struct wav *)p->u.io.file;
                    993:
                    994:        if (f->pipe.file.state & FILE_WINUSE)
1.8       jakemsr   995:                return 0;
1.15      ratchov   996:        for (;;) {
                    997:                if (!wav_wdata(f))
                    998:                        return 0;
1.6       ratchov   999:        }
1.15      ratchov  1000:        return 1;
1.1       ratchov  1001: }
                   1002:
1.15      ratchov  1003: int
                   1004: wwav_out(struct aproc *p, struct abuf *obuf_dummy)
1.1       ratchov  1005: {
1.17      ratchov  1006:        struct abuf *ibuf = LIST_FIRST(&p->ins);
1.15      ratchov  1007:        struct wav *f = (struct wav *)p->u.io.file;
1.3       ratchov  1008:
1.15      ratchov  1009:        if (ibuf && f->pstate == WAV_RUN) {
                   1010:                if (!abuf_fill(ibuf))
1.1       ratchov  1011:                        return 0;
                   1012:        }
1.15      ratchov  1013:        if (!wav_wdata(f))
                   1014:                return 0;
                   1015:        return 1;
1.1       ratchov  1016: }
                   1017:
1.15      ratchov  1018: struct aproc *
                   1019: wwav_new(struct file *f)
1.1       ratchov  1020: {
1.15      ratchov  1021:        struct aproc *p;
1.1       ratchov  1022:
1.15      ratchov  1023:        p = aproc_new(&wwav_ops, f->name);
                   1024:        p->u.io.file = f;
1.24      deraadt  1025:        p->u.io.partial = 0;
1.15      ratchov  1026:        f->wproc = p;
                   1027:        return p;
1.1       ratchov  1028: }