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

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