Make slot_{attach,detach}() the opposite of each other
authorratchov <ratchov@openbsd.org>
Thu, 28 Jan 2021 11:06:07 +0000 (11:06 +0000)
committerratchov <ratchov@openbsd.org>
Thu, 28 Jan 2021 11:06:07 +0000 (11:06 +0000)
No bahavior change. Now, slot_attach() moves slot's clock forward and
puts the slot on device list; slot_detach() does the opposite: remove
from device list and move clock backwards. This will allow to detach a
client and attach it later in exactly the same state.

usr.bin/sndiod/dev.c

index 299a959..2f425da 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dev.c,v 1.78 2021/01/28 11:02:28 ratchov Exp $        */
+/*     $OpenBSD: dev.c,v 1.79 2021/01/28 11:06:07 ratchov Exp $        */
 /*
  * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
  *
@@ -1575,6 +1575,7 @@ dev_sync_attach(struct dev *d)
                if (!s->ops || !s->opt->mmc)
                        continue;
                slot_attach(s);
+               s->pstate = SLOT_RUN;
        }
        d->tstate = MMC_RUN;
        dev_midi_full(d);
@@ -2000,34 +2001,34 @@ slot_attach(struct slot *s)
 {
        struct dev *d = s->dev;
        long long pos;
-       int startpos;
 
        /*
         * start the device if not started
         */
        dev_wakeup(d);
 
-       /*
-        * get the current position, the origin is when the first sample
-        * played and/or recorded
-        */
-       startpos = dev_getpos(d) * (int)s->round / (int)d->round;
-
        /*
         * adjust initial clock
         */
-       pos = (long long)d->delta * s->round;
-       s->delta = startpos + pos / (int)d->round;
+       pos = s->delta_rem +
+           (long long)s->delta * d->round +
+           (long long)d->delta * s->round;
+       s->delta = pos / (int)d->round;
        s->delta_rem = pos % d->round;
+       if (s->delta_rem < 0) {
+               s->delta_rem += d->round;
+               s->delta--;
+       }
 
-       s->pstate = SLOT_RUN;
 #ifdef DEBUG
        if (log_level >= 2) {
                slot_log(s);
                log_puts(": attached at ");
-               log_puti(startpos);
-               log_puts(", delta = ");
-               log_puti(d->delta);
+               log_puti(s->delta);
+               log_puts(" + ");
+               log_puti(s->delta_rem);
+               log_puts("/");
+               log_puti(s->round);
                log_puts("\n");
        }
 #endif
@@ -2065,9 +2066,10 @@ slot_ready(struct slot *s)
         */
        if (s->dev->pstate == DEV_CFG)
                return;
-       if (!s->opt->mmc)
+       if (!s->opt->mmc) {
                slot_attach(s);
-       else
+               s->pstate = SLOT_RUN;
+       } else
                dev_sync_attach(s->dev);
 }
 
@@ -2115,6 +2117,13 @@ slot_start(struct slot *s)
        }
        s->skip = 0;
 
+       /*
+        * get the current position, the origin is when the first sample
+        * played and/or recorded
+        */
+       s->delta = dev_getpos(s->dev) * (int)s->round / (int)s->dev->round;
+       s->delta_rem = 0;
+
        if (s->mode & MODE_PLAY) {
                s->pstate = SLOT_START;
        } else {
@@ -2130,6 +2139,8 @@ void
 slot_detach(struct slot *s)
 {
        struct slot **ps;
+       struct dev *d;
+       long long pos;
 
 #ifdef DEBUG
        if (log_level >= 3) {
@@ -2147,6 +2158,35 @@ slot_detach(struct slot *s)
 #endif
        }
        *ps = s->next;
+
+       d = s->dev;
+
+       /*
+        * adjust clock, go back d->delta ticks so that slot_attach()
+        * could be called with the resulting state
+        */
+       pos = s->delta_rem +
+           (long long)s->delta * d->round -
+           (long long)d->delta * s->round;
+       s->delta = pos / (int)d->round;
+       s->delta_rem = pos % d->round;
+       if (s->delta_rem < 0) {
+               s->delta_rem += d->round;
+               s->delta--;
+       }
+
+#ifdef DEBUG
+       if (log_level >= 2) {
+               slot_log(s);
+               log_puts(": detached at ");
+               log_puti(s->delta);
+               log_puts(" + ");
+               log_puti(s->delta_rem);
+               log_puts("/");
+               log_puti(d->round);
+               log_puts("\n");
+       }
+#endif
        if (s->mode & MODE_PLAY)
                dev_mix_adjvol(s->dev);
 }