[BACK]Return to sock.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / aucat

Annotation of src/usr.bin/aucat/sock.c, Revision 1.41

1.40      ratchov     1: /*     $OpenBSD: sock.c,v 1.39 2010/01/15 22:17:44 ratchov Exp $       */
1.1       ratchov     2: /*
                      3:  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
1.41    ! ratchov    17: /*
        !            18:  * TODO:
        !            19:  *
        !            20:  *     change f->bufsz to contain only socket-side buffer,
        !            21:  *     because it's less error prone
        !            22:  */
1.1       ratchov    23:
                     24: #include <stdio.h>
                     25: #include <stdlib.h>
                     26: #include <string.h>
1.20      ratchov    27:
                     28: #include "abuf.h"
1.1       ratchov    29: #include "aproc.h"
1.20      ratchov    30: #include "conf.h"
1.1       ratchov    31: #include "dev.h"
1.19      ratchov    32: #include "midi.h"
                     33: #include "opt.h"
1.20      ratchov    34: #include "sock.h"
1.37      ratchov    35: #ifdef DEBUG
                     36: #include "dbg.h"
                     37: #endif
1.1       ratchov    38:
1.41    ! ratchov    39: int sock_attach(struct sock *, int);
1.1       ratchov    40: int sock_read(struct sock *);
                     41: int sock_write(struct sock *);
                     42: int sock_execmsg(struct sock *);
                     43: void sock_reset(struct sock *);
                     44:
                     45: struct fileops sock_ops = {
                     46:        "sock",
                     47:        sizeof(struct sock),
                     48:                pipe_close,
                     49:        pipe_read,
                     50:        pipe_write,
                     51:        NULL, /* start */
                     52:        NULL, /* stop */
                     53:        pipe_nfds,
                     54:        pipe_pollfd,
                     55:        pipe_revents
                     56: };
1.30      ratchov    57:
1.37      ratchov    58: #ifdef DEBUG
                     59: void
                     60: sock_dbg(struct sock *f)
                     61: {
1.41    ! ratchov    62:        static char *pstates[] = { "hel", "ini", "sta", "run", "mid" };
1.37      ratchov    63:        static char *rstates[] = { "rdat", "rmsg", "rret" };
                     64:        static char *wstates[] = { "widl", "wmsg", "wdat" };
                     65:
1.41    ! ratchov    66:        if (f->slot >= 0 && dev_midi) {
1.37      ratchov    67:                dbg_puts(dev_midi->u.ctl.slot[f->slot].name);
                     68:                dbg_putu(dev_midi->u.ctl.slot[f->slot].unit);
                     69:        } else
                     70:                dbg_puts(f->pipe.file.name);
                     71:        dbg_puts("/");
                     72:        dbg_puts(pstates[f->pstate]);
                     73:        dbg_puts("|");
                     74:        dbg_puts(rstates[f->rstate]);
                     75:        dbg_puts("|");
                     76:        dbg_puts(wstates[f->wstate]);
                     77: }
                     78: #endif
1.1       ratchov    79:
1.34      ratchov    80: void sock_setvol(void *, unsigned);
1.35      ratchov    81: void sock_startreq(void *);
1.34      ratchov    82:
                     83: struct ctl_ops ctl_sockops = {
                     84:        sock_setvol,
1.41    ! ratchov    85:        sock_startreq
1.34      ratchov    86: };
                     87:
1.1       ratchov    88: void
                     89: rsock_done(struct aproc *p)
                     90: {
                     91:        struct sock *f = (struct sock *)p->u.io.file;
                     92:
1.11      ratchov    93:        if (f == NULL)
                     94:                return;
1.1       ratchov    95:        sock_reset(f);
                     96:        f->pipe.file.rproc = NULL;
                     97:        if (f->pipe.file.wproc) {
1.34      ratchov    98:                if (f->slot >= 0)
1.24      ratchov    99:                        ctl_slotdel(dev_midi, f->slot);
1.1       ratchov   100:                aproc_del(f->pipe.file.wproc);
                    101:                file_del(&f->pipe.file);
                    102:        }
1.11      ratchov   103:        p->u.io.file = NULL;
1.1       ratchov   104: }
                    105:
                    106: int
                    107: rsock_in(struct aproc *p, struct abuf *ibuf_dummy)
                    108: {
                    109:        struct sock *f = (struct sock *)p->u.io.file;
                    110:        struct abuf *obuf;
                    111:
                    112:        if (!sock_read(f))
                    113:                return 0;
                    114:        obuf = LIST_FIRST(&p->obuflist);
1.34      ratchov   115:        if (obuf && f->pstate >= SOCK_RUN) {
1.1       ratchov   116:                if (!abuf_flush(obuf))
                    117:                        return 0;
                    118:        }
                    119:        return 1;
                    120: }
                    121:
                    122: int
                    123: rsock_out(struct aproc *p, struct abuf *obuf)
                    124: {
                    125:        struct sock *f = (struct sock *)p->u.io.file;
                    126:
1.19      ratchov   127:        if (f->pipe.file.state & FILE_RINUSE)
1.1       ratchov   128:                return 0;
                    129:
1.12      ratchov   130:        /*
1.20      ratchov   131:         * When calling sock_read(), we may receive a ``STOP'' command,
1.1       ratchov   132:         * and detach ``obuf''. In this case, there's no more caller and
1.20      ratchov   133:         * we'll stop processing further messages, resulting in a deadlock.
1.1       ratchov   134:         * The solution is to iterate over sock_read() in order to
                    135:         * consume all messages().
                    136:         */
                    137:        for (;;) {
                    138:                if (!sock_read(f))
1.12      ratchov   139:                        return 0;
1.1       ratchov   140:        }
                    141:        return 1;
                    142: }
                    143:
                    144: void
                    145: rsock_eof(struct aproc *p, struct abuf *ibuf_dummy)
                    146: {
                    147:        aproc_del(p);
                    148: }
                    149:
                    150: void
                    151: rsock_hup(struct aproc *p, struct abuf *ibuf)
                    152: {
                    153:        aproc_del(p);
                    154: }
                    155:
                    156: void
                    157: rsock_opos(struct aproc *p, struct abuf *obuf, int delta)
                    158: {
                    159:        struct sock *f = (struct sock *)p->u.io.file;
                    160:
1.41    ! ratchov   161:        if (f->mode & AMSG_REC)
1.14      ratchov   162:                return;
                    163:
                    164:        f->delta += delta;
1.37      ratchov   165: #ifdef DEBUG
                    166:        if (debug_level >= 4) {
                    167:                aproc_dbg(p);
                    168:                dbg_puts(": moved to delta = ");
                    169:                dbg_puti(f->delta);
                    170:                dbg_puts("\n");
                    171:        }
                    172: #endif
1.14      ratchov   173:        f->tickpending++;
1.1       ratchov   174:        for (;;) {
                    175:                if (!sock_write(f))
                    176:                        break;
                    177:        }
                    178: }
                    179:
                    180: struct aproc_ops rsock_ops = {
                    181:        "rsock",
                    182:        rsock_in,
                    183:        rsock_out,
                    184:        rsock_eof,
                    185:        rsock_hup,
                    186:        NULL, /* newin */
                    187:        NULL, /* newout */
                    188:        NULL, /* ipos */
                    189:        rsock_opos,
                    190:        rsock_done
                    191: };
                    192:
                    193: void
                    194: wsock_done(struct aproc *p)
                    195: {
                    196:        struct sock *f = (struct sock *)p->u.io.file;
                    197:
1.11      ratchov   198:        if (f == NULL)
                    199:                return;
1.1       ratchov   200:        sock_reset(f);
                    201:        f->pipe.file.wproc = NULL;
                    202:        if (f->pipe.file.rproc) {
1.34      ratchov   203:                if (f->slot >= 0)
1.24      ratchov   204:                        ctl_slotdel(dev_midi, f->slot);
1.1       ratchov   205:                aproc_del(f->pipe.file.rproc);
                    206:                file_del(&f->pipe.file);
                    207:        }
1.11      ratchov   208:        p->u.io.file = NULL;
1.1       ratchov   209: }
                    210:
                    211: int
                    212: wsock_in(struct aproc *p, struct abuf *ibuf)
                    213: {
                    214:        struct sock *f = (struct sock *)p->u.io.file;
                    215:
1.19      ratchov   216:        if (f->pipe.file.state & FILE_WINUSE)
1.1       ratchov   217:                return 0;
                    218:        /*
1.20      ratchov   219:         * See remark in rsock_out().
1.1       ratchov   220:         */
                    221:        for (;;) {
                    222:                if (!sock_write(f))
                    223:                        return 0;
                    224:        }
                    225:        return 1;
                    226: }
                    227:
                    228: int
                    229: wsock_out(struct aproc *p, struct abuf *obuf_dummy)
                    230: {
                    231:        struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
                    232:        struct sock *f = (struct sock *)p->u.io.file;
                    233:
                    234:        if (ibuf) {
                    235:                if (!abuf_fill(ibuf))
                    236:                        return 0;
                    237:        }
                    238:        if (!sock_write(f))
                    239:                return 0;
                    240:        return 1;
                    241: }
                    242:
                    243: void
                    244: wsock_eof(struct aproc *p, struct abuf *obuf)
                    245: {
                    246:        aproc_del(p);
                    247: }
                    248:
                    249: void
                    250: wsock_hup(struct aproc *p, struct abuf *obuf_dummy)
                    251: {
                    252:        aproc_del(p);
                    253: }
                    254:
                    255: void
                    256: wsock_ipos(struct aproc *p, struct abuf *obuf, int delta)
                    257: {
                    258:        struct sock *f = (struct sock *)p->u.io.file;
                    259:
1.41    ! ratchov   260:        if (!(f->mode & AMSG_REC))
1.14      ratchov   261:                return;
1.1       ratchov   262:
1.14      ratchov   263:        f->delta += delta;
1.37      ratchov   264: #ifdef DEBUG
                    265:        if (debug_level >= 4) {
                    266:                aproc_dbg(p);
                    267:                dbg_puts(": moved to delta = ");
                    268:                dbg_puti(f->delta);
                    269:                dbg_puts("\n");
                    270:        }
                    271: #endif
1.33      ratchov   272:        f->tickpending++;
1.1       ratchov   273:        for (;;) {
                    274:                if (!sock_write(f))
                    275:                        break;
                    276:        }
                    277: }
                    278:
                    279: struct aproc_ops wsock_ops = {
                    280:        "wsock",
                    281:        wsock_in,
                    282:        wsock_out,
                    283:        wsock_eof,
                    284:        wsock_hup,
                    285:        NULL, /* newin */
                    286:        NULL, /* newout */
                    287:        wsock_ipos,
                    288:        NULL, /* opos */
                    289:        wsock_done
                    290: };
                    291:
                    292: /*
1.20      ratchov   293:  * Initialise socket in the SOCK_HELLO state with default
                    294:  * parameters.
1.1       ratchov   295:  */
                    296: struct sock *
1.19      ratchov   297: sock_new(struct fileops *ops, int fd)
1.1       ratchov   298: {
                    299:        struct aproc *rproc, *wproc;
                    300:        struct sock *f;
                    301:
1.19      ratchov   302:        f = (struct sock *)pipe_new(ops, fd, "sock");
1.13      ratchov   303:        if (f == NULL)
                    304:                return NULL;
1.18      ratchov   305:        f->pstate = SOCK_HELLO;
1.1       ratchov   306:        f->mode = 0;
1.19      ratchov   307:        f->opt = opt_byname("default");
                    308:        if (f->opt) {
1.41    ! ratchov   309:                if (dev_sub)
1.19      ratchov   310:                        f->wpar = f->opt->wpar;
1.41    ! ratchov   311:                if (dev_mix)
1.19      ratchov   312:                        f->rpar = f->opt->rpar;
1.1       ratchov   313:        }
                    314:        f->xrun = AMSG_IGNORE;
1.10      ratchov   315:        f->bufsz = dev_bufsz;
1.1       ratchov   316:        f->round = dev_round;
1.14      ratchov   317:        f->delta = 0;
                    318:        f->tickpending = 0;
1.25      ratchov   319:        f->vol = f->lastvol = MIDI_MAXCTL;
1.24      ratchov   320:        f->slot = -1;
1.1       ratchov   321:
1.19      ratchov   322:        wproc = aproc_new(&wsock_ops, f->pipe.file.name);
1.1       ratchov   323:        wproc->u.io.file = &f->pipe.file;
                    324:        f->pipe.file.wproc = wproc;
                    325:        f->wstate = SOCK_WIDLE;
                    326:        f->wtodo = 0xdeadbeef;
                    327:
1.19      ratchov   328:        rproc = aproc_new(&rsock_ops, f->pipe.file.name);
1.1       ratchov   329:        rproc->u.io.file = &f->pipe.file;
                    330:        f->pipe.file.rproc = rproc;
                    331:        f->rstate = SOCK_RMSG;
                    332:        f->rtodo = sizeof(struct amsg);
                    333:        return f;
                    334: }
                    335:
                    336: /*
1.20      ratchov   337:  * Free buffers.
1.1       ratchov   338:  */
                    339: void
                    340: sock_freebuf(struct sock *f)
                    341: {
                    342:        struct abuf *rbuf, *wbuf;
1.12      ratchov   343:
1.1       ratchov   344:        f->pstate = SOCK_INIT;
1.37      ratchov   345: #ifdef DEBUG
                    346:        if (debug_level >= 3) {
                    347:                sock_dbg(f);
                    348:                dbg_puts(": freeing buffers\n");
                    349:        }
                    350: #endif
1.35      ratchov   351:        wbuf = LIST_FIRST(&f->pipe.file.wproc->ibuflist);
1.1       ratchov   352:        rbuf = LIST_FIRST(&f->pipe.file.rproc->obuflist);
1.35      ratchov   353:        if (rbuf || wbuf)
                    354:                ctl_slotstop(dev_midi, f->slot);
1.1       ratchov   355:        if (rbuf)
                    356:                abuf_eof(rbuf);
                    357:        if (wbuf)
                    358:                abuf_hup(wbuf);
1.32      ratchov   359:        f->tickpending = 0;
1.1       ratchov   360: }
                    361:
                    362: /*
1.20      ratchov   363:  * Allocate buffers, so client can start filling write-end.
1.1       ratchov   364:  */
                    365: void
                    366: sock_allocbuf(struct sock *f)
                    367: {
                    368:        struct abuf *rbuf = NULL, *wbuf = NULL;
                    369:
                    370:        if (f->mode & AMSG_PLAY) {
1.10      ratchov   371:                rbuf = abuf_new(f->bufsz, &f->rpar);
1.1       ratchov   372:                aproc_setout(f->pipe.file.rproc, rbuf);
                    373:        }
1.41    ! ratchov   374:        if (f->mode & AMSG_REC) {
1.10      ratchov   375:                wbuf = abuf_new(f->bufsz, &f->wpar);
1.1       ratchov   376:                aproc_setin(f->pipe.file.wproc, wbuf);
1.41    ! ratchov   377:                f->walign = dev_round * wbuf->bpf;
1.1       ratchov   378:        }
1.14      ratchov   379:        f->delta = 0;
                    380:        f->tickpending = 0;
1.37      ratchov   381: #ifdef DEBUG
                    382:        if (debug_level >= 3) {
                    383:                sock_dbg(f);
                    384:                dbg_puts(": allocating ");
                    385:                dbg_putu(f->bufsz);
1.41    ! ratchov   386:                dbg_puts(" fr buffers\n");
1.37      ratchov   387:        }
                    388: #endif
1.41    ! ratchov   389:        f->pstate = SOCK_START;
        !           390:        if (!(f->mode & AMSG_PLAY) && ctl_slotstart(dev_midi, f->slot))
        !           391:                (void)sock_attach(f, 0);
1.1       ratchov   392: }
                    393:
                    394: /*
1.25      ratchov   395:  * Set volume. Callback invoked when volume is modified externally
1.3       ratchov   396:  */
                    397: void
1.25      ratchov   398: sock_setvol(void *arg, unsigned vol)
1.3       ratchov   399: {
1.25      ratchov   400:        struct sock *f = (struct sock *)arg;
1.3       ratchov   401:        struct abuf *rbuf;
1.12      ratchov   402:
1.3       ratchov   403:        f->vol = vol;
1.12      ratchov   404:        rbuf = LIST_FIRST(&f->pipe.file.rproc->obuflist);
1.3       ratchov   405:        if (!rbuf) {
1.37      ratchov   406: #ifdef DEBUG
                    407:                if (debug_level >= 3) {
                    408:                        sock_dbg(f);
                    409:                        dbg_puts(": no read buffer to set volume yet\n");
                    410:                }
                    411: #endif
1.3       ratchov   412:                return;
                    413:        }
1.25      ratchov   414:        dev_setvol(rbuf, MIDI_TO_ADATA(vol));
1.3       ratchov   415: }
                    416:
                    417: /*
1.35      ratchov   418:  * Attach the stream. Callback invoked when MMC start
                    419:  */
                    420: void
                    421: sock_startreq(void *arg)
                    422: {
                    423:        struct sock *f = (struct sock *)arg;
                    424:
1.37      ratchov   425: #ifdef DEBUG
1.41    ! ratchov   426:        if (f->pstate != SOCK_START) {
1.37      ratchov   427:                sock_dbg(f);
1.41    ! ratchov   428:                dbg_puts(": not in START state\n");
1.37      ratchov   429:                dbg_panic();
                    430:        }
                    431: #endif
1.35      ratchov   432:        (void)sock_attach(f, 0);
                    433: }
                    434:
                    435: /*
1.20      ratchov   436:  * Attach play and/or record buffers to dev_mix and/or dev_sub.
1.1       ratchov   437:  */
1.41    ! ratchov   438: int
1.1       ratchov   439: sock_attach(struct sock *f, int force)
                    440: {
                    441:        struct abuf *rbuf, *wbuf;
                    442:
                    443:        rbuf = LIST_FIRST(&f->pipe.file.rproc->obuflist);
                    444:        wbuf = LIST_FIRST(&f->pipe.file.wproc->ibuflist);
                    445:
                    446:        /*
1.20      ratchov   447:         * If in SOCK_START state, dont attach until
                    448:         * the buffer isn't completely filled.
1.1       ratchov   449:         */
                    450:        if (!force && rbuf && ABUF_WOK(rbuf))
1.41    ! ratchov   451:                return 0;
1.12      ratchov   452:
1.37      ratchov   453: #ifdef DEBUG
                    454:        if (debug_level >= 3) {
                    455:                sock_dbg(f);
1.41    ! ratchov   456:                dbg_puts(": attaching to device\n");
1.37      ratchov   457:        }
                    458: #endif
1.41    ! ratchov   459:        f->pstate = SOCK_RUN;
        !           460:
1.1       ratchov   461:        /*
1.41    ! ratchov   462:         * Attach them to the device.
1.1       ratchov   463:         */
1.41    ! ratchov   464:        dev_attach(f->pipe.file.name,
        !           465:            (f->mode & AMSG_PLAY) ? rbuf : NULL, &f->rpar, f->xrun,
        !           466:            (f->mode & AMSG_REC)  ? wbuf : NULL, &f->wpar, f->xrun,
        !           467:            f->opt->maxweight);
1.3       ratchov   468:        if (f->mode & AMSG_PLAY)
1.25      ratchov   469:                dev_setvol(rbuf, MIDI_TO_ADATA(f->vol));
1.3       ratchov   470:
1.1       ratchov   471:        /*
1.20      ratchov   472:         * Send the initial position, if needed.
1.1       ratchov   473:         */
                    474:        for (;;) {
                    475:                if (!sock_write(f))
                    476:                        break;
                    477:        }
1.41    ! ratchov   478:        return 1;
1.1       ratchov   479: }
                    480:
                    481: void
                    482: sock_reset(struct sock *f)
                    483: {
                    484:        switch (f->pstate) {
                    485:        case SOCK_START:
1.35      ratchov   486:                if (ctl_slotstart(dev_midi, f->slot)) {
                    487:                        (void)sock_attach(f, 1);
                    488:                        f->pstate = SOCK_RUN;
                    489:                }
1.1       ratchov   490:                /* PASSTHROUGH */
                    491:        case SOCK_RUN:
                    492:                sock_freebuf(f);
                    493:                f->pstate = SOCK_INIT;
                    494:                /* PASSTHROUGH */
                    495:        case SOCK_INIT:
                    496:                /* nothing yet */
                    497:                break;
                    498:        }
                    499: }
                    500:
                    501: /*
1.20      ratchov   502:  * Read a message from the file descriptor, return 1 if done, 0
                    503:  * otherwise. The message is stored in f->rmsg.
1.1       ratchov   504:  */
                    505: int
                    506: sock_rmsg(struct sock *f)
                    507: {
                    508:        unsigned count;
                    509:        unsigned char *data;
                    510:
                    511:        while (f->rtodo > 0) {
                    512:                if (!(f->pipe.file.state & FILE_ROK)) {
1.37      ratchov   513: #ifdef DEBUG
                    514:                        if (debug_level >= 4) {
                    515:                                sock_dbg(f);
                    516:                                dbg_puts(": reading message blocked, ");
                    517:                                dbg_putu(f->rtodo);
                    518:                                dbg_puts(" bytes remaining\n");
                    519:                        }
                    520: #endif
1.1       ratchov   521:                        return 0;
                    522:                }
                    523:                data = (unsigned char *)&f->rmsg;
                    524:                data += sizeof(struct amsg) - f->rtodo;
                    525:                count = file_read(&f->pipe.file, data, f->rtodo);
                    526:                if (count == 0)
                    527:                        return 0;
                    528:                f->rtodo -= count;
                    529:        }
1.37      ratchov   530: #ifdef DEBUG
                    531:        if (debug_level >= 4) {
                    532:                sock_dbg(f);
                    533:                dbg_puts(": read full message\n");
                    534:        }
                    535: #endif
1.1       ratchov   536:        return 1;
                    537: }
                    538:
                    539: /*
1.20      ratchov   540:  * Write a message to the file descriptor, return 1 if done, 0
1.1       ratchov   541:  * otherwise.  The "m" argument is f->rmsg or f->wmsg, and the "ptodo"
                    542:  * points to the f->rtodo or f->wtodo respectively.
                    543:  */
                    544: int
                    545: sock_wmsg(struct sock *f, struct amsg *m, unsigned *ptodo)
                    546: {
                    547:        unsigned count;
                    548:        unsigned char *data;
                    549:
                    550:        while (*ptodo > 0) {
                    551:                if (!(f->pipe.file.state & FILE_WOK)) {
1.37      ratchov   552: #ifdef DEBUG
                    553:                        if (debug_level >= 4) {
                    554:                                sock_dbg(f);
                    555:                                dbg_puts(": writing message blocked, ");
                    556:                                dbg_putu(*ptodo);
                    557:                                dbg_puts(" bytes remaining\n");
                    558:                        }
                    559: #endif
1.1       ratchov   560:                        return 0;
                    561:                }
                    562:                data = (unsigned char *)m;
                    563:                data += sizeof(struct amsg) - *ptodo;
                    564:                count = file_write(&f->pipe.file, data, *ptodo);
                    565:                if (count == 0)
                    566:                        return 0;
                    567:                *ptodo -= count;
                    568:        }
1.37      ratchov   569: #ifdef DEBUG
                    570:        if (debug_level >= 4) {
                    571:                sock_dbg(f);
                    572:                dbg_puts(": wrote full message\n");
                    573:        }
                    574: #endif
1.1       ratchov   575:        return 1;
                    576: }
                    577:
                    578: /*
1.20      ratchov   579:  * Read data chunk from the file descriptor, return 1 if at least one
1.1       ratchov   580:  * byte was read, 0 if the file blocked.
                    581:  */
                    582: int
                    583: sock_rdata(struct sock *f)
                    584: {
                    585:        struct aproc *p;
                    586:        struct abuf *obuf;
1.41    ! ratchov   587:        unsigned char *data;
        !           588:        unsigned count, n;
1.1       ratchov   589:
1.37      ratchov   590: #ifdef DEBUG
                    591:        if (f->pstate != SOCK_MIDI && f->rtodo == 0) {
                    592:                sock_dbg(f);
                    593:                dbg_puts(": data block already read\n");
                    594:                dbg_panic();
                    595:        }
                    596: #endif
1.1       ratchov   597:        p = f->pipe.file.rproc;
                    598:        obuf = LIST_FIRST(&p->obuflist);
1.19      ratchov   599:        if (obuf == NULL)
                    600:                return 0;
1.41    ! ratchov   601:        if (ABUF_FULL(obuf) || !(f->pipe.file.state & FILE_ROK))
        !           602:                return 0;
        !           603:        data = abuf_wgetblk(obuf, &count, 0);
        !           604:        if (f->pstate != SOCK_MIDI && count > f->rtodo)
        !           605:                count = f->rtodo;
        !           606:        n = file_read(&f->pipe.file, data, count);
        !           607:        if (n == 0)
1.1       ratchov   608:                return 0;
1.41    ! ratchov   609:        abuf_wcommit(obuf, n);
        !           610:        if (f->pstate != SOCK_MIDI)
1.19      ratchov   611:                f->rtodo -= n;
1.1       ratchov   612:        return 1;
                    613: }
                    614:
                    615: /*
1.20      ratchov   616:  * Write data chunk to the file descriptor, return 1 if at least one
1.1       ratchov   617:  * byte was written, 0 if the file blocked.
                    618:  */
                    619: int
                    620: sock_wdata(struct sock *f)
                    621: {
                    622:        struct aproc *p;
                    623:        struct abuf *ibuf;
1.41    ! ratchov   624:        unsigned char *data;
        !           625:        unsigned count, n;
        !           626: #define ZERO_MAX 0x1000
        !           627:        static unsigned char zero[ZERO_MAX];
1.1       ratchov   628:
1.37      ratchov   629: #ifdef DEBUG
                    630:        if (f->pstate != SOCK_MIDI && f->wtodo == 0) {
                    631:                sock_dbg(f);
                    632:                dbg_puts(": attempted to write zero-sized data block\n");
                    633:                dbg_panic();
                    634:        }
                    635: #endif
1.1       ratchov   636:        if (!(f->pipe.file.state & FILE_WOK))
                    637:                return 0;
                    638:        p = f->pipe.file.wproc;
                    639:        ibuf = LIST_FIRST(&p->ibuflist);
1.41    ! ratchov   640:        if (ibuf) {
        !           641:                if (ABUF_EMPTY(ibuf))
1.1       ratchov   642:                        return 0;
1.41    ! ratchov   643:                data = abuf_rgetblk(ibuf, &count, 0);
        !           644:                if (f->pstate != SOCK_MIDI && count > f->wtodo)
        !           645:                        count = f->wtodo;
        !           646:                n = file_write(&f->pipe.file, data, count);
        !           647:                if (n == 0)
        !           648:                        return 0;
        !           649:                abuf_rdiscard(ibuf, n);
        !           650:                if (f->pstate != SOCK_MIDI)
        !           651:                        f->wtodo -= n;
1.1       ratchov   652:        } else {
1.41    ! ratchov   653:                if (f->pstate == SOCK_MIDI)
        !           654:                        return 0;
        !           655:                /*
        !           656:                 * There's no dev_detach() routine yet,
        !           657:                 * so now we abruptly destroy the buffer.
        !           658:                 * Until we implement dev_detach, complete
        !           659:                 * the packet with zeros...
        !           660:                 */
        !           661:                count = ZERO_MAX;
        !           662:                if (count > f->wtodo)
        !           663:                        count = f->wtodo;
        !           664:                n = file_write(&f->pipe.file, zero, count);
        !           665:                if (n == 0)
1.1       ratchov   666:                        return 0;
                    667:                f->wtodo -= n;
1.12      ratchov   668:        }
1.1       ratchov   669:        return 1;
                    670: }
                    671:
                    672: int
                    673: sock_setpar(struct sock *f)
                    674: {
                    675:        struct amsg_par *p = &f->rmsg.u.par;
1.9       ratchov   676:        unsigned min, max, rate;
1.12      ratchov   677:
1.1       ratchov   678:        if (AMSG_ISSET(p->bits)) {
                    679:                if (p->bits < BITS_MIN || p->bits > BITS_MAX) {
1.37      ratchov   680: #ifdef DEBUG
                    681:                        if (debug_level >= 1) {
                    682:                                sock_dbg(f);
                    683:                                dbg_puts(": ");
                    684:                                dbg_putu(p->bits);
                    685:                                dbg_puts(": bits out of bounds\n");
                    686:                        }
                    687: #endif
1.1       ratchov   688:                        return 0;
                    689:                }
                    690:                if (AMSG_ISSET(p->bps)) {
                    691:                        if (p->bps < ((p->bits + 7) / 8) || p->bps > 4) {
1.37      ratchov   692: #ifdef DEBUG
                    693:                                if (debug_level >= 1) {
                    694:                                        sock_dbg(f);
                    695:                                        dbg_puts(": ");
                    696:                                        dbg_putu(p->bps);
                    697:                                        dbg_puts(": wrong bytes per sample\n");
                    698:                                }
                    699: #endif
1.1       ratchov   700:                                return 0;
                    701:                        }
                    702:                } else
                    703:                        p->bps = APARAMS_BPS(p->bits);
                    704:                f->rpar.bits = f->wpar.bits = p->bits;
                    705:                f->rpar.bps = f->wpar.bps = p->bps;
1.37      ratchov   706: #ifdef DEBUG
                    707:                if (debug_level >= 3) {
                    708:                        sock_dbg(f);
                    709:                        dbg_puts(": using ");
                    710:                        dbg_putu(p->bits);
                    711:                        dbg_puts("bits, ");
                    712:                        dbg_putu(p->bps);
                    713:                        dbg_puts(" bytes per sample\n");
                    714:                }
                    715: #endif
1.1       ratchov   716:        }
                    717:        if (AMSG_ISSET(p->sig))
                    718:                f->rpar.sig = f->wpar.sig = p->sig ? 1 : 0;
                    719:        if (AMSG_ISSET(p->le))
                    720:                f->rpar.le = f->wpar.le = p->le ? 1 : 0;
                    721:        if (AMSG_ISSET(p->msb))
                    722:                f->rpar.msb = f->wpar.msb = p->msb ? 1 : 0;
1.41    ! ratchov   723:        if (AMSG_ISSET(p->rchan) && (f->mode & AMSG_REC)) {
1.1       ratchov   724:                if (p->rchan < 1)
                    725:                        p->rchan = 1;
1.6       ratchov   726:                if (p->rchan > NCHAN_MAX)
                    727:                        p->rchan = NCHAN_MAX;
1.19      ratchov   728:                f->wpar.cmin = f->opt->wpar.cmin;
                    729:                f->wpar.cmax = f->opt->wpar.cmin + p->rchan - 1;
                    730:                if (f->wpar.cmax > f->opt->wpar.cmax)
                    731:                        f->wpar.cmax = f->opt->wpar.cmax;
1.37      ratchov   732: #ifdef DEBUG
                    733:                if (debug_level >= 3) {
                    734:                        sock_dbg(f);
                    735:                        dbg_puts(": using recording channels ");
                    736:                        dbg_putu(f->wpar.cmin);
                    737:                        dbg_puts("..");
                    738:                        dbg_putu(f->wpar.cmax);
                    739:                        dbg_puts("\n");
                    740:                }
                    741: #endif
1.1       ratchov   742:        }
                    743:        if (AMSG_ISSET(p->pchan) && (f->mode & AMSG_PLAY)) {
                    744:                if (p->pchan < 1)
                    745:                        p->pchan = 1;
1.6       ratchov   746:                if (p->pchan > NCHAN_MAX)
                    747:                        p->pchan = NCHAN_MAX;
1.19      ratchov   748:                f->rpar.cmin = f->opt->rpar.cmin;
                    749:                f->rpar.cmax = f->opt->rpar.cmin + p->pchan - 1;
                    750:                if (f->rpar.cmax > f->opt->rpar.cmax)
                    751:                        f->rpar.cmax = f->opt->rpar.cmax;
1.37      ratchov   752: #ifdef DEBUG
                    753:                if (debug_level >= 3) {
                    754:                        sock_dbg(f);
                    755:                        dbg_puts(": using playback channels ");
                    756:                        dbg_putu(f->rpar.cmin);
                    757:                        dbg_puts("..");
                    758:                        dbg_putu(f->rpar.cmax);
                    759:                        dbg_puts("\n");
                    760:                }
                    761: #endif
1.1       ratchov   762:        }
                    763:        if (AMSG_ISSET(p->rate)) {
                    764:                if (p->rate < RATE_MIN)
                    765:                        p->rate = RATE_MIN;
                    766:                if (p->rate > RATE_MAX)
                    767:                        p->rate = RATE_MAX;
1.9       ratchov   768:                f->round = dev_roundof(p->rate);
1.1       ratchov   769:                f->rpar.rate = f->wpar.rate = p->rate;
1.10      ratchov   770:                if (!AMSG_ISSET(p->appbufsz)) {
                    771:                        p->appbufsz = dev_bufsz / dev_round * f->round;
1.37      ratchov   772: #ifdef DEBUG
                    773:                        if (debug_level >= 3) {
                    774:                                sock_dbg(f);
                    775:                                dbg_puts(": using ");
                    776:                                dbg_putu(p->appbufsz);
                    777:                                dbg_puts(" fr app buffer size\n");
                    778:                        }
                    779: #endif
                    780:                }
                    781: #ifdef DEBUG
                    782:                if (debug_level >= 3) {
                    783:                        sock_dbg(f);
                    784:                        dbg_puts(": using ");
                    785:                        dbg_putu(p->rate);
                    786:                        dbg_puts("Hz sample rate, ");
                    787:                        dbg_putu(f->round);
                    788:                        dbg_puts(" fr block size\n");
1.10      ratchov   789:                }
1.37      ratchov   790: #endif
1.1       ratchov   791:        }
                    792:        if (AMSG_ISSET(p->xrun)) {
                    793:                if (p->xrun != AMSG_IGNORE &&
                    794:                    p->xrun != AMSG_SYNC &&
                    795:                    p->xrun != AMSG_ERROR) {
1.37      ratchov   796: #ifdef DEBUG
                    797:                        if (debug_level >= 1) {
                    798:                                sock_dbg(f);
                    799:                                dbg_puts(": ");
                    800:                                dbg_putx(p->xrun);
                    801:                                dbg_puts(": bad xrun policy\n");
                    802:                        }
                    803: #endif
1.1       ratchov   804:                        return 0;
                    805:                }
                    806:                f->xrun = p->xrun;
1.35      ratchov   807:                if (f->opt->mmc && f->xrun == AMSG_IGNORE)
                    808:                        f->xrun = AMSG_SYNC;
1.37      ratchov   809: #ifdef DEBUG
                    810:                if (debug_level >= 3) {
                    811:                        sock_dbg(f);
                    812:                        dbg_puts(": using 0x");
                    813:                        dbg_putx(f->xrun);
                    814:                        dbg_puts(" xrun policy\n");
                    815:                }
                    816: #endif
1.1       ratchov   817:        }
                    818:        if (AMSG_ISSET(p->bufsz)) {
1.10      ratchov   819:                /*
                    820:                 * XXX: bufsz will become read-only, but for now
                    821:                 *      allow old library to properly work
                    822:                 */
1.37      ratchov   823: #ifdef DEBUG
                    824:                if (debug_level >= 1) {
                    825:                        sock_dbg(f);
                    826:                        dbg_puts(": legacy client using ");
                    827:                        dbg_putx(p->bufsz);
                    828:                        dbg_puts("fr total buffer size\n");
                    829:                }
                    830: #endif
1.10      ratchov   831:                min = (dev_bufsz / dev_round) * f->round;
                    832:                if (p->bufsz < min)
                    833:                        p->bufsz = min;
                    834:                p->appbufsz = p->bufsz - min;
                    835:        }
                    836:        if (AMSG_ISSET(p->appbufsz)) {
1.9       ratchov   837:                rate = (f->mode & AMSG_PLAY) ? f->rpar.rate : f->wpar.rate;
1.41    ! ratchov   838:                min = 2;
        !           839:                max = 2 + rate / dev_round;
1.9       ratchov   840:                min *= f->round;
                    841:                max *= f->round;
1.10      ratchov   842:                p->appbufsz += f->round - 1;
                    843:                p->appbufsz -= p->appbufsz % f->round;
                    844:                if (p->appbufsz < min)
                    845:                        p->appbufsz = min;
                    846:                if (p->appbufsz > max)
                    847:                        p->appbufsz = max;
                    848:                f->bufsz = p->appbufsz;
1.37      ratchov   849: #ifdef DEBUG
                    850:                if (debug_level >= 3) {
                    851:                        sock_dbg(f);
                    852:                        dbg_puts(": using ");
                    853:                        dbg_putu(f->bufsz);
                    854:                        dbg_puts(" buffer size\n");
                    855:                }
                    856: #endif
                    857:        }
                    858: #ifdef DEBUG
                    859:        if (debug_level >= 2) {
1.41    ! ratchov   860:                if (f->slot >= -1 && dev_midi) {
1.37      ratchov   861:                        dbg_puts(dev_midi->u.ctl.slot[f->slot].name);
                    862:                        dbg_putu(dev_midi->u.ctl.slot[f->slot].unit);
                    863:                } else
                    864:                        dbg_puts(f->pipe.file.name);
                    865:                dbg_puts(": buffer size = ");
                    866:                dbg_putu(f->bufsz);
                    867:                if (f->mode & AMSG_PLAY) {
                    868:                        dbg_puts(", play = ");
                    869:                        aparams_dbg(&f->rpar);
                    870:                }
1.41    ! ratchov   871:                if (f->mode & AMSG_REC) {
1.37      ratchov   872:                        dbg_puts(", rec:");
                    873:                        aparams_dbg(&f->wpar);
                    874:                }
                    875:                dbg_puts("\n");
1.1       ratchov   876:        }
1.37      ratchov   877: #endif
1.1       ratchov   878:        return 1;
                    879: }
                    880:
1.19      ratchov   881: /*
                    882:  * allocate buffers, so client can start filling write-end.
                    883:  */
                    884: void
                    885: sock_midiattach(struct sock *f, unsigned mode)
                    886: {
                    887:        struct abuf *rbuf = NULL, *wbuf = NULL;
                    888:
                    889:        if (mode & AMSG_MIDIOUT) {
1.22      ratchov   890:                rbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
1.19      ratchov   891:                aproc_setout(f->pipe.file.rproc, rbuf);
                    892:        }
                    893:        if (mode & AMSG_MIDIIN) {
1.22      ratchov   894:                wbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
1.19      ratchov   895:                aproc_setin(f->pipe.file.wproc, wbuf);
                    896:        }
1.23      ratchov   897:        dev_midiattach(rbuf, wbuf);
1.19      ratchov   898: }
                    899:
1.17      ratchov   900: int
                    901: sock_hello(struct sock *f)
                    902: {
                    903:        struct amsg_hello *p = &f->rmsg.u.hello;
                    904:
1.37      ratchov   905: #ifdef DEBUG
                    906:        if (debug_level >= 3) {
                    907:                sock_dbg(f);
                    908:                dbg_puts(": hello from <");
                    909:                dbg_puts(p->who);
                    910:                dbg_puts(">, proto = ");
                    911:                dbg_putx(p->proto);
                    912:                dbg_puts(", ver ");
                    913:                dbg_putu(p->version);
                    914:                dbg_puts("\n");
                    915:        }
                    916: #endif
1.33      ratchov   917:        if (p->version != AMSG_VERSION) {
1.37      ratchov   918: #ifdef DEBUG
                    919:                if (debug_level >= 1) {
                    920:                        sock_dbg(f);
                    921:                        dbg_puts(": ");
                    922:                        dbg_putu(p->version);
                    923:                        dbg_puts(": bad version\n");
                    924:                }
                    925: #endif
1.33      ratchov   926:                return 0;
                    927:        }
                    928:        /*
                    929:         * XXX : dev_midi can no longer be NULL, right ?
                    930:         */
1.41    ! ratchov   931:        if (dev_midi && (p->proto & (AMSG_MIDIIN | AMSG_MIDIOUT))) {
1.19      ratchov   932:                if (p->proto & ~(AMSG_MIDIIN | AMSG_MIDIOUT)) {
1.37      ratchov   933: #ifdef DEBUG
                    934:                        if (debug_level >= 1) {
                    935:                                sock_dbg(f);
                    936:                                dbg_puts(": ");
                    937:                                dbg_putx(p->proto);
                    938:                                dbg_puts(": bad hello protocol\n");
                    939:                        }
                    940: #endif
1.19      ratchov   941:                        return 0;
                    942:                }
                    943:                f->mode = p->proto;
                    944:                f->pstate = SOCK_MIDI;
                    945:                sock_midiattach(f, p->proto);
                    946:                return 1;
                    947:        }
                    948:        f->opt = opt_byname(p->opt);
                    949:        if (f->opt == NULL)
                    950:                return 0;
1.41    ! ratchov   951:        if (dev_sub)
1.19      ratchov   952:                f->wpar = f->opt->wpar;
1.41    ! ratchov   953:        if (dev_mix)
1.19      ratchov   954:                f->rpar = f->opt->rpar;
1.35      ratchov   955:        if (f->opt->mmc)
                    956:                f->xrun = AMSG_SYNC;
1.18      ratchov   957:        if ((p->proto & ~(AMSG_PLAY | AMSG_REC)) != 0 ||
                    958:            (p->proto &  (AMSG_PLAY | AMSG_REC)) == 0) {
1.37      ratchov   959: #ifdef DEBUG
                    960:                if (debug_level >= 1) {
                    961:                        sock_dbg(f);
                    962:                        dbg_puts(": ");
                    963:                        dbg_putx(p->proto);
                    964:                        dbg_puts(": unsupported hello protocol\n");
                    965:                }
                    966: #endif
1.17      ratchov   967:                return 0;
                    968:        }
1.18      ratchov   969:        f->mode = 0;
                    970:        if (p->proto & AMSG_PLAY) {
1.41    ! ratchov   971:                if (!dev_mix) {
1.37      ratchov   972: #ifdef DEBUG
                    973:                        if (debug_level >= 1) {
                    974:                                sock_dbg(f);
                    975:                                dbg_puts(": playback not available\n");
                    976:                        }
                    977: #endif
1.18      ratchov   978:                        return 0;
                    979:                }
                    980:                f->mode |= AMSG_PLAY;
1.17      ratchov   981:        }
1.18      ratchov   982:        if (p->proto & AMSG_REC) {
1.41    ! ratchov   983:                if (!dev_sub) {
1.37      ratchov   984: #ifdef DEBUG
                    985:                        if (debug_level >= 1) {
                    986:                                sock_dbg(f);
                    987:                                dbg_puts(": recording not available\n");
                    988:                        }
                    989: #endif
1.18      ratchov   990:                        return 0;
                    991:                }
1.41    ! ratchov   992:                f->mode |= AMSG_REC;
1.17      ratchov   993:        }
1.41    ! ratchov   994:        if (dev_midi) {
1.35      ratchov   995:                f->slot = ctl_slotnew(dev_midi,
                    996:                     p->who, &ctl_sockops, f,
                    997:                     f->opt->mmc);
1.24      ratchov   998:                if (f->slot < 0) {
1.37      ratchov   999: #ifdef DEBUG
                   1000:                        if (debug_level >= 1) {
                   1001:                                sock_dbg(f);
                   1002:                                dbg_puts(": out of mixer slots\n");
                   1003:                        }
                   1004: #endif
1.24      ratchov  1005:                        return 0;
                   1006:                }
                   1007:        }
1.18      ratchov  1008:        f->pstate = SOCK_INIT;
1.17      ratchov  1009:        return 1;
                   1010: }
                   1011:
1.1       ratchov  1012: /*
1.20      ratchov  1013:  * Execute message in f->rmsg and change the state accordingly; return 1
1.1       ratchov  1014:  * on success, and 0 on failure, in which case the socket is destroyed.
                   1015:  */
                   1016: int
                   1017: sock_execmsg(struct sock *f)
                   1018: {
                   1019:        struct amsg *m = &f->rmsg;
                   1020:
                   1021:        switch (m->cmd) {
                   1022:        case AMSG_DATA:
1.37      ratchov  1023: #ifdef DEBUG
                   1024:                if (debug_level >= 4) {
                   1025:                        sock_dbg(f);
                   1026:                        dbg_puts(": DATA message\n");
                   1027:                }
                   1028: #endif
1.41    ! ratchov  1029:                if (f->pstate != SOCK_RUN && f->pstate != SOCK_START) {
1.37      ratchov  1030: #ifdef DEBUG
                   1031:                        if (debug_level >= 1) {
                   1032:                                sock_dbg(f);
                   1033:                                dbg_puts(": DATA, bad state\n");
                   1034:                        }
                   1035: #endif
1.8       ratchov  1036:                        aproc_del(f->pipe.file.rproc);
                   1037:                        return 0;
                   1038:                }
                   1039:                if (!(f->mode & AMSG_PLAY)) {
1.37      ratchov  1040: #ifdef DEBUG
                   1041:                        if (debug_level >= 1) {
                   1042:                                sock_dbg(f);
                   1043:                                dbg_puts(": DATA not allowed in record-only mode\n");
                   1044:                        }
                   1045: #endif
1.1       ratchov  1046:                        aproc_del(f->pipe.file.rproc);
                   1047:                        return 0;
                   1048:                }
1.41    ! ratchov  1049:                if (f->pstate == SOCK_START &&
        !          1050:                    ABUF_FULL(LIST_FIRST(&f->pipe.file.rproc->obuflist))) {
1.37      ratchov  1051: #ifdef DEBUG
                   1052:                        if (debug_level >= 1) {
                   1053:                                sock_dbg(f);
                   1054:                                dbg_puts(": DATA client violates flow control\n");
                   1055:                        }
                   1056: #endif
1.34      ratchov  1057:                        aproc_del(f->pipe.file.rproc);
                   1058:                        return 0;
                   1059:                }
1.1       ratchov  1060:                f->rstate = SOCK_RDATA;
1.41    ! ratchov  1061:                f->rtodo = m->u.data.size;
1.1       ratchov  1062:                if (f->rtodo == 0) {
1.37      ratchov  1063: #ifdef DEBUG
                   1064:                        if (debug_level >= 1) {
                   1065:                                sock_dbg(f);
                   1066:                                dbg_puts(": zero-length data chunk\n");
                   1067:                        }
                   1068: #endif
1.1       ratchov  1069:                        aproc_del(f->pipe.file.rproc);
                   1070:                        return 0;
                   1071:                }
                   1072:                break;
                   1073:        case AMSG_START:
1.37      ratchov  1074: #ifdef DEBUG
                   1075:                if (debug_level >= 3) {
                   1076:                        sock_dbg(f);
                   1077:                        dbg_puts(": START message\n");
                   1078:                }
                   1079: #endif
1.1       ratchov  1080:                if (f->pstate != SOCK_INIT) {
1.37      ratchov  1081: #ifdef DEBUG
                   1082:                        if (debug_level >= 1) {
                   1083:                                sock_dbg(f);
                   1084:                                dbg_puts(": START, bad state\n");
                   1085:                        }
                   1086: #endif
1.1       ratchov  1087:                        aproc_del(f->pipe.file.rproc);
                   1088:                        return 0;
                   1089:                }
                   1090:                sock_allocbuf(f);
                   1091:                f->rstate = SOCK_RMSG;
                   1092:                f->rtodo = sizeof(struct amsg);
                   1093:                break;
                   1094:        case AMSG_STOP:
1.37      ratchov  1095: #ifdef DEBUG
                   1096:                if (debug_level >= 3) {
                   1097:                        sock_dbg(f);
                   1098:                        dbg_puts(": STOP message\n");
                   1099:                }
                   1100: #endif
1.41    ! ratchov  1101:                if (f->pstate != SOCK_RUN && f->pstate != SOCK_START) {
1.37      ratchov  1102: #ifdef DEBUG
                   1103:                        if (debug_level >= 1) {
                   1104:                                sock_dbg(f);
                   1105:                                dbg_puts(": STOP, bad state\n");
                   1106:                        }
                   1107: #endif
1.1       ratchov  1108:                        aproc_del(f->pipe.file.rproc);
                   1109:                        return 0;
                   1110:                }
1.41    ! ratchov  1111:                if (f->pstate == SOCK_START &&
1.35      ratchov  1112:                    ctl_slotstart(dev_midi, f->slot))
1.1       ratchov  1113:                        (void)sock_attach(f, 1);
1.41    ! ratchov  1114:                sock_freebuf(f);
1.1       ratchov  1115:                AMSG_INIT(m);
                   1116:                m->cmd = AMSG_ACK;
                   1117:                f->rstate = SOCK_RRET;
                   1118:                f->rtodo = sizeof(struct amsg);
                   1119:                break;
                   1120:        case AMSG_SETPAR:
1.37      ratchov  1121: #ifdef DEBUG
                   1122:                if (debug_level >= 3) {
                   1123:                        sock_dbg(f);
                   1124:                        dbg_puts(": SETPAR message\n");
                   1125:                }
                   1126: #endif
1.1       ratchov  1127:                if (f->pstate != SOCK_INIT) {
1.37      ratchov  1128: #ifdef DEBUG
                   1129:                        if (debug_level >= 1) {
                   1130:                                sock_dbg(f);
                   1131:                                dbg_puts(": SETPAR, bad state\n");
                   1132:                        }
                   1133: #endif
1.1       ratchov  1134:                        aproc_del(f->pipe.file.rproc);
                   1135:                        return 0;
                   1136:                }
                   1137:                if (!sock_setpar(f)) {
                   1138:                        aproc_del(f->pipe.file.rproc);
                   1139:                        return 0;
                   1140:                }
                   1141:                f->rtodo = sizeof(struct amsg);
                   1142:                f->rstate = SOCK_RMSG;
                   1143:                break;
                   1144:        case AMSG_GETPAR:
1.37      ratchov  1145: #ifdef DEBUG
                   1146:                if (debug_level >= 3) {
                   1147:                        sock_dbg(f);
                   1148:                        dbg_puts(": GETPAR message\n");
                   1149:                }
                   1150: #endif
1.1       ratchov  1151:                if (f->pstate != SOCK_INIT) {
1.37      ratchov  1152: #ifdef DEBUG
                   1153:                        if (debug_level >= 1) {
                   1154:                                sock_dbg(f);
                   1155:                                dbg_puts(": GETPAR, bad state\n");
                   1156:                        }
                   1157: #endif
1.1       ratchov  1158:                        aproc_del(f->pipe.file.rproc);
                   1159:                        return 0;
                   1160:                }
                   1161:                AMSG_INIT(m);
                   1162:                m->cmd = AMSG_GETPAR;
1.18      ratchov  1163:                m->u.par.legacy_mode = f->mode;
1.41    ! ratchov  1164:                m->u.par.bits = f->rpar.bits;
        !          1165:                m->u.par.bps = f->rpar.bps;
        !          1166:                m->u.par.sig = f->rpar.sig;
        !          1167:                m->u.par.le = f->rpar.le;
        !          1168:                m->u.par.msb = f->rpar.msb;
        !          1169:                m->u.par.rate = f->rpar.rate;
        !          1170:                m->u.par.rchan = f->wpar.cmax - f->wpar.cmin + 1;
        !          1171:                m->u.par.pchan = f->rpar.cmax - f->rpar.cmin + 1;
1.10      ratchov  1172:                m->u.par.appbufsz = f->bufsz;
1.12      ratchov  1173:                m->u.par.bufsz =
1.10      ratchov  1174:                    f->bufsz + (dev_bufsz / dev_round) * f->round;
1.1       ratchov  1175:                m->u.par.round = f->round;
                   1176:                f->rstate = SOCK_RRET;
                   1177:                f->rtodo = sizeof(struct amsg);
                   1178:                break;
                   1179:        case AMSG_GETCAP:
1.37      ratchov  1180: #ifdef DEBUG
                   1181:                if (debug_level >= 3) {
                   1182:                        sock_dbg(f);
                   1183:                        dbg_puts(": GETCAP message\n");
                   1184:                }
                   1185: #endif
1.1       ratchov  1186:                if (f->pstate != SOCK_INIT) {
1.37      ratchov  1187: #ifdef DEBUG
                   1188:                        if (debug_level >= 1) {
                   1189:                                sock_dbg(f);
                   1190:                                dbg_puts(": GETCAP, bad state\n");
                   1191:                        }
                   1192: #endif
1.1       ratchov  1193:                        aproc_del(f->pipe.file.rproc);
                   1194:                        return 0;
                   1195:                }
                   1196:                AMSG_INIT(m);
                   1197:                m->cmd = AMSG_GETCAP;
                   1198:                m->u.cap.rate = dev_rate;
1.41    ! ratchov  1199:                m->u.cap.pchan = dev_mix ?
1.19      ratchov  1200:                    (f->opt->rpar.cmax - f->opt->rpar.cmin + 1) : 0;
1.41    ! ratchov  1201:                m->u.cap.rchan = dev_sub ?
1.19      ratchov  1202:                    (f->opt->wpar.cmax - f->opt->wpar.cmin + 1) : 0;
1.1       ratchov  1203:                m->u.cap.bits = sizeof(short) * 8;
                   1204:                m->u.cap.bps = sizeof(short);
                   1205:                f->rstate = SOCK_RRET;
                   1206:                f->rtodo = sizeof(struct amsg);
1.3       ratchov  1207:                break;
                   1208:        case AMSG_SETVOL:
1.37      ratchov  1209: #ifdef DEBUG
                   1210:                if (debug_level >= 3) {
                   1211:                        sock_dbg(f);
                   1212:                        dbg_puts(": SETVOL message\n");
                   1213:                }
                   1214: #endif
1.41    ! ratchov  1215:                if (f->pstate != SOCK_RUN &&
        !          1216:                    f->pstate != SOCK_START && f->pstate != SOCK_INIT) {
1.37      ratchov  1217: #ifdef DEBUG
                   1218:                        if (debug_level >= 1) {
                   1219:                                sock_dbg(f);
                   1220:                                dbg_puts(": SETVOL, bad state\n");
                   1221:                        }
                   1222: #endif
1.3       ratchov  1223:                        aproc_del(f->pipe.file.rproc);
                   1224:                        return 0;
                   1225:                }
                   1226:                if (m->u.vol.ctl > MIDI_MAXCTL) {
1.37      ratchov  1227: #ifdef DEBUG
                   1228:                        if (debug_level >= 1) {
                   1229:                                sock_dbg(f);
                   1230:                                dbg_puts(": SETVOL, volume out of range\n");
                   1231:                        }
                   1232: #endif
1.3       ratchov  1233:                        aproc_del(f->pipe.file.rproc);
                   1234:                        return 0;
                   1235:                }
1.25      ratchov  1236:                sock_setvol(f, m->u.vol.ctl);
1.34      ratchov  1237:                if (f->slot >= 0)
1.24      ratchov  1238:                        ctl_slotvol(dev_midi, f->slot, m->u.vol.ctl);
1.3       ratchov  1239:                f->rtodo = sizeof(struct amsg);
                   1240:                f->rstate = SOCK_RMSG;
1.17      ratchov  1241:                break;
                   1242:        case AMSG_HELLO:
1.37      ratchov  1243: #ifdef DEBUG
                   1244:                if (debug_level >= 3) {
                   1245:                        sock_dbg(f);
                   1246:                        dbg_puts(": HELLO message\n");
                   1247:                }
                   1248: #endif
1.18      ratchov  1249:                if (f->pstate != SOCK_HELLO) {
1.37      ratchov  1250: #ifdef DEBUG
                   1251:                        if (debug_level >= 1) {
                   1252:                                sock_dbg(f);
                   1253:                                dbg_puts(": HELLO, bad state\n");
                   1254:                        }
                   1255: #endif
1.17      ratchov  1256:                        aproc_del(f->pipe.file.rproc);
                   1257:                        return 0;
                   1258:                }
                   1259:                if (!sock_hello(f)) {
                   1260:                        aproc_del(f->pipe.file.rproc);
                   1261:                        return 0;
                   1262:                }
                   1263:                AMSG_INIT(m);
                   1264:                m->cmd = AMSG_ACK;
                   1265:                f->rstate = SOCK_RRET;
                   1266:                f->rtodo = sizeof(struct amsg);
1.1       ratchov  1267:                break;
1.28      ratchov  1268:        case AMSG_BYE:
1.37      ratchov  1269: #ifdef DEBUG
                   1270:                if (debug_level >= 3) {
                   1271:                        sock_dbg(f);
                   1272:                        dbg_puts(": BYE message\n");
                   1273:                }
                   1274: #endif
1.29      ratchov  1275:                if (f->pstate != SOCK_INIT) {
1.37      ratchov  1276: #ifdef DEBUG
                   1277:                        if (debug_level >= 1) {
                   1278:                                sock_dbg(f);
                   1279:                                dbg_puts(": BYE, bad state\n");
                   1280:                        }
                   1281: #endif
1.29      ratchov  1282:                }
1.28      ratchov  1283:                aproc_del(f->pipe.file.rproc);
                   1284:                return 0;
1.1       ratchov  1285:        default:
1.37      ratchov  1286: #ifdef DEBUG
                   1287:                if (debug_level >= 1) {
                   1288:                        sock_dbg(f);
                   1289:                        dbg_puts(": unknown command in message\n");
                   1290:                }
                   1291: #endif
1.1       ratchov  1292:                aproc_del(f->pipe.file.rproc);
                   1293:                return 0;
                   1294:        }
                   1295:        if (f->rstate == SOCK_RRET) {
                   1296:                if (f->wstate != SOCK_WIDLE ||
                   1297:                    !sock_wmsg(f, &f->rmsg, &f->rtodo))
                   1298:                        return 0;
1.37      ratchov  1299: #ifdef DEBUG
                   1300:                if (debug_level >= 3) {
                   1301:                        sock_dbg(f);
                   1302:                        dbg_puts(": RRET done\n");
                   1303:                }
                   1304: #endif
1.19      ratchov  1305:                if (f->pstate == SOCK_MIDI && (f->mode & AMSG_MIDIOUT)) {
                   1306:                        f->rstate = SOCK_RDATA;
                   1307:                        f->rtodo = 0;
                   1308:                } else {
                   1309:                        f->rstate = SOCK_RMSG;
                   1310:                        f->rtodo = sizeof(struct amsg);
                   1311:                }
1.1       ratchov  1312:        }
                   1313:        return 1;
                   1314: }
                   1315:
                   1316: /*
1.20      ratchov  1317:  * Create a new data/pos message.
1.1       ratchov  1318:  */
                   1319: int
                   1320: sock_buildmsg(struct sock *f)
                   1321: {
                   1322:        struct aproc *p;
                   1323:        struct abuf *ibuf;
1.41    ! ratchov  1324:        unsigned size;
1.12      ratchov  1325:
1.19      ratchov  1326:        if (f->pstate == SOCK_MIDI) {
1.37      ratchov  1327: #ifdef DEBUG
                   1328:                if (debug_level >= 3) {
                   1329:                        sock_dbg(f);
                   1330:                        dbg_puts(": switching to MIDI mode\n");
                   1331:                }
                   1332: #endif
1.19      ratchov  1333:                f->wstate = SOCK_WDATA;
                   1334:                f->wtodo = 0;
                   1335:                return 1;
                   1336:        }
                   1337:
1.1       ratchov  1338:        /*
1.20      ratchov  1339:         * If pos changed, build a MOVE message.
1.1       ratchov  1340:         */
1.41    ! ratchov  1341:        if (f->tickpending) {
1.37      ratchov  1342: #ifdef DEBUG
                   1343:                if (debug_level >= 4) {
                   1344:                        sock_dbg(f);
                   1345:                        dbg_puts(": building POS message, delta = ");
                   1346:                        dbg_puti(f->delta);
                   1347:                        dbg_puts("\n");
                   1348:                }
                   1349: #endif
1.1       ratchov  1350:                AMSG_INIT(&f->wmsg);
                   1351:                f->wmsg.cmd = AMSG_MOVE;
1.14      ratchov  1352:                f->wmsg.u.ts.delta = f->delta;
1.1       ratchov  1353:                f->wtodo = sizeof(struct amsg);
                   1354:                f->wstate = SOCK_WMSG;
1.14      ratchov  1355:                f->delta = 0;
                   1356:                f->tickpending = 0;
1.25      ratchov  1357:                return 1;
                   1358:        }
                   1359:
                   1360:        /*
                   1361:         * if volume changed build a SETVOL message
                   1362:         */
1.27      ratchov  1363:        if (f->pstate >= SOCK_START && f->vol != f->lastvol) {
1.37      ratchov  1364: #ifdef DEBUG
                   1365:                if (debug_level >= 4) {
                   1366:                        sock_dbg(f);
                   1367:                        dbg_puts(": building SETVOL message, vol = ");
                   1368:                        dbg_puti(f->vol);
                   1369:                        dbg_puts("\n");
                   1370:                }
                   1371: #endif
1.25      ratchov  1372:                AMSG_INIT(&f->wmsg);
                   1373:                f->wmsg.cmd = AMSG_SETVOL;
                   1374:                f->wmsg.u.vol.ctl = f->vol;
                   1375:                f->wtodo = sizeof(struct amsg);
                   1376:                f->wstate = SOCK_WMSG;
                   1377:                f->lastvol = f->vol;
1.1       ratchov  1378:                return 1;
                   1379:        }
                   1380:
                   1381:        /*
1.20      ratchov  1382:         * If data available, build a DATA message.
1.1       ratchov  1383:         */
                   1384:        p = f->pipe.file.wproc;
                   1385:        ibuf = LIST_FIRST(&p->ibuflist);
                   1386:        if (ibuf && ABUF_ROK(ibuf)) {
1.41    ! ratchov  1387:                size = ibuf->used - (ibuf->used % ibuf->bpf);
        !          1388:                if (size > AMSG_DATAMAX)
        !          1389:                        size = AMSG_DATAMAX - (AMSG_DATAMAX % ibuf->bpf);
1.39      ratchov  1390:                if (size > f->walign)
                   1391:                        size = f->walign;
                   1392:                f->walign -= size;
                   1393:                if (f->walign == 0)
1.41    ! ratchov  1394:                        f->walign = dev_round * ibuf->bpf;
1.1       ratchov  1395:                AMSG_INIT(&f->wmsg);
                   1396:                f->wmsg.cmd = AMSG_DATA;
1.41    ! ratchov  1397:                f->wmsg.u.data.size = size;
1.1       ratchov  1398:                f->wtodo = sizeof(struct amsg);
                   1399:                f->wstate = SOCK_WMSG;
                   1400:                return 1;
                   1401:        }
1.37      ratchov  1402: #ifdef DEBUG
                   1403:        if (debug_level >= 4) {
                   1404:                sock_dbg(f);
                   1405:                dbg_puts(": no messages to build anymore, idling...\n");
                   1406:        }
                   1407: #endif
1.1       ratchov  1408:        f->wstate = SOCK_WIDLE;
                   1409:        return 0;
                   1410: }
                   1411:
                   1412: /*
1.20      ratchov  1413:  * Read from the socket file descriptor, fill input buffer and update
1.1       ratchov  1414:  * the state. Return 1 if at least one message or 1 data byte was
                   1415:  * processed, 0 if something blocked.
                   1416:  */
                   1417: int
                   1418: sock_read(struct sock *f)
                   1419: {
1.37      ratchov  1420: #ifdef DEBUG
                   1421:        if (debug_level >= 4) {
                   1422:                sock_dbg(f);
1.39      ratchov  1423:                dbg_puts(": reading ");
1.37      ratchov  1424:                dbg_putu(f->rtodo);
1.39      ratchov  1425:                dbg_puts(" todo\n");
1.37      ratchov  1426:        }
                   1427: #endif
1.1       ratchov  1428:        switch (f->rstate) {
                   1429:        case SOCK_RMSG:
                   1430:                if (!sock_rmsg(f))
                   1431:                        return 0;
                   1432:                if (!sock_execmsg(f))
                   1433:                        return 0;
                   1434:                break;
                   1435:        case SOCK_RDATA:
                   1436:                if (!sock_rdata(f))
                   1437:                        return 0;
1.19      ratchov  1438:                if (f->pstate != SOCK_MIDI && f->rtodo == 0) {
1.1       ratchov  1439:                        f->rstate = SOCK_RMSG;
                   1440:                        f->rtodo = sizeof(struct amsg);
                   1441:                }
1.35      ratchov  1442:                /*
1.41    ! ratchov  1443:                 * XXX: have to way that the buffer is full before starting
1.35      ratchov  1444:                 */
1.41    ! ratchov  1445:                if (f->pstate == SOCK_START && ctl_slotstart(dev_midi, f->slot))
1.1       ratchov  1446:                        (void)sock_attach(f, 0);
                   1447:                break;
                   1448:        case SOCK_RRET:
1.37      ratchov  1449: #ifdef DEBUG
                   1450:                if (debug_level >= 4) {
                   1451:                        sock_dbg(f);
                   1452:                        dbg_puts(": blocked by pending RRET message\n");
                   1453:                }
                   1454: #endif
1.1       ratchov  1455:                return 0;
                   1456:        }
                   1457:        return 1;
                   1458: }
                   1459:
                   1460: /*
1.20      ratchov  1461:  * Process messages to return.
1.1       ratchov  1462:  */
                   1463: int
                   1464: sock_return(struct sock *f)
                   1465: {
                   1466:        struct aproc *rp;
                   1467:
                   1468:        while (f->rstate == SOCK_RRET) {
                   1469:                if (!sock_wmsg(f, &f->rmsg, &f->rtodo))
                   1470:                        return 0;
1.37      ratchov  1471: #ifdef DEBUG
                   1472:                if (debug_level >= 4) {
                   1473:                        sock_dbg(f);
                   1474:                        dbg_puts(": sent RRET message\n");
                   1475:                }
                   1476: #endif
1.19      ratchov  1477:                if (f->pstate == SOCK_MIDI && (f->mode & AMSG_MIDIOUT)) {
                   1478:                        f->rstate = SOCK_RDATA;
                   1479:                        f->rtodo = 0;
                   1480:                } else {
                   1481:                        f->rstate = SOCK_RMSG;
                   1482:                        f->rtodo = sizeof(struct amsg);
                   1483:                }
                   1484:                if (f->pipe.file.state & FILE_RINUSE)
                   1485:                        break;
                   1486:                f->pipe.file.state |= FILE_RINUSE;
1.1       ratchov  1487:                for (;;) {
                   1488:                        /*
                   1489:                         * in() may trigger rsock_done and destroy the
1.20      ratchov  1490:                         * wsock.
1.1       ratchov  1491:                         */
                   1492:                        rp = f->pipe.file.rproc;
                   1493:                        if (!rp || !rp->ops->in(rp, NULL))
                   1494:                                break;
                   1495:                }
1.19      ratchov  1496:                f->pipe.file.state &= ~FILE_RINUSE;
1.1       ratchov  1497:                if (f->pipe.file.wproc == NULL)
                   1498:                        return 0;
                   1499:        }
                   1500:        return 1;
                   1501: }
                   1502:
                   1503: /*
1.20      ratchov  1504:  * Write messages and data on the socket file descriptor. Return 1 if
1.1       ratchov  1505:  * at least one message or one data byte was processed, 0 if something
                   1506:  * blocked.
                   1507:  */
                   1508: int
                   1509: sock_write(struct sock *f)
                   1510: {
1.37      ratchov  1511: #ifdef DEBUG
                   1512:        if (debug_level >= 4) {
                   1513:                sock_dbg(f);
1.39      ratchov  1514:                dbg_puts(": writing ");
1.37      ratchov  1515:                dbg_putu(f->wtodo);
1.39      ratchov  1516:                dbg_puts(" todo\n");
1.37      ratchov  1517:        }
                   1518: #endif
1.1       ratchov  1519:        switch (f->wstate) {
                   1520:        case SOCK_WMSG:
                   1521:                if (!sock_wmsg(f, &f->wmsg, &f->wtodo))
                   1522:                        return 0;
                   1523:                if (f->wmsg.cmd != AMSG_DATA) {
                   1524:                        f->wstate = SOCK_WIDLE;
                   1525:                        f->wtodo = 0xdeadbeef;
                   1526:                        break;
                   1527:                }
                   1528:                f->wstate = SOCK_WDATA;
1.41    ! ratchov  1529:                f->wtodo = f->wmsg.u.data.size;
1.1       ratchov  1530:                /* PASSTHROUGH */
                   1531:        case SOCK_WDATA:
                   1532:                if (!sock_wdata(f))
                   1533:                        return 0;
1.19      ratchov  1534:                if (f->pstate == SOCK_MIDI || f->wtodo > 0)
1.1       ratchov  1535:                        break;
                   1536:                f->wstate = SOCK_WIDLE;
                   1537:                f->wtodo = 0xdeadbeef;
                   1538:                /* PASSTHROUGH */
                   1539:        case SOCK_WIDLE:
                   1540:                if (!sock_return(f))
                   1541:                        return 0;
                   1542:                if (!sock_buildmsg(f))
                   1543:                        return 0;
                   1544:                break;
1.37      ratchov  1545: #ifdef DEBUG
                   1546:        default:
                   1547:                sock_dbg(f);
                   1548:                dbg_puts(": bad writing end state\n");
                   1549:                dbg_panic();
                   1550: #endif
1.1       ratchov  1551:        }
                   1552:        return 1;
                   1553: }