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

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