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

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