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

Diff for /src/usr.bin/aucat/Attic/aproc.c between version 1.11 and 1.12

version 1.11, 2008/08/20 14:22:50 version 1.12, 2008/10/26 08:49:43
Line 39 
Line 39 
  *   *
  *      (hard) add a lowpass filter for the resampler. Quality is   *      (hard) add a lowpass filter for the resampler. Quality is
  *      not acceptable as is.   *      not acceptable as is.
    *
  */   */
 #include <err.h>  #include <err.h>
 #include <limits.h>  #include <limits.h>
Line 70 
Line 71 
 void  void
 aproc_del(struct aproc *p)  aproc_del(struct aproc *p)
 {  {
           struct abuf *i;
   
           DPRINTF("aproc_del: %s(%s): terminating...\n", p->ops->name, p->name);
   
         if (p->ops->done)          if (p->ops->done)
                 p->ops->done(p);                  p->ops->done(p);
         DPRINTF("aproc_del: %s: %s: deleted\n", p->ops->name, p->name);  
           while (!LIST_EMPTY(&p->ibuflist)) {
                   i = LIST_FIRST(&p->ibuflist);
                   abuf_hup(i);
           }
           while (!LIST_EMPTY(&p->obuflist)) {
                   i = LIST_FIRST(&p->obuflist);
                   abuf_eof(i);
           }
           DPRINTF("aproc_del: %s(%s): freed\n", p->ops->name, p->name);
         free(p);          free(p);
 }  }
   
Line 94 
Line 108 
                 p->ops->newout(p, obuf);                  p->ops->newout(p, obuf);
 }  }
   
   void
   aproc_ipos(struct aproc *p, struct abuf *ibuf, int delta)
   {
           struct abuf *obuf;
   
           DPRINTFN(3, "aproc_ipos: %s: delta = %d\n", p->name, delta);
   
           LIST_FOREACH(obuf, &p->obuflist, oent) {
                   abuf_ipos(obuf, delta);
           }
   }
   
   void
   aproc_opos(struct aproc *p, struct abuf *obuf, int delta)
   {
           struct abuf *ibuf;
   
           DPRINTFN(3, "aproc_opos: %s: delta = %d\n", p->name, delta);
   
           LIST_FOREACH(ibuf, &p->ibuflist, ient) {
                   abuf_opos(ibuf, delta);
           }
   }
   
 int  int
 rpipe_in(struct aproc *p, struct abuf *ibuf_dummy)  rpipe_in(struct aproc *p, struct abuf *ibuf_dummy)
 {  {
Line 104 
Line 142 
   
         DPRINTFN(3, "rpipe_in: %s\n", p->name);          DPRINTFN(3, "rpipe_in: %s\n", p->name);
   
         if (ABUF_FULL(obuf))          if (ABUF_FULL(obuf) || !(f->state & FILE_ROK))
                 return 0;                  return 0;
         data = abuf_wgetblk(obuf, &count, 0);          data = abuf_wgetblk(obuf, &count, 0);
         count = file_read(f, data, count);          count = file_read(f, data, count);
           if (count == 0)
                   return 0;
         abuf_wcommit(obuf, count);          abuf_wcommit(obuf, count);
         abuf_flush(obuf);          if (!abuf_flush(obuf))
         return !ABUF_FULL(obuf);                  return 0;
           return 1;
 }  }
   
 int  int
Line 120 
Line 161 
         unsigned char *data;          unsigned char *data;
         unsigned count;          unsigned count;
   
           if (f->refs > 0)
                   return 0;
         DPRINTFN(3, "rpipe_out: %s\n", p->name);          DPRINTFN(3, "rpipe_out: %s\n", p->name);
   
         if (!(f->state & FILE_ROK))          if (ABUF_FULL(obuf) || !(f->state & FILE_ROK))
                 return 0;                  return 0;
         data = abuf_wgetblk(obuf, &count, 0);          data = abuf_wgetblk(obuf, &count, 0);
         count = file_read(f, data, count);          count = file_read(f, data, count);
           if (count == 0)
                   return 0;
         abuf_wcommit(obuf, count);          abuf_wcommit(obuf, count);
         return f->state & FILE_ROK;          return 1;
 }  }
   
 void  void
Line 136 
Line 181 
         struct file *f = p->u.io.file;          struct file *f = p->u.io.file;
   
         f->rproc = NULL;          f->rproc = NULL;
         f->events &= ~POLLIN;          if (f->wproc == NULL)
                   file_del(f);
 }  }
   
 void  void
 rpipe_eof(struct aproc *p, struct abuf *ibuf_dummy)  rpipe_eof(struct aproc *p, struct abuf *ibuf_dummy)
 {  {
         DPRINTFN(3, "rpipe_eof: %s\n", p->name);          DPRINTFN(3, "rpipe_eof: %s\n", p->name);
         abuf_eof(LIST_FIRST(&p->obuflist));  
         aproc_del(p);          aproc_del(p);
 }  }
   
Line 155 
Line 200 
 }  }
   
 struct aproc_ops rpipe_ops = {  struct aproc_ops rpipe_ops = {
         "rpipe", rpipe_in, rpipe_out, rpipe_eof, rpipe_hup, NULL, NULL, rpipe_done          "rpipe",
           rpipe_in,
           rpipe_out,
           rpipe_eof,
           rpipe_hup,
           NULL, /* newin */
           NULL, /* newout */
           aproc_ipos,
           aproc_opos,
           rpipe_done
 };  };
   
 struct aproc *  struct aproc *
Line 165 
Line 219 
   
         p = aproc_new(&rpipe_ops, f->name);          p = aproc_new(&rpipe_ops, f->name);
         p->u.io.file = f;          p->u.io.file = f;
         f->rproc = p;          f->rproc = p;
         f->events |= POLLIN;  
         return p;          return p;
 }  }
   
Line 176 
Line 229 
         struct file *f = p->u.io.file;          struct file *f = p->u.io.file;
   
         f->wproc = NULL;          f->wproc = NULL;
         f->events &= ~POLLOUT;          if (f->rproc == NULL)
                   file_del(f);
 }  }
   
 int  int
Line 186 
Line 240 
         unsigned char *data;          unsigned char *data;
         unsigned count;          unsigned count;
   
           if (f->refs > 0)
                   return 0;
         DPRINTFN(3, "wpipe_in: %s\n", p->name);          DPRINTFN(3, "wpipe_in: %s\n", p->name);
   
         if (!(f->state & FILE_WOK))          if (ABUF_EMPTY(ibuf) || !(f->state & FILE_WOK))
                 return 0;                  return 0;
   
         data = abuf_rgetblk(ibuf, &count, 0);          data = abuf_rgetblk(ibuf, &count, 0);
         count = file_write(f, data, count);          count = file_write(f, data, count);
           if (count == 0)
                   return 0;
         abuf_rdiscard(ibuf, count);          abuf_rdiscard(ibuf, count);
         return f->state & FILE_WOK;          return 1;
 }  }
   
 int  int
Line 207 
Line 264 
   
         DPRINTFN(3, "wpipe_out: %s\n", p->name);          DPRINTFN(3, "wpipe_out: %s\n", p->name);
   
         if (ABUF_EMPTY(ibuf))          if (!abuf_fill(ibuf)) {
                   DPRINTFN(3, "wpipe_out: fill failed\n");
                 return 0;                  return 0;
           }
           if (ABUF_EMPTY(ibuf) || !(f->state & FILE_WOK))
                   return 0;
         data = abuf_rgetblk(ibuf, &count, 0);          data = abuf_rgetblk(ibuf, &count, 0);
         count = file_write(f, data, count);          if (count == 0) {
         abuf_rdiscard(ibuf, count);                  DPRINTF("wpipe_out: %s: underrun\n", p->name);
         if (ABUF_EOF(ibuf)) {  
                 abuf_hup(ibuf);  
                 aproc_del(p);  
                 return 0;                  return 0;
         }          }
         abuf_fill(ibuf);          count = file_write(f, data, count);
           if (count == 0)
                   return 0;
           abuf_rdiscard(ibuf, count);
         return 1;          return 1;
 }  }
   
Line 232 
Line 293 
 wpipe_hup(struct aproc *p, struct abuf *obuf_dummy)  wpipe_hup(struct aproc *p, struct abuf *obuf_dummy)
 {  {
         DPRINTFN(3, "wpipe_hup: %s\n", p->name);          DPRINTFN(3, "wpipe_hup: %s\n", p->name);
         abuf_hup(LIST_FIRST(&p->ibuflist));  
         aproc_del(p);          aproc_del(p);
 }  }
   
 struct aproc_ops wpipe_ops = {  struct aproc_ops wpipe_ops = {
         "wpipe", wpipe_in, wpipe_out, wpipe_eof, wpipe_hup, NULL, NULL, wpipe_done          "wpipe",
           wpipe_in,
           wpipe_out,
           wpipe_eof,
           wpipe_hup,
           NULL, /* newin */
           NULL, /* newout */
           aproc_ipos,
           aproc_opos,
           wpipe_done
 };  };
   
 struct aproc *  struct aproc *
Line 248 
Line 317 
         p = aproc_new(&wpipe_ops, f->name);          p = aproc_new(&wpipe_ops, f->name);
         p->u.io.file = f;          p->u.io.file = f;
         f->wproc = p;          f->wproc = p;
         f->events |= POLLOUT;  
         return p;          return p;
 }  }
   
Line 265 
Line 333 
         DPRINTFN(4, "mix_bzero: used = %u, todo = %u\n",          DPRINTFN(4, "mix_bzero: used = %u, todo = %u\n",
             obuf->used, obuf->mixtodo);              obuf->used, obuf->mixtodo);
         odata = (short *)abuf_wgetblk(obuf, &ocount, obuf->mixtodo);          odata = (short *)abuf_wgetblk(obuf, &ocount, obuf->mixtodo);
           ocount -= ocount % obuf->bpf;
         if (ocount == 0)          if (ocount == 0)
                 return;                  return;
         memset(odata, 0, ocount);          memset(odata, 0, ocount);
Line 286 
Line 355 
             obuf->mixtodo, ibuf->mixdone);              obuf->mixtodo, ibuf->mixdone);
   
         idata = (short *)abuf_rgetblk(ibuf, &icount, 0);          idata = (short *)abuf_rgetblk(ibuf, &icount, 0);
           icount -= icount % ibuf->bpf;
         if (icount == 0)          if (icount == 0)
                 return;                  return;
   
         odata = (short *)abuf_wgetblk(obuf, &ocount, ibuf->mixdone);          odata = (short *)abuf_wgetblk(obuf, &ocount, ibuf->mixdone);
           ocount -= ocount % obuf->bpf;
         if (ocount == 0)          if (ocount == 0)
                 return;                  return;
   
Line 306 
Line 377 
             scount, ibuf->mixdone, obuf->mixtodo);              scount, ibuf->mixdone, obuf->mixtodo);
 }  }
   
 /*  
  * Remove an input stream from the mixer.  
  */  
 void  
 mix_rm(struct aproc *p, struct abuf *ibuf)  
 {  
         LIST_REMOVE(ibuf, ient);  
         DPRINTF("mix_rm: %s\n", p->name);  
 }  
   
 int  int
 mix_in(struct aproc *p, struct abuf *ibuf)  mix_in(struct aproc *p, struct abuf *ibuf)
 {  {
Line 325 
Line 386 
         DPRINTFN(4, "mix_in: used = %u, done = %u, todo = %u\n",          DPRINTFN(4, "mix_in: used = %u, done = %u, todo = %u\n",
             ibuf->used, ibuf->mixdone, obuf->mixtodo);              ibuf->used, ibuf->mixdone, obuf->mixtodo);
   
         if (ibuf->mixdone >= obuf->mixtodo)          if (!ABUF_ROK(ibuf) || ibuf->mixdone == obuf->mixtodo)
                 return 0;                  return 0;
   
         mix_badd(ibuf, obuf);          mix_badd(ibuf, obuf);
         ocount = obuf->mixtodo;          ocount = obuf->mixtodo;
         LIST_FOREACH(i, &p->ibuflist, ient) {          LIST_FOREACH(i, &p->ibuflist, ient) {
Line 337 
Line 399 
                 return 0;                  return 0;
   
         abuf_wcommit(obuf, ocount);          abuf_wcommit(obuf, ocount);
           p->u.mix.lat += ocount / obuf->bpf;
         obuf->mixtodo -= ocount;          obuf->mixtodo -= ocount;
         abuf_flush(obuf);          if (!abuf_flush(obuf))
                   return 0; /* hup */
         mix_bzero(p);          mix_bzero(p);
         for (i = LIST_FIRST(&p->ibuflist); i != LIST_END(&p->ibuflist); i = inext) {          for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) {
                 inext = LIST_NEXT(i, ient);                  inext = LIST_NEXT(i, ient);
                 i->mixdone -= ocount;                  i->mixdone -= ocount;
                 if (i != ibuf && i->mixdone < obuf->mixtodo) {                  if (i->mixdone < obuf->mixtodo)
                         if (ABUF_EOF(i)) {  
                                 mix_rm(p, i);  
                                 abuf_hup(i);  
                                 continue;  
                         }  
                         mix_badd(i, obuf);                          mix_badd(i, obuf);
                         abuf_fill(i);                  if (!abuf_fill(i))
                 }                          continue;
         }          }
         return 1;          return 1;
 }  }
Line 365 
Line 424 
         DPRINTFN(4, "mix_out: used = %u, todo = %u\n",          DPRINTFN(4, "mix_out: used = %u, todo = %u\n",
             obuf->used, obuf->mixtodo);              obuf->used, obuf->mixtodo);
   
           if (!ABUF_WOK(obuf))
                   return 0;
   
         mix_bzero(p);          mix_bzero(p);
         ocount = obuf->mixtodo;          ocount = obuf->mixtodo;
         for (i = LIST_FIRST(&p->ibuflist); i != LIST_END(&p->ibuflist); i = inext) {          for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) {
                 inext = LIST_NEXT(i, ient);                  inext = LIST_NEXT(i, ient);
                   if (!abuf_fill(i))
                           continue;
                 if (!ABUF_ROK(i)) {                  if (!ABUF_ROK(i)) {
                         if ((p->u.mix.flags & MIX_DROP) && i->mixdone == 0) {                          if ((p->u.mix.flags & MIX_DROP) && i->mixdone == 0) {
                                 if (i->xrun == XRUN_ERROR) {                                  if (i->xrun == XRUN_ERROR) {
                                         mix_rm(p, i);  
                                         abuf_hup(i);                                          abuf_hup(i);
                                         continue;                                          continue;
                                 }                                  }
Line 380 
Line 443 
                                 i->mixdone += drop;                                  i->mixdone += drop;
                                 if (i->xrun == XRUN_SYNC)                                  if (i->xrun == XRUN_SYNC)
                                         i->drop += drop;                                          i->drop += drop;
                                   else {
                                           abuf_opos(i, -(int)(drop / i->bpf));
                                           if (i->duplex) {
                                                   DPRINTF("mix_out: duplex %u\n",
                                                       drop);
                                                   i->duplex->drop += drop *
                                                       i->duplex->bpf / i->bpf;
                                                   abuf_ipos(i->duplex,
                                                       -(int)(drop / i->bpf));
                                           }
                                   }
                                 DPRINTF("mix_out: drop = %u\n", i->drop);                                  DPRINTF("mix_out: drop = %u\n", i->drop);
                         }                          }
                 } else                  } else
                         mix_badd(i, obuf);                          mix_badd(i, obuf);
                 if (ocount > i->mixdone)                  if (ocount > i->mixdone)
                         ocount = i->mixdone;                          ocount = i->mixdone;
                 if (ABUF_EOF(i)) {  
                         mix_rm(p, i);  
                         abuf_hup(i);  
                         continue;  
                 }  
                 abuf_fill(i);  
         }          }
         if (ocount == 0)          if (ocount == 0)
                 return 0;                  return 0;
         if (LIST_EMPTY(&p->ibuflist) && (p->u.mix.flags & MIX_AUTOQUIT)) {          if (LIST_EMPTY(&p->ibuflist) && (p->u.mix.flags & MIX_AUTOQUIT)) {
                 DPRINTF("mix_out: nothing more to do...\n");                  DPRINTF("mix_out: nothing more to do...\n");
                 obuf->wproc = NULL;  
                 aproc_del(p);                  aproc_del(p);
                 return 0;                  return 0;
         }          }
         abuf_wcommit(obuf, ocount);          abuf_wcommit(obuf, ocount);
           p->u.mix.lat += ocount / obuf->bpf;
         obuf->mixtodo -= ocount;          obuf->mixtodo -= ocount;
         LIST_FOREACH(i, &p->ibuflist, ient) {          LIST_FOREACH(i, &p->ibuflist, ient) {
                 i->mixdone -= ocount;                  i->mixdone -= ocount;
Line 415 
Line 483 
         struct abuf *obuf = LIST_FIRST(&p->obuflist);          struct abuf *obuf = LIST_FIRST(&p->obuflist);
   
         DPRINTF("mix_eof: %s: detached\n", p->name);          DPRINTF("mix_eof: %s: detached\n", p->name);
         mix_rm(p, ibuf);          mix_setmaster(p);
   
         /*          /*
          * If there's no more inputs, abuf_run() will trigger the eof           * If there's no more inputs, abuf_run() will trigger the eof
          * condition and propagate it, so no need to handle it here.           * condition and propagate it, so no need to handle it here.
Line 431 
Line 500 
   
         while (!LIST_EMPTY(&p->ibuflist)) {          while (!LIST_EMPTY(&p->ibuflist)) {
                 ibuf = LIST_FIRST(&p->ibuflist);                  ibuf = LIST_FIRST(&p->ibuflist);
                 mix_rm(p, ibuf);  
                 abuf_hup(ibuf);                  abuf_hup(ibuf);
         }          }
         DPRINTF("mix_hup: %s: done\n", p->name);          DPRINTF("mix_hup: %s: done\n", p->name);
Line 444 
Line 512 
         ibuf->mixdone = 0;          ibuf->mixdone = 0;
         ibuf->mixvol = ADATA_UNIT;          ibuf->mixvol = ADATA_UNIT;
         ibuf->xrun = XRUN_IGNORE;          ibuf->xrun = XRUN_IGNORE;
           mix_setmaster(p);
 }  }
   
 void  void
Line 453 
Line 522 
         mix_bzero(p);          mix_bzero(p);
 }  }
   
   void
   mix_opos(struct aproc *p, struct abuf *obuf, int delta)
   {
           DPRINTFN(3, "mix_opos: lat = %d/%d\n", p->u.mix.lat, p->u.mix.maxlat);
           p->u.mix.lat -= delta;
           aproc_opos(p, obuf, delta);
   }
   
 struct aproc_ops mix_ops = {  struct aproc_ops mix_ops = {
         "mix", mix_in, mix_out, mix_eof, mix_hup, mix_newin, mix_newout, NULL          "mix",
           mix_in,
           mix_out,
           mix_eof,
           mix_hup,
           mix_newin,
           mix_newout,
           aproc_ipos,
           mix_opos,
           NULL
 };  };
   
 struct aproc *  struct aproc *
 mix_new(void)  mix_new(char *name, int maxlat)
 {  {
         struct aproc *p;          struct aproc *p;
   
         p = aproc_new(&mix_ops, "softmix");          p = aproc_new(&mix_ops, name);
         p->u.mix.flags = 0;          p->u.mix.flags = 0;
           p->u.mix.lat = 0;
           p->u.mix.maxlat = maxlat;
         return p;          return p;
 }  }
   
Line 473 
Line 561 
         struct abuf *obuf = LIST_FIRST(&p->obuflist);          struct abuf *obuf = LIST_FIRST(&p->obuflist);
   
         abuf_wcommit(obuf, obuf->mixtodo);          abuf_wcommit(obuf, obuf->mixtodo);
           p->u.mix.lat += obuf->mixtodo / obuf->bpf;
         obuf->mixtodo = 0;          obuf->mixtodo = 0;
         abuf_run(obuf);          abuf_run(obuf);
         mix_bzero(p);          mix_bzero(p);
Line 504 
Line 593 
         unsigned icount, ocount, scount;          unsigned icount, ocount, scount;
   
         idata = abuf_rgetblk(ibuf, &icount, obuf->subdone);          idata = abuf_rgetblk(ibuf, &icount, obuf->subdone);
           icount -= icount % ibuf->bpf;
         if (icount == 0)          if (icount == 0)
                 return;                  return;
         odata = abuf_wgetblk(obuf, &ocount, 0);          odata = abuf_wgetblk(obuf, &ocount, 0);
           ocount -= icount % obuf->bpf;
         if (ocount == 0)          if (ocount == 0)
                 return;                  return;
         scount = (icount < ocount) ? icount : ocount;          scount = (icount < ocount) ? icount : ocount;
         memcpy(odata, idata, scount);          memcpy(odata, idata, scount);
         abuf_wcommit(obuf, scount);          abuf_wcommit(obuf, scount);
         obuf->subdone += scount;          obuf->subdone += scount;
         DPRINTFN(4, "sub_bcopy: %u bytes\n", scount);          DPRINTFN(4, "sub_bcopy: %u bytes\n", scount);
 }  }
   
 void  
 sub_rm(struct aproc *p, struct abuf *obuf)  
 {  
         LIST_REMOVE(obuf, oent);  
         DPRINTF("sub_rm: %s\n", p->name);  
 }  
   
 int  int
 sub_in(struct aproc *p, struct abuf *ibuf)  sub_in(struct aproc *p, struct abuf *ibuf)
 {  {
         struct abuf *i, *inext;          struct abuf *i, *inext;
         unsigned done, drop;          unsigned done, drop;
         int again;  
           if (!ABUF_ROK(ibuf))
         again = 1;                  return 0;
         done = ibuf->used;          done = ibuf->used;
         for (i = LIST_FIRST(&p->obuflist); i != LIST_END(&p->obuflist); i = inext) {          for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) {
                 inext = LIST_NEXT(i, oent);                  inext = LIST_NEXT(i, oent);
                 if (!ABUF_WOK(i)) {                  if (!ABUF_WOK(i)) {
                         if ((p->u.sub.flags & SUB_DROP) && i->subdone == 0) {                          if ((p->u.sub.flags & SUB_DROP) && i->subdone == 0) {
                                 if (i->xrun == XRUN_ERROR) {                                  if (i->xrun == XRUN_ERROR) {
                                         sub_rm(p, i);  
                                         abuf_eof(i);                                          abuf_eof(i);
                                         continue;                                          continue;
                                 }                                  }
                                 drop = ibuf->used;                                  drop = ibuf->used;
                                 if (i->xrun == XRUN_SYNC)                                  if (i->xrun == XRUN_SYNC)
                                         i->silence += drop;                                          i->silence += drop;
                                   else {
                                           abuf_ipos(i, -(int)(drop / i->bpf));
                                           if (i->duplex) {
                                                   DPRINTF("sub_in: duplex %u\n",
                                                       drop);
                                                   i->duplex->silence += drop *
                                                       i->duplex->bpf / i->bpf;
                                                   abuf_opos(i->duplex,
                                                       -(int)(drop / i->bpf));
                                           }
                                   }
                                 i->subdone += drop;                                  i->subdone += drop;
                                 DPRINTF("sub_in: silence =  %u\n", i->silence);                                  DPRINTF("sub_in: silence = %u\n", i->silence);
                         }                          }
                 } else {                  } else
                         sub_bcopy(ibuf, i);                          sub_bcopy(ibuf, i);
                         abuf_flush(i);  
                 }  
                 if (!ABUF_WOK(i))  
                         again = 0;  
                 if (done > i->subdone)                  if (done > i->subdone)
                         done = i->subdone;                          done = i->subdone;
                   if (!abuf_flush(i))
                           continue;
         }          }
         LIST_FOREACH(i, &p->obuflist, oent) {          LIST_FOREACH(i, &p->obuflist, oent) {
                 i->subdone -= done;                  i->subdone -= done;
         }          }
         abuf_rdiscard(ibuf, done);          abuf_rdiscard(ibuf, done);
         return again;          p->u.sub.lat -= done / ibuf->bpf;
           return 1;
 }  }
   
 int  int
Line 570 
Line 663 
         struct abuf *i, *inext;          struct abuf *i, *inext;
         unsigned done;          unsigned done;
   
         if (obuf->subdone >= ibuf->used)          if (!ABUF_WOK(obuf))
                 return 0;                  return 0;
           if (!abuf_fill(ibuf)) {
                   return 0;
           }
           if (obuf->subdone == ibuf->used)
                   return 0;
   
         sub_bcopy(ibuf, obuf);  
   
         done = ibuf->used;          done = ibuf->used;
         LIST_FOREACH(i, &p->obuflist, oent) {          for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) {
                 if (i != obuf && ABUF_WOK(i)) {                  inext = LIST_NEXT(i, oent);
                         sub_bcopy(ibuf, i);                  if (!abuf_flush(i))
                         abuf_flush(i);                          continue;
                 }                  sub_bcopy(ibuf, i);
                 if (done > i->subdone)                  if (done > i->subdone)
                         done = i->subdone;                          done = i->subdone;
         }          }
         if (done == 0)  
                 return 0;  
         LIST_FOREACH(i, &p->obuflist, oent) {          LIST_FOREACH(i, &p->obuflist, oent) {
                 i->subdone -= done;                  i->subdone -= done;
         }          }
         abuf_rdiscard(ibuf, done);          abuf_rdiscard(ibuf, done);
         if (ABUF_EOF(ibuf)) {          p->u.sub.lat -= done / ibuf->bpf;
                 abuf_hup(ibuf);  
                 for (i = LIST_FIRST(&p->obuflist);  
                      i != LIST_END(&p->obuflist);  
                      i = inext) {  
                         inext = LIST_NEXT(i, oent);  
                         if (i != ibuf)  
                                 abuf_eof(i);  
                 }  
                 ibuf->wproc = NULL;  
                 aproc_del(p);  
                 return 0;  
         }  
         abuf_fill(ibuf);  
         return 1;          return 1;
 }  }
   
Line 614 
Line 695 
   
         while (!LIST_EMPTY(&p->obuflist)) {          while (!LIST_EMPTY(&p->obuflist)) {
                 obuf = LIST_FIRST(&p->obuflist);                  obuf = LIST_FIRST(&p->obuflist);
                 sub_rm(p, obuf);  
                 abuf_eof(obuf);                  abuf_eof(obuf);
         }          }
         aproc_del(p);          aproc_del(p);
Line 626 
Line 706 
         struct abuf *ibuf = LIST_FIRST(&p->ibuflist);          struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
   
         DPRINTF("sub_hup: %s: detached\n", p->name);          DPRINTF("sub_hup: %s: detached\n", p->name);
         sub_rm(p, obuf);          abuf_run(ibuf);
         if (LIST_EMPTY(&p->obuflist) && (p->u.sub.flags & SUB_AUTOQUIT)) {  
                 abuf_hup(ibuf);  
                 aproc_del(p);  
         } else  
                 abuf_run(ibuf);  
         DPRINTF("sub_hup: done\n");          DPRINTF("sub_hup: done\n");
 }  }
   
Line 642 
Line 717 
         obuf->xrun = XRUN_IGNORE;          obuf->xrun = XRUN_IGNORE;
 }  }
   
   void
   sub_ipos(struct aproc *p, struct abuf *ibuf, int delta)
   {
           p->u.sub.lat += delta;
           DPRINTFN(3, "sub_ipos: lat = %d/%d\n", p->u.sub.lat, p->u.sub.maxlat);
           aproc_ipos(p, ibuf, delta);
   }
   
 struct aproc_ops sub_ops = {  struct aproc_ops sub_ops = {
         "sub", sub_in, sub_out, sub_eof, sub_hup, NULL, sub_newout, NULL          "sub",
           sub_in,
           sub_out,
           sub_eof,
           sub_hup,
           NULL,
           sub_newout,
           sub_ipos,
           aproc_opos,
           NULL
 };  };
   
 struct aproc *  struct aproc *
 sub_new(void)  sub_new(char *name, int maxlat)
 {  {
         struct aproc *p;          struct aproc *p;
   
         p = aproc_new(&sub_ops, "copy");          p = aproc_new(&sub_ops, name);
         p->u.sub.flags = 0;          p->u.sub.flags = 0;
           p->u.sub.lat = 0;
           p->u.sub.maxlat = maxlat;
         return p;          return p;
 }  }
   
   
 /*  /*
  * Convert one block.   * Convert one block.
  */   */
Line 695 
Line 788 
          */           */
         idata = abuf_rgetblk(ibuf, &icount, 0);          idata = abuf_rgetblk(ibuf, &icount, 0);
         ifr = icount / ibuf->bpf;          ifr = icount / ibuf->bpf;
           icount = ifr * ibuf->bpf;
   
         odata = abuf_wgetblk(obuf, &ocount, 0);          odata = abuf_wgetblk(obuf, &ocount, 0);
         ofr = ocount / obuf->bpf;          ofr = ocount / obuf->bpf;
           ocount = ofr * obuf->bpf;
   
         /*          /*
          * Partially copy structures into local variables, to avoid           * Partially copy structures into local variables, to avoid
Line 784 
Line 879 
 {  {
         struct abuf *obuf = LIST_FIRST(&p->obuflist);          struct abuf *obuf = LIST_FIRST(&p->obuflist);
   
         if (!ABUF_WOK(obuf))          DPRINTFN(4, "conv_in: %s\n", p->name);
   
           if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
                 return 0;                  return 0;
         conv_bcopy(&p->u.conv.ist, &p->u.conv.ost, ibuf, obuf);          conv_bcopy(&p->u.conv.ist, &p->u.conv.ost, ibuf, obuf);
         abuf_flush(obuf);          if (!abuf_flush(obuf))
         return ABUF_WOK(obuf);                  return 0;
           return 1;
 }  }
   
 int  int
Line 796 
Line 894 
 {  {
         struct abuf *ibuf = LIST_FIRST(&p->ibuflist);          struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
   
         if (!ABUF_ROK(ibuf))          DPRINTFN(4, "conv_out: %s\n", p->name);
   
           if (!abuf_fill(ibuf))
                 return 0;                  return 0;
         conv_bcopy(&p->u.conv.ist, &p->u.conv.ost, ibuf, obuf);          if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
         if (ABUF_EOF(ibuf)) {  
                 obuf->wproc = NULL;  
                 abuf_hup(ibuf);  
                 aproc_del(p);  
                 return 0;                  return 0;
         }          conv_bcopy(&p->u.conv.ist, &p->u.conv.ost, ibuf, obuf);
         abuf_fill(ibuf);  
         return 1;          return 1;
 }  }
   
 void  void
 conv_eof(struct aproc *p, struct abuf *ibuf)  conv_eof(struct aproc *p, struct abuf *ibuf)
 {  {
         abuf_eof(LIST_FIRST(&p->obuflist));          DPRINTFN(4, "conv_eof: %s\n", p->name);
   
         aproc_del(p);          aproc_del(p);
 }  }
   
 void  void
 conv_hup(struct aproc *p, struct abuf *obuf)  conv_hup(struct aproc *p, struct abuf *obuf)
 {  {
         abuf_hup(LIST_FIRST(&p->ibuflist));          DPRINTFN(4, "conv_hup: %s\n", p->name);
   
         aproc_del(p);          aproc_del(p);
 }  }
   
Line 850 
Line 947 
         st->rate = par->rate;          st->rate = par->rate;
         st->pos = 0;          st->pos = 0;
   
         for (i = 0; i < CHAN_MAX; i++)          for (i = 0; i < NCHAN_MAX; i++)
                 st->ctx[i] = 0;                  st->ctx[i] = 0;
 }  }
   
   void
   conv_ipos(struct aproc *p, struct abuf *ibuf, int delta)
   {
           struct abuf *obuf = LIST_FIRST(&p->obuflist);
           long long ipos;
           int ifac, ofac;
   
           DPRINTFN(3, "conv_ipos: %d\n", delta);
   
           ifac = p->u.conv.ist.rate;
           ofac = p->u.conv.ost.rate;
           ipos = p->u.conv.idelta + (long long)delta * ofac;
           delta = (ipos + ifac - 1) / ifac;
           p->u.conv.idelta = ipos - (long long)delta * ifac;
           abuf_ipos(obuf, delta);
   }
   
   void
   conv_opos(struct aproc *p, struct abuf *obuf, int delta)
   {
           struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
           long long opos;
           int ifac, ofac;
   
           DPRINTFN(3, "conv_opos: %d\n", delta);
   
           ifac = p->u.conv.ist.rate;
           ofac = p->u.conv.ost.rate;
           opos = p->u.conv.odelta + (long long)delta * ifac;
           delta = (opos + ofac - 1) / ofac;
           p->u.conv.odelta = opos - (long long)delta * ofac;
           abuf_opos(ibuf, delta);
   }
   
 struct aproc_ops conv_ops = {  struct aproc_ops conv_ops = {
         "conv", conv_in, conv_out, conv_eof, conv_hup, NULL, NULL, NULL          "conv",
           conv_in,
           conv_out,
           conv_eof,
           conv_hup,
           NULL,
           NULL,
           conv_ipos,
           conv_opos,
           NULL
 };  };
   
 struct aproc *  struct aproc *
Line 866 
Line 1006 
         p = aproc_new(&conv_ops, name);          p = aproc_new(&conv_ops, name);
         aconv_init(&p->u.conv.ist, ipar, 1);          aconv_init(&p->u.conv.ist, ipar, 1);
         aconv_init(&p->u.conv.ost, opar, 0);          aconv_init(&p->u.conv.ost, opar, 0);
           p->u.conv.idelta = 0;
           p->u.conv.odelta = 0;
           if (debug_level > 0) {
                   DPRINTF("conv_new: %s: ", p->name);
                   aparams_print2(ipar, opar);
                   DPRINTF("\n");
           }
         return p;          return p;
 }  }

Legend:
Removed from v.1.11  
changed lines
  Added in v.1.12