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

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