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

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