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

Diff for /src/usr.bin/aucat/Attic/dev.c between version 1.56 and 1.57

version 1.56, 2010/05/08 15:35:45 version 1.57, 2010/06/04 06:15:28
Line 25 
Line 25 
  *   *
  * From the main loop, the device is used as follows:   * From the main loop, the device is used as follows:
  *   *
  *   1. create the device using dev_init_xxx()   *   1. create the device using dev_new_xxx()
  *   2. call dev_run() in the event loop   *   2. call dev_run() in the event loop
  *   3. destroy the device using dev_done()   *   3. destroy the device using dev_del()
  *   4. continue running the event loop to drain   *   4. continue running the event loop to drain
  *   *
  * The device is used as follows from aproc context:   * The device is used as follows from aproc context:
Line 100 
Line 100 
 #include "dbg.h"  #include "dbg.h"
 #endif  #endif
   
 /*  int  dev_open(struct dev *);
  * state of the device  void dev_close(struct dev *);
  */  void dev_start(struct dev *);
 #define DEV_CLOSED      0               /* closed */  void dev_stop(struct dev *);
 #define DEV_INIT        1               /* stopped */  void dev_clear(struct dev *);
 #define DEV_START       2               /* ready to start */  void dev_prime(struct dev *);
 #define DEV_RUN         3               /* started */  
   
 /*  struct dev *dev_list = NULL;
  * desired parameters  
  */  
 unsigned dev_reqmode;                           /* mode */  
 struct aparams dev_reqipar, dev_reqopar;        /* parameters */  
 unsigned dev_reqbufsz;                          /* buffer size */  
 unsigned dev_reqround;                          /* block size */  
 unsigned dev_reqprime;                          /* prime play buffer? */  
   
 /*  /*
  * actual parameters and runtime state  
  */  
 char *dev_path;                                 /* sio path */  
 unsigned dev_refcnt = 0;                        /* number of openers */  
 unsigned dev_pstate;                            /* on of DEV_xxx */  
 unsigned dev_mode;                              /* bitmap of MODE_xxx */  
 unsigned dev_bufsz, dev_round, dev_rate;  
 struct aparams dev_ipar, dev_opar;  
 struct aproc *dev_mix, *dev_sub, *dev_rec, *dev_play, *dev_submon, *dev_mon;  
 struct aproc *dev_midi;  
   
 void dev_start(void);  
 void dev_stop(void);  
 void dev_clear(void);  
 void dev_prime(void);  
   
 /*  
  * Create a sndio device   * Create a sndio device
  */   */
 void  struct dev *
 dev_init_sio(char *path, unsigned mode,  dev_new_sio(char *path,
     struct aparams *dipar, struct aparams *dopar,      unsigned mode, struct aparams *dipar, struct aparams *dopar,
     unsigned bufsz, unsigned round)      unsigned bufsz, unsigned round, unsigned hold, unsigned prime)
 {  {
         dev_path = path;          struct dev *d;
         dev_reqmode = mode;  
           d = malloc(sizeof(struct dev));
           if (d == NULL) {
                   perror("malloc");
                   exit(1);
           }
           d->path = path;
           d->reqmode = mode;
         if (mode & MODE_PLAY)          if (mode & MODE_PLAY)
                 dev_reqopar = *dopar;                  d->reqopar = *dopar;
         if (mode & MODE_RECMASK)          if (mode & MODE_RECMASK)
                 dev_reqipar = *dipar;                  d->reqipar = *dipar;
         dev_reqbufsz = bufsz;          d->reqbufsz = bufsz;
         dev_reqround = round;          d->reqround = round;
         dev_pstate = DEV_CLOSED;          d->prime = prime;
           d->hold = hold;
           d->pstate = DEV_CLOSED;
           d->next = dev_list;
           dev_list = d;
           if (d->hold && !dev_open(d)) {
                   dev_del(d);
                   return NULL;
           }
           return d;
 }  }
   
 /*  /*
  * Create a loopback synchronous device   * Create a loopback synchronous device
  */   */
 void  struct dev *
 dev_init_loop(struct aparams *dipar, struct aparams *dopar, unsigned bufsz)  dev_new_loop(struct aparams *dipar, struct aparams *dopar, unsigned bufsz)
 {  {
         struct aparams par;          struct aparams par;
         unsigned cmin, cmax, rate;          unsigned cmin, cmax, rate;
           struct dev *d;
   
           d = malloc(sizeof(struct dev));
           if (d == NULL) {
                   perror("malloc");
                   exit(1);
           }
         cmin = (dipar->cmin < dopar->cmin) ? dipar->cmin : dopar->cmin;          cmin = (dipar->cmin < dopar->cmin) ? dipar->cmin : dopar->cmin;
         cmax = (dipar->cmax > dopar->cmax) ? dipar->cmax : dopar->cmax;          cmax = (dipar->cmax > dopar->cmax) ? dipar->cmax : dopar->cmax;
         rate = (dipar->rate > dopar->rate) ? dipar->rate : dopar->rate;          rate = (dipar->rate > dopar->rate) ? dipar->rate : dopar->rate;
         aparams_init(&par, cmin, cmax, rate);          aparams_init(&par, cmin, cmax, rate);
         dev_reqipar = par;          d->reqipar = par;
         dev_reqopar = par;          d->reqopar = par;
         dev_rate = rate;          d->rate = rate;
         dev_reqround = (bufsz + 1) / 2;          d->reqround = (bufsz + 1) / 2;
         dev_reqbufsz = dev_reqround * 2;          d->reqbufsz = d->reqround * 2;
         dev_reqmode = MODE_PLAY | MODE_REC | MODE_LOOP;          d->reqmode = MODE_PLAY | MODE_REC | MODE_LOOP;
         dev_pstate = DEV_CLOSED;          d->pstate = DEV_CLOSED;
           d->hold = 0;
           d->prime = 0;
           d->next = dev_list;
           dev_list = d;
           return d;
 }  }
   
 /*  /*
  * Create a MIDI thru box device   * Create a MIDI thru box device
  */   */
 void  struct dev *
 dev_init_thru(void)  dev_new_thru(void)
 {  {
         dev_reqmode = 0;          struct dev *d;
         dev_pstate = DEV_CLOSED;  
           d = malloc(sizeof(struct dev));
           if (d == NULL) {
                   perror("malloc");
                   exit(1);
           }
           d->reqmode = 0;
           d->pstate = DEV_CLOSED;
           d->hold = 0;
           d->prime = 0;
           d->next = dev_list;
           dev_list = d;
           return d;
 }  }
   
 /*  /*
Line 190 
Line 204 
  * monitor, midi control, and any necessary conversions.   * monitor, midi control, and any necessary conversions.
  */   */
 int  int
 dev_open(void)  dev_open(struct dev *d)
 {  {
         struct file *f;          struct file *f;
         struct aparams par;          struct aparams par;
Line 198 
Line 212 
         struct abuf *buf;          struct abuf *buf;
         unsigned siomode;          unsigned siomode;
   
         dev_mode = dev_reqmode;          d->mode = d->reqmode;
         dev_round = dev_reqround;          d->round = d->reqround;
         dev_bufsz = dev_reqbufsz;          d->bufsz = d->reqbufsz;
         dev_ipar = dev_reqipar;          d->ipar = d->reqipar;
         dev_opar = dev_reqopar;          d->opar = d->reqopar;
         dev_rec = NULL;          d->rec = NULL;
         dev_play = NULL;          d->play = NULL;
         dev_mon = NULL;          d->mon = NULL;
         dev_submon = NULL;          d->submon = NULL;
         dev_rate = 0;          d->rate = 0;
   
         /*          /*
          * If needed, open the device (ie create dev_rec and dev_play)           * If needed, open the device (ie create dev_rec and dev_play)
          */           */
         if ((dev_mode & (MODE_PLAY | MODE_REC)) && !(dev_mode & MODE_LOOP)) {          if ((d->mode & (MODE_PLAY | MODE_REC)) && !(d->mode & MODE_LOOP)) {
                 siomode = dev_mode & (MODE_PLAY | MODE_REC);                  siomode = d->mode & (MODE_PLAY | MODE_REC);
                 f = (struct file *)siofile_new(&siofile_ops,                  f = (struct file *)siofile_new(&siofile_ops,
                     dev_path,                      d->path,
                     &siomode,                      &siomode,
                     &dev_ipar,                      &d->ipar,
                     &dev_opar,                      &d->opar,
                     &dev_bufsz,                      &d->bufsz,
                     &dev_round);                      &d->round);
                 if (f == NULL) {                  if (f == NULL) {
 #ifdef DEBUG  #ifdef DEBUG
                         if (debug_level >= 1) {                          if (debug_level >= 1) {
                                 dbg_puts(dev_path ? dev_path : "default");                                  dbg_puts(d->path ? d->path : "default");
                                 dbg_puts(": failed to open audio device\n");                                  dbg_puts(": failed to open audio device\n");
                         }                          }
 #endif  #endif
                         return 0;                          return 0;
                 }                  }
                 if (!(siomode & MODE_PLAY))                  if (!(siomode & MODE_PLAY))
                         dev_mode &= ~(MODE_PLAY | MODE_MON);                          d->mode &= ~(MODE_PLAY | MODE_MON);
                 if (!(siomode & MODE_REC))                  if (!(siomode & MODE_REC))
                         dev_mode &= ~MODE_REC;                          d->mode &= ~MODE_REC;
                 if ((dev_mode & (MODE_PLAY | MODE_REC)) == 0) {                  if ((d->mode & (MODE_PLAY | MODE_REC)) == 0) {
 #ifdef DEBUG  #ifdef DEBUG
                         if (debug_level >= 1) {                          if (debug_level >= 1) {
                                 dbg_puts(dev_path ? dev_path : "default");                                  dbg_puts(d->path ? d->path : "default");
                                 dbg_puts(": mode not supported by device\n");                                  dbg_puts(": mode not supported by device\n");
                         }                          }
 #endif  #endif
                         return 0;                          return 0;
                 }                  }
                 dev_rate = dev_mode & MODE_REC ? dev_ipar.rate : dev_opar.rate;                  d->rate = d->mode & MODE_REC ? d->ipar.rate : d->opar.rate;
 #ifdef DEBUG  #ifdef DEBUG
                 if (debug_level >= 2) {                  if (debug_level >= 2) {
                         if (dev_mode & MODE_REC) {                          if (d->mode & MODE_REC) {
                                 dbg_puts("hw recording ");                                  dbg_puts("hw recording ");
                                 aparams_dbg(&dev_ipar);                                  aparams_dbg(&d->ipar);
                                 dbg_puts("\n");                                  dbg_puts("\n");
                         }                          }
                         if (dev_mode & MODE_PLAY) {                          if (d->mode & MODE_PLAY) {
                                 dbg_puts("hw playing ");                                  dbg_puts("hw playing ");
                                 aparams_dbg(&dev_opar);                                  aparams_dbg(&d->opar);
                                 dbg_puts("\n");                                  dbg_puts("\n");
                         }                          }
                 }                  }
 #endif  #endif
                 if (dev_mode & MODE_REC) {                  if (d->mode & MODE_REC) {
                         dev_rec = rsio_new(f);                          d->rec = rsio_new(f);
                         dev_rec->refs++;                          d->rec->refs++;
                 }                  }
                 if (dev_mode & MODE_PLAY) {                  if (d->mode & MODE_PLAY) {
                         dev_play = wsio_new(f);                          d->play = wsio_new(f);
                         dev_play->refs++;                          d->play->refs++;
                 }                  }
         }          }
   
Line 272 
Line 286 
          * Create the midi control end, or a simple thru box           * Create the midi control end, or a simple thru box
          * if there's no device           * if there's no device
          */           */
         dev_midi = (dev_mode == 0) ? thru_new("thru") : ctl_new("ctl");          d->midi = (d->mode == 0) ? thru_new("thru") : ctl_new("ctl", d);
         dev_midi->refs++;          d->midi->refs++;
   
         /*          /*
          * Create mixer, demuxer and monitor           * Create mixer, demuxer and monitor
          */           */
         if (dev_mode & MODE_PLAY) {          if (d->mode & MODE_PLAY) {
                 dev_mix = mix_new("play", dev_bufsz, dev_round);                  d->mix = mix_new("play", d->bufsz, d->round);
                 dev_mix->refs++;                  d->mix->refs++;
                 dev_mix->u.mix.ctl = dev_midi;                  d->mix->u.mix.ctl = d->midi;
         }          }
         if (dev_mode & MODE_REC) {          if (d->mode & MODE_REC) {
                 dev_sub = sub_new("rec", dev_bufsz, dev_round);                  d->sub = sub_new("rec", d->bufsz, d->round);
                 dev_sub->refs++;                  d->sub->refs++;
                 /*                  /*
                  * If not playing, use the record end as clock source                   * If not playing, use the record end as clock source
                  */                   */
                 if (!(dev_mode & MODE_PLAY))                  if (!(d->mode & MODE_PLAY))
                         dev_sub->u.sub.ctl = dev_midi;                          d->sub->u.sub.ctl = d->midi;
         }          }
         if (dev_mode & MODE_LOOP) {          if (d->mode & MODE_LOOP) {
                 /*                  /*
                  * connect mixer out to demuxer in                   * connect mixer out to demuxer in
                  */                   */
                 buf = abuf_new(dev_bufsz, &dev_opar);                  buf = abuf_new(d->bufsz, &d->opar);
                 aproc_setout(dev_mix, buf);                  aproc_setout(d->mix, buf);
                 aproc_setin(dev_sub, buf);                  aproc_setin(d->sub, buf);
   
                 dev_mix->flags |= APROC_QUIT;                  d->mix->flags |= APROC_QUIT;
                 dev_sub->flags |= APROC_QUIT;                  d->sub->flags |= APROC_QUIT;
                 dev_rate = dev_opar.rate;                  d->rate = d->opar.rate;
         }          }
         if (dev_rec) {          if (d->rec) {
                 aparams_init(&par, dev_ipar.cmin, dev_ipar.cmax, dev_rate);                  aparams_init(&par, d->ipar.cmin, d->ipar.cmax, d->rate);
   
                 /*                  /*
                  * Create device <-> demuxer buffer                   * Create device <-> demuxer buffer
                  */                   */
                 buf = abuf_new(dev_bufsz, &dev_ipar);                  buf = abuf_new(d->bufsz, &d->ipar);
                 aproc_setout(dev_rec, buf);                  aproc_setout(d->rec, buf);
   
                 /*                  /*
                  * Insert a converter, if needed.                   * Insert a converter, if needed.
                  */                   */
                 if (!aparams_eqenc(&dev_ipar, &par)) {                  if (!aparams_eqenc(&d->ipar, &par)) {
                         conv = dec_new("rec", &dev_ipar);                          conv = dec_new("rec", &d->ipar);
                         aproc_setin(conv, buf);                          aproc_setin(conv, buf);
                         buf = abuf_new(dev_round, &par);                          buf = abuf_new(d->round, &par);
                         aproc_setout(conv, buf);                          aproc_setout(conv, buf);
                 }                  }
                 dev_ipar = par;                  d->ipar = par;
                 aproc_setin(dev_sub, buf);                  aproc_setin(d->sub, buf);
         }          }
         if (dev_play) {          if (d->play) {
                 aparams_init(&par, dev_opar.cmin, dev_opar.cmax, dev_rate);                  aparams_init(&par, d->opar.cmin, d->opar.cmax, d->rate);
   
                 /*                  /*
                  * Create device <-> mixer buffer                   * Create device <-> mixer buffer
                  */                   */
                 buf = abuf_new(dev_bufsz, &dev_opar);                  buf = abuf_new(d->bufsz, &d->opar);
                 aproc_setin(dev_play, buf);                  aproc_setin(d->play, buf);
   
                 /*                  /*
                  * Append a converter, if needed.                   * Append a converter, if needed.
                  */                   */
                 if (!aparams_eqenc(&par, &dev_opar)) {                  if (!aparams_eqenc(&par, &d->opar)) {
                         conv = enc_new("play", &dev_opar);                          conv = enc_new("play", &d->opar);
                         aproc_setout(conv, buf);                          aproc_setout(conv, buf);
                         buf = abuf_new(dev_round, &par);                          buf = abuf_new(d->round, &par);
                         aproc_setin(conv, buf);                          aproc_setin(conv, buf);
                 }                  }
                 dev_opar = par;                  d->opar = par;
                 aproc_setout(dev_mix, buf);                  aproc_setout(d->mix, buf);
         }          }
         if (dev_mode & MODE_MON) {          if (d->mode & MODE_MON) {
                 dev_mon = mon_new("mon", dev_bufsz);                  d->mon = mon_new("mon", d->bufsz);
                 dev_mon->refs++;                  d->mon->refs++;
                 buf = abuf_new(dev_bufsz, &dev_opar);                  buf = abuf_new(d->bufsz, &d->opar);
                 aproc_setout(dev_mon, buf);                  aproc_setout(d->mon, buf);
   
                 /*                  /*
                  * Append a "sub" to which clients will connect.                   * Append a "sub" to which clients will connect.
                  */                   */
                 dev_submon = sub_new("mon", dev_bufsz, dev_round);                  d->submon = sub_new("mon", d->bufsz, d->round);
                 dev_submon->refs++;                  d->submon->refs++;
                 aproc_setin(dev_submon, buf);                  aproc_setin(d->submon, buf);
   
                 /*                  /*
                  * Attach to the mixer                   * Attach to the mixer
                  */                   */
                 dev_mix->u.mix.mon = dev_mon;                  d->mix->u.mix.mon = d->mon;
                 dev_mon->refs++;                  d->mon->refs++;
         }          }
 #ifdef DEBUG  #ifdef DEBUG
         if (debug_level >= 2) {          if (debug_level >= 2) {
                 if (dev_mode & (MODE_PLAY | MODE_RECMASK)) {                  if (d->mode & (MODE_PLAY | MODE_RECMASK)) {
                         dbg_puts("device block size is ");                          dbg_puts("device block size is ");
                         dbg_putu(dev_round);                          dbg_putu(d->round);
                         dbg_puts(" frames, using ");                          dbg_puts(" frames, using ");
                         dbg_putu(dev_bufsz / dev_round);                          dbg_putu(d->bufsz / d->round);
                         dbg_puts(" blocks\n");                          dbg_puts(" blocks\n");
                 }                  }
         }          }
 #endif  #endif
         dev_pstate = DEV_INIT;          d->pstate = DEV_INIT;
         if (dev_reqprime)          if (d->prime)
                 dev_prime();                  dev_prime(d);
         return 1;          return 1;
 }  }
   
Line 387 
Line 401 
  * once both play chain and record chain are gone.   * once both play chain and record chain are gone.
  */   */
 void  void
 dev_close(void)  dev_close(struct dev *d)
 {  {
         struct file *f;          struct file *f;
   
Line 395 
Line 409 
          * if the device is starting, ensure it actually starts           * if the device is starting, ensure it actually starts
          * so buffers are drained, else clear any buffers           * so buffers are drained, else clear any buffers
          */           */
         switch (dev_pstate) {          switch (d->pstate) {
         case DEV_START:          case DEV_START:
 #ifdef DEBUG  #ifdef DEBUG
                 if (debug_level >= 3)                  if (debug_level >= 3)
                         dbg_puts("draining device\n");                          dbg_puts("draining device\n");
 #endif  #endif
                 dev_start();                  dev_start(d);
                 break;                  break;
         case DEV_INIT:          case DEV_INIT:
 #ifdef DEBUG  #ifdef DEBUG
                 if (debug_level >= 3)                  if (debug_level >= 3)
                         dbg_puts("flushing device\n");                          dbg_puts("flushing device\n");
 #endif  #endif
                 dev_clear();                  dev_clear(d);
                 break;                  break;
         }          }
 #ifdef DEBUG  #ifdef DEBUG
Line 416 
Line 430 
                 dbg_puts("closing device\n");                  dbg_puts("closing device\n");
 #endif  #endif
   
         if (dev_mix) {          if (d->mix) {
                 /*                  /*
                  * Put the mixer in ``autoquit'' state and generate                   * Put the mixer in ``autoquit'' state and generate
                  * EOF on all inputs connected it. Once buffers are                   * EOF on all inputs connected it. Once buffers are
Line 427 
Line 441 
                  * reorder the file_list, we have to restart the loop                   * reorder the file_list, we have to restart the loop
                  * after each call to file_eof().                   * after each call to file_eof().
                  */                   */
                 if (APROC_OK(dev_mix))                  if (APROC_OK(d->mix))
                         mix_quit(dev_mix);                          mix_quit(d->mix);
   
                 /*                  /*
                  * XXX: handle this in mix_done()                   * XXX: handle this in mix_done()
                  */                   */
                 if (APROC_OK(dev_mix->u.mix.mon)) {                  if (APROC_OK(d->mix->u.mix.mon)) {
                         dev_mix->u.mix.mon->refs--;                          d->mix->u.mix.mon->refs--;
                         aproc_del(dev_mix->u.mix.mon);                          aproc_del(d->mix->u.mix.mon);
                         dev_mix->u.mix.mon = NULL;                          d->mix->u.mix.mon = NULL;
                 }                  }
         restart_mix:          restart_mix:
                 LIST_FOREACH(f, &file_list, entry) {                  LIST_FOREACH(f, &file_list, entry) {
                         if (f->rproc != NULL &&                          if (f->rproc != NULL &&
                             aproc_depend(dev_mix, f->rproc)) {                              aproc_depend(d->mix, f->rproc)) {
                                 file_eof(f);                                  file_eof(f);
                                 goto restart_mix;                                  goto restart_mix;
                         }                          }
                 }                  }
         } else if (dev_sub || dev_submon) {          } else if (d->sub || d->submon) {
                 /*                  /*
                  * Same as above, but since there's no mixer,                   * Same as above, but since there's no mixer,
                  * we generate EOF on the record-end of the                   * we generate EOF on the record-end of the
Line 455 
Line 469 
         restart_sub:          restart_sub:
                 LIST_FOREACH(f, &file_list, entry) {                  LIST_FOREACH(f, &file_list, entry) {
                         if (f->rproc != NULL &&                          if (f->rproc != NULL &&
                             (aproc_depend(dev_sub, f->rproc) ||                              (aproc_depend(d->sub, f->rproc) ||
                              aproc_depend(dev_submon, f->rproc))) {                               aproc_depend(d->submon, f->rproc))) {
                                 file_eof(f);                                  file_eof(f);
                                 goto restart_sub;                                  goto restart_sub;
                         }                          }
                 }                  }
         }          }
         if (dev_midi) {          if (d->midi) {
                 dev_midi->flags |= APROC_QUIT;                  d->midi->flags |= APROC_QUIT;
                 if (LIST_EMPTY(&dev_midi->ins))                  if (LIST_EMPTY(&d->midi->ins))
                         aproc_del(dev_midi);                          aproc_del(d->midi);
         restart_midi:          restart_midi:
                 LIST_FOREACH(f, &file_list, entry) {                  LIST_FOREACH(f, &file_list, entry) {
                         if (f->rproc &&                          if (f->rproc &&
                             aproc_depend(dev_midi, f->rproc)) {                              aproc_depend(d->midi, f->rproc)) {
                                 file_eof(f);                                  file_eof(f);
                                 goto restart_midi;                                  goto restart_midi;
                         }                          }
                 }                  }
         }          }
         if (dev_mix) {          if (d->mix) {
                 if (--dev_mix->refs == 0 && (dev_mix->flags & APROC_ZOMB))                  if (--d->mix->refs == 0 && (d->mix->flags & APROC_ZOMB))
                         aproc_del(dev_mix);                          aproc_del(d->mix);
                 dev_mix = NULL;                  d->mix = NULL;
         }          }
         if (dev_play) {          if (d->play) {
                 if (--dev_play->refs == 0 && (dev_play->flags & APROC_ZOMB))                  if (--d->play->refs == 0 && (d->play->flags & APROC_ZOMB))
                         aproc_del(dev_play);                          aproc_del(d->play);
                 dev_play = NULL;                  d->play = NULL;
         }          }
         if (dev_sub) {          if (d->sub) {
                 if (--dev_sub->refs == 0 && (dev_sub->flags & APROC_ZOMB))                  if (--d->sub->refs == 0 && (d->sub->flags & APROC_ZOMB))
                         aproc_del(dev_sub);                          aproc_del(d->sub);
                 dev_sub = NULL;                  d->sub = NULL;
         }          }
         if (dev_rec) {          if (d->rec) {
                 if (--dev_rec->refs == 0 && (dev_rec->flags & APROC_ZOMB))                  if (--d->rec->refs == 0 && (d->rec->flags & APROC_ZOMB))
                         aproc_del(dev_rec);                          aproc_del(d->rec);
                 dev_rec = NULL;                  d->rec = NULL;
         }          }
         if (dev_submon) {          if (d->submon) {
                 if (--dev_submon->refs == 0 && (dev_submon->flags & APROC_ZOMB))                  if (--d->submon->refs == 0 && (d->submon->flags & APROC_ZOMB))
                         aproc_del(dev_submon);                          aproc_del(d->submon);
                 dev_submon = NULL;                  d->submon = NULL;
         }          }
         if (dev_mon) {          if (d->mon) {
                 if (--dev_mon->refs == 0 && (dev_mon->flags & APROC_ZOMB))                  if (--d->mon->refs == 0 && (d->mon->flags & APROC_ZOMB))
                         aproc_del(dev_mon);                          aproc_del(d->mon);
                 dev_mon = NULL;                  d->mon = NULL;
         }          }
         if (dev_midi) {          if (d->midi) {
                 if (--dev_midi->refs == 0 && (dev_midi->flags & APROC_ZOMB))                  if (--d->midi->refs == 0 && (d->midi->flags & APROC_ZOMB))
                         aproc_del(dev_midi);                          aproc_del(d->midi);
                 dev_midi = NULL;                  d->midi = NULL;
         }          }
         dev_pstate = DEV_CLOSED;          d->pstate = DEV_CLOSED;
 }  }
   
 /*  /*
  * Free the device   * Free the device
  */   */
 void  void
 dev_done(void)  dev_del(struct dev *d)
 {  {
         if (dev_pstate != DEV_CLOSED)          struct dev **p;
                 dev_close();  
           if (d->pstate != DEV_CLOSED)
                   dev_close(d);
           for (p = &dev_list; *p != d; p = &(*p)->next) {
   #ifdef DEBUG
                   if (*p == NULL) {
                           dbg_puts("device to delete not on the list\n");
                           dbg_panic();
                   }
   #endif
           }
           *p = d->next;
           free(d);
 }  }
   
 /*  /*
  * Open a MIDI device and connect it to the thru box   * Open a MIDI device and connect it to the thru box
  */   */
 int  int
 dev_thruadd(char *name, int in, int out)  dev_thruadd(struct dev *d, char *name, int in, int out)
 {  {
         struct file *f;          struct file *f;
         struct abuf *rbuf = NULL, *wbuf = NULL;          struct abuf *rbuf = NULL, *wbuf = NULL;
         struct aproc *rproc, *wproc;          struct aproc *rproc, *wproc;
   
         if (!dev_ref())          if (!dev_ref(d))
                 return 0;                  return 0;
         f = (struct file *)miofile_new(&miofile_ops, name, in, out);          f = (struct file *)miofile_new(&miofile_ops, name, in, out);
         if (f == NULL)          if (f == NULL)
Line 548 
Line 574 
                 wbuf = abuf_new(MIDI_BUFSZ, &aparams_none);                  wbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
                 aproc_setin(wproc, wbuf);                  aproc_setin(wproc, wbuf);
         }          }
         dev_midiattach(rbuf, wbuf);          dev_midiattach(d, rbuf, wbuf);
         return 1;          return 1;
 }  }
   
Line 556 
Line 582 
  * Attach a bi-directional MIDI stream to the MIDI device   * Attach a bi-directional MIDI stream to the MIDI device
  */   */
 void  void
 dev_midiattach(struct abuf *ibuf, struct abuf *obuf)  dev_midiattach(struct dev *d, struct abuf *ibuf, struct abuf *obuf)
 {  {
         if (ibuf)          if (ibuf)
                 aproc_setin(dev_midi, ibuf);                  aproc_setin(d->midi, ibuf);
         if (obuf) {          if (obuf) {
                 aproc_setout(dev_midi, obuf);                  aproc_setout(d->midi, obuf);
                 if (ibuf) {                  if (ibuf) {
                         ibuf->duplex = obuf;                          ibuf->duplex = obuf;
                         obuf->duplex = ibuf;                          obuf->duplex = ibuf;
Line 570 
Line 596 
 }  }
   
 unsigned  unsigned
 dev_roundof(unsigned newrate)  dev_roundof(struct dev *d, unsigned newrate)
 {  {
         return (dev_round * newrate + dev_rate / 2) / dev_rate;          return (d->round * newrate + d->rate / 2) / d->rate;
 }  }
   
 /*  /*
  * Start the (paused) device. By default it's paused.   * Start the (paused) device. By default it's paused.
  */   */
 void  void
 dev_start(void)  dev_start(struct dev *d)
 {  {
         struct file *f;          struct file *f;
   
Line 587 
Line 613 
         if (debug_level >= 2)          if (debug_level >= 2)
                 dbg_puts("starting device\n");                  dbg_puts("starting device\n");
 #endif  #endif
         dev_pstate = DEV_RUN;          d->pstate = DEV_RUN;
         if (dev_mode & MODE_LOOP)          if (d->mode & MODE_LOOP)
                 return;                  return;
         if (APROC_OK(dev_mix))          if (APROC_OK(d->mix))
                 dev_mix->flags |= APROC_DROP;                  d->mix->flags |= APROC_DROP;
         if (APROC_OK(dev_sub))          if (APROC_OK(d->sub))
                 dev_sub->flags |= APROC_DROP;                  d->sub->flags |= APROC_DROP;
         if (APROC_OK(dev_submon))          if (APROC_OK(d->submon))
                 dev_submon->flags |= APROC_DROP;                  d->submon->flags |= APROC_DROP;
         if (APROC_OK(dev_play) && dev_play->u.io.file) {          if (APROC_OK(d->play) && d->play->u.io.file) {
                 f = dev_play->u.io.file;                  f = d->play->u.io.file;
                 f->ops->start(f);                  f->ops->start(f);
         } else if (APROC_OK(dev_rec) && dev_rec->u.io.file) {          } else if (APROC_OK(d->rec) && d->rec->u.io.file) {
                 f = dev_rec->u.io.file;                  f = d->rec->u.io.file;
                 f->ops->start(f);                  f->ops->start(f);
         }          }
 }  }
Line 610 
Line 636 
  * so it shouldn't be called from aproc methods   * so it shouldn't be called from aproc methods
  */   */
 void  void
 dev_stop(void)  dev_stop(struct dev *d)
 {  {
         struct file *f;          struct file *f;
   
 #ifdef DEBUG  #ifdef DEBUG
         if (debug_level >= 2)          if (debug_level >= 2)
                 dbg_puts("stopping stopped\n");                  dbg_puts("device stopped\n");
 #endif  #endif
         dev_pstate = DEV_INIT;          d->pstate = DEV_INIT;
         if (dev_mode & MODE_LOOP)          if (d->mode & MODE_LOOP)
                 return;                  return;
         if (APROC_OK(dev_play) && dev_play->u.io.file) {          if (APROC_OK(d->play) && d->play->u.io.file) {
                 f = dev_play->u.io.file;                  f = d->play->u.io.file;
                 f->ops->stop(f);                  f->ops->stop(f);
         } else if (APROC_OK(dev_rec) && dev_rec->u.io.file) {          } else if (APROC_OK(d->rec) && d->rec->u.io.file) {
                 f = dev_rec->u.io.file;                  f = d->rec->u.io.file;
                 f->ops->stop(f);                  f->ops->stop(f);
         }          }
         if (APROC_OK(dev_mix))          if (APROC_OK(d->mix))
                 dev_mix->flags &= ~APROC_DROP;                  d->mix->flags &= ~APROC_DROP;
         if (APROC_OK(dev_sub))          if (APROC_OK(d->sub))
                 dev_sub->flags &= ~APROC_DROP;                  d->sub->flags &= ~APROC_DROP;
         if (APROC_OK(dev_submon))          if (APROC_OK(d->submon))
                 dev_submon->flags &= ~APROC_DROP;                  d->submon->flags &= ~APROC_DROP;
 }  }
   
 int  int
 dev_ref(void)  dev_ref(struct dev *d)
 {  {
 #ifdef DEBUG  #ifdef DEBUG
         if (debug_level >= 3)          if (debug_level >= 3)
                 dbg_puts("device requested\n");                  dbg_puts("device requested\n");
 #endif  #endif
         if (dev_pstate == DEV_CLOSED && !dev_open())          if (d->pstate == DEV_CLOSED && !dev_open(d)) {
                   if (d->hold)
                           dev_del(d);
                 return 0;                  return 0;
         dev_refcnt++;          }
           d->refcnt++;
         return 1;          return 1;
 }  }
   
 void  void
 dev_unref(void)  dev_unref(struct dev *d)
 {  {
 #ifdef DEBUG  #ifdef DEBUG
         if (debug_level >= 3)          if (debug_level >= 3)
                 dbg_puts("device released\n");                  dbg_puts("device released\n");
 #endif  #endif
         dev_refcnt--;          d->refcnt--;
         if (dev_refcnt == 0 && dev_pstate == DEV_INIT)          if (d->refcnt == 0 && d->pstate == DEV_INIT && !d->hold)
                 dev_close();                  dev_close(d);
 }  }
   
 /*  /*
Line 672 
Line 701 
  * on fatal error   * on fatal error
  */   */
 int  int
 dev_run(void)  dev_run(struct dev *d)
 {  {
         if (dev_pstate == DEV_CLOSED)          if (d->pstate == DEV_CLOSED)
                 return 1;                  return 1;
         /*          /*
          * check if device isn't gone           * check if device isn't gone
          */           */
         if (((dev_mode & MODE_PLAY) && !APROC_OK(dev_mix)) ||          if (((d->mode & MODE_PLAY) && !APROC_OK(d->mix)) ||
             ((dev_mode & MODE_REC)  && !APROC_OK(dev_sub)) ||              ((d->mode & MODE_REC)  && !APROC_OK(d->sub)) ||
             ((dev_mode & MODE_MON)  && !APROC_OK(dev_submon))) {              ((d->mode & MODE_MON)  && !APROC_OK(d->submon))) {
 #ifdef DEBUG  #ifdef DEBUG
                 if (debug_level >= 1)                  if (debug_level >= 1)
                         dbg_puts("device disappeared\n");                          dbg_puts("device disappeared\n");
 #endif  #endif
                 dev_close();                  if (d->hold) {
                 return 0;                          dev_del(d);
                           return 0;
                   }
                   dev_close(d);
                   return 1;
         }          }
         switch (dev_pstate) {          switch (d->pstate) {
         case DEV_INIT:          case DEV_INIT:
                 /* nothing */                  /* nothing */
                 break;                  break;
         case DEV_START:          case DEV_START:
                 dev_start();                  dev_start(d);
                 /* PASSTHROUGH */                  /* PASSTHROUGH */
         case DEV_RUN:          case DEV_RUN:
                 /*                  /*
                  * if the device is not used, then stop it                   * if the device is not used, then stop it
                  */                   */
                 if ((!APROC_OK(dev_mix) ||                  if ((!APROC_OK(d->mix) ||
                         dev_mix->u.mix.idle > 2 * dev_bufsz) &&                          d->mix->u.mix.idle > 2 * d->bufsz) &&
                     (!APROC_OK(dev_sub) ||                      (!APROC_OK(d->sub) ||
                         dev_sub->u.sub.idle > 2 * dev_bufsz) &&                          d->sub->u.sub.idle > 2 * d->bufsz) &&
                     (!APROC_OK(dev_submon) ||                      (!APROC_OK(d->submon) ||
                         dev_submon->u.sub.idle > 2 * dev_bufsz) &&                          d->submon->u.sub.idle > 2 * d->bufsz) &&
                     (!APROC_OK(dev_midi) ||                      (!APROC_OK(d->midi) ||
                         dev_midi->u.ctl.tstate != CTL_RUN)) {                          d->midi->u.ctl.tstate != CTL_RUN)) {
 #ifdef DEBUG  #ifdef DEBUG
                         if (debug_level >= 3)                          if (debug_level >= 3)
                                 dbg_puts("device idle, suspending\n");                                  dbg_puts("device idle, suspending\n");
 #endif  #endif
                         dev_stop();                          dev_stop(d);
                         if (dev_refcnt == 0)                          if (d->refcnt == 0 && !d->hold)
                                 dev_close();                                  dev_close(d);
                         else {                          else {
                                 dev_clear();                                  dev_clear(d);
                                 if (dev_reqprime)                                  if (d->prime)
                                         dev_prime();                                          dev_prime(d);
                         }                          }
                 }                  }
                 break;                  break;
Line 734 
Line 767 
  * This routine can be called from aproc context.   * This routine can be called from aproc context.
  */   */
 void  void
 dev_wakeup(void)  dev_wakeup(struct dev *d)
 {  {
         if (dev_pstate == DEV_INIT)          if (d->pstate == DEV_INIT)
                 dev_pstate = DEV_START;                  d->pstate = DEV_START;
 }  }
   
 /*  /*
  * Find the end points connected to the mix/sub.   * Find the end points connected to the mix/sub.
  */   */
 int  int
 dev_getep(unsigned mode, struct abuf **sibuf, struct abuf **sobuf)  dev_getep(struct dev *d,
       unsigned mode, struct abuf **sibuf, struct abuf **sobuf)
 {  {
         struct abuf *ibuf, *obuf;          struct abuf *ibuf, *obuf;
   
         if (mode & MODE_PLAY) {          if (mode & MODE_PLAY) {
                 if (!APROC_OK(dev_mix))                  if (!APROC_OK(d->mix))
                         return 0;                          return 0;
                 ibuf = *sibuf;                  ibuf = *sibuf;
                 for (;;) {                  for (;;) {
Line 762 
Line 796 
 #endif  #endif
                                 return 0;                                  return 0;
                         }                          }
                         if (ibuf->rproc == dev_mix)                          if (ibuf->rproc == d->mix)
                                 break;                                  break;
                         ibuf = LIST_FIRST(&ibuf->rproc->outs);                          ibuf = LIST_FIRST(&ibuf->rproc->outs);
                 }                  }
                 *sibuf = ibuf;                  *sibuf = ibuf;
         }          }
         if (mode & MODE_REC) {          if (mode & MODE_REC) {
                 if (!APROC_OK(dev_sub))                  if (!APROC_OK(d->sub))
                         return 0;                          return 0;
                 obuf = *sobuf;                  obuf = *sobuf;
                 for (;;) {                  for (;;) {
Line 782 
Line 816 
 #endif  #endif
                                 return 0;                                  return 0;
                         }                          }
                         if (obuf->wproc == dev_sub)                          if (obuf->wproc == d->sub)
                                 break;                                  break;
                         obuf = LIST_FIRST(&obuf->wproc->ins);                          obuf = LIST_FIRST(&obuf->wproc->ins);
                 }                  }
                 *sobuf = obuf;                  *sobuf = obuf;
         }          }
         if (mode & MODE_MON) {          if (mode & MODE_MON) {
                 if (!APROC_OK(dev_submon))                  if (!APROC_OK(d->submon))
                         return 0;                          return 0;
                 obuf = *sobuf;                  obuf = *sobuf;
                 for (;;) {                  for (;;) {
Line 802 
Line 836 
 #endif  #endif
                                 return 0;                                  return 0;
                         }                          }
                         if (obuf->wproc == dev_submon)                          if (obuf->wproc == d->submon)
                                 break;                                  break;
                         obuf = LIST_FIRST(&obuf->wproc->ins);                          obuf = LIST_FIRST(&obuf->wproc->ins);
                 }                  }
Line 816 
Line 850 
  * them underruns/overruns).   * them underruns/overruns).
  */   */
 void  void
 dev_sync(unsigned mode, struct abuf *ibuf, struct abuf *obuf)  dev_sync(struct dev *d, unsigned mode, struct abuf *ibuf, struct abuf *obuf)
 {  {
         int delta, offs;          int delta, offs;
         struct abuf *mbuf;          struct abuf *mbuf = NULL;
   
         if (!dev_getep(mode, &ibuf, &obuf))          if (!dev_getep(d, mode, &ibuf, &obuf))
                 return;                  return;
         /*          /*
          * Calculate delta, the number of frames the play chain is ahead           * Calculate delta, the number of frames the play chain is ahead
Line 830 
Line 864 
          */           */
         offs = 0;          offs = 0;
         delta = 0;          delta = 0;
         if (APROC_OK(dev_mix)) {          if (APROC_OK(d->mix)) {
                 mbuf = LIST_FIRST(&dev_mix->outs);                  mbuf = LIST_FIRST(&d->mix->outs);
                 offs += mbuf->w.mix.todo;                  offs += mbuf->w.mix.todo;
                 delta += dev_mix->u.mix.lat;                  delta += d->mix->u.mix.lat;
         }          }
         if (APROC_OK(dev_sub))          if (APROC_OK(d->sub))
                 delta += dev_sub->u.sub.lat;                  delta += d->sub->u.sub.lat;
 #ifdef DEBUG  #ifdef DEBUG
         if (debug_level >= 3) {          if (debug_level >= 3) {
                 dbg_puts("syncing device");                  dbg_puts("syncing device");
                 if (APROC_OK(dev_mix)) {                  if (APROC_OK(d->mix)) {
                         dbg_puts(", ");                          dbg_puts(", ");
                         aproc_dbg(dev_mix);                          aproc_dbg(d->mix);
                         dbg_puts(": todo = ");                          dbg_puts(": todo = ");
                         dbg_putu(mbuf->w.mix.todo);                          dbg_putu(mbuf->w.mix.todo);
                         dbg_puts(": lat = ");                          dbg_puts(": lat = ");
                         dbg_putu(dev_mix->u.mix.lat);                          dbg_putu(d->mix->u.mix.lat);
                 }                  }
                 if (APROC_OK(dev_sub)) {                  if (APROC_OK(d->sub)) {
                         dbg_puts(", ");                          dbg_puts(", ");
                         aproc_dbg(dev_sub);                          aproc_dbg(d->sub);
                         dbg_puts(": lat = ");                          dbg_puts(": lat = ");
                         dbg_putu(dev_sub->u.sub.lat);                          dbg_putu(d->sub->u.sub.lat);
                 }                  }
                 dbg_puts("\n");                  dbg_puts("\n");
         }          }
Line 868 
Line 902 
  * a stream would have if dev_attach() is called on it.   * a stream would have if dev_attach() is called on it.
  */   */
 int  int
 dev_getpos(void)  dev_getpos(struct dev *d)
 {  {
         struct abuf *mbuf = NULL;          struct abuf *mbuf = NULL;
   
         if (APROC_OK(dev_mix)) {          if (APROC_OK(d->mix)) {
                 mbuf = LIST_FIRST(&dev_mix->outs);                  mbuf = LIST_FIRST(&d->mix->outs);
                 return -(mbuf->w.mix.todo + dev_mix->u.mix.lat);                  return -(mbuf->w.mix.todo + d->mix->u.mix.lat);
         } else          } else
                 return 0;                  return 0;
 }  }
Line 886 
Line 920 
  * and rec.   * and rec.
  */   */
 void  void
 dev_attach(char *name, unsigned mode,  dev_attach(struct dev *d, char *name, unsigned mode,
     struct abuf *ibuf, struct aparams *sipar, unsigned inch,      struct abuf *ibuf, struct aparams *sipar, unsigned inch,
     struct abuf *obuf, struct aparams *sopar, unsigned onch,      struct abuf *obuf, struct aparams *sopar, unsigned onch,
     unsigned xrun, int vol)      unsigned xrun, int vol)
Line 897 
Line 931 
         unsigned round, nblk, nch;          unsigned round, nblk, nch;
   
 #ifdef DEBUG  #ifdef DEBUG
         if ((!APROC_OK(dev_mix)    && (mode & MODE_PLAY)) ||          if ((!APROC_OK(d->mix)    && (mode & MODE_PLAY)) ||
             (!APROC_OK(dev_sub)    && (mode & MODE_REC)) ||              (!APROC_OK(d->sub)    && (mode & MODE_REC)) ||
             (!APROC_OK(dev_submon) && (mode & MODE_MON))) {              (!APROC_OK(d->submon) && (mode & MODE_MON))) {
                 dbg_puts("mode beyond device mode, not attaching\n");                  dbg_puts("mode beyond device mode, not attaching\n");
                 return;                  return;
         }          }
 #endif  #endif
         if (mode & MODE_PLAY) {          if (mode & MODE_PLAY) {
                 ipar = *sipar;                  ipar = *sipar;
                 pbuf = LIST_FIRST(&dev_mix->outs);                  pbuf = LIST_FIRST(&d->mix->outs);
                 nblk = (dev_bufsz / dev_round + 3) / 4;                  nblk = (d->bufsz / d->round + 3) / 4;
                 round = dev_roundof(ipar.rate);                  round = dev_roundof(d, ipar.rate);
                 nch = ipar.cmax - ipar.cmin + 1;                  nch = ipar.cmax - ipar.cmin + 1;
                 if (!aparams_eqenc(&ipar, &dev_opar)) {                  if (!aparams_eqenc(&ipar, &d->opar)) {
                         conv = dec_new(name, &ipar);                          conv = dec_new(name, &ipar);
                         ipar.bps = dev_opar.bps;                          ipar.bps = d->opar.bps;
                         ipar.bits = dev_opar.bits;                          ipar.bits = d->opar.bits;
                         ipar.sig = dev_opar.sig;                          ipar.sig = d->opar.sig;
                         ipar.le = dev_opar.le;                          ipar.le = d->opar.le;
                         ipar.msb = dev_opar.msb;                          ipar.msb = d->opar.msb;
                         aproc_setin(conv, ibuf);                          aproc_setin(conv, ibuf);
                         ibuf = abuf_new(nblk * round, &ipar);                          ibuf = abuf_new(nblk * round, &ipar);
                         aproc_setout(conv, ibuf);                          aproc_setout(conv, ibuf);
Line 928 
Line 962 
                         ibuf = abuf_new(nblk * round, &ipar);                          ibuf = abuf_new(nblk * round, &ipar);
                         aproc_setout(conv, ibuf);                          aproc_setout(conv, ibuf);
                 }                  }
                 if (!aparams_eqrate(&ipar, &dev_opar)) {                  if (!aparams_eqrate(&ipar, &d->opar)) {
                         conv = resamp_new(name, round, dev_round);                          conv = resamp_new(name, round, d->round);
                         ipar.rate = dev_opar.rate;                          ipar.rate = d->opar.rate;
                         round = dev_round;                          round = d->round;
                         aproc_setin(conv, ibuf);                          aproc_setin(conv, ibuf);
                         ibuf = abuf_new(nblk * round, &ipar);                          ibuf = abuf_new(nblk * round, &ipar);
                         aproc_setout(conv, ibuf);                          aproc_setout(conv, ibuf);
Line 943 
Line 977 
                         ibuf = abuf_new(nblk * round, &ipar);                          ibuf = abuf_new(nblk * round, &ipar);
                         aproc_setout(conv, ibuf);                          aproc_setout(conv, ibuf);
                 }                  }
                 aproc_setin(dev_mix, ibuf);                  aproc_setin(d->mix, ibuf);
                 ibuf->r.mix.xrun = xrun;                  ibuf->r.mix.xrun = xrun;
                 ibuf->r.mix.maxweight = vol;                  ibuf->r.mix.maxweight = vol;
                 mix_setmaster(dev_mix);                  mix_setmaster(d->mix);
         }          }
         if (mode & MODE_REC) {          if (mode & MODE_REC) {
                 opar = *sopar;                  opar = *sopar;
                 rbuf = LIST_FIRST(&dev_sub->ins);                  rbuf = LIST_FIRST(&d->sub->ins);
                 round = dev_roundof(opar.rate);                  round = dev_roundof(d, opar.rate);
                 nblk = (dev_bufsz / dev_round + 3) / 4;                  nblk = (d->bufsz / d->round + 3) / 4;
                 nch = opar.cmax - opar.cmin + 1;                  nch = opar.cmax - opar.cmin + 1;
                 if (!aparams_eqenc(&opar, &dev_ipar)) {                  if (!aparams_eqenc(&opar, &d->ipar)) {
                         conv = enc_new(name, &opar);                          conv = enc_new(name, &opar);
                         opar.bps = dev_ipar.bps;                          opar.bps = d->ipar.bps;
                         opar.bits = dev_ipar.bits;                          opar.bits = d->ipar.bits;
                         opar.sig = dev_ipar.sig;                          opar.sig = d->ipar.sig;
                         opar.le = dev_ipar.le;                          opar.le = d->ipar.le;
                         opar.msb = dev_ipar.msb;                          opar.msb = d->ipar.msb;
                         aproc_setout(conv, obuf);                          aproc_setout(conv, obuf);
                         obuf = abuf_new(nblk * round, &opar);                          obuf = abuf_new(nblk * round, &opar);
                         aproc_setin(conv, obuf);                          aproc_setin(conv, obuf);
Line 972 
Line 1006 
                         obuf = abuf_new(nblk * round, &opar);                          obuf = abuf_new(nblk * round, &opar);
                         aproc_setin(conv, obuf);                          aproc_setin(conv, obuf);
                 }                  }
                 if (!aparams_eqrate(&opar, &dev_ipar)) {                  if (!aparams_eqrate(&opar, &d->ipar)) {
                         conv = resamp_new(name, dev_round, round);                          conv = resamp_new(name, d->round, round);
                         opar.rate = dev_ipar.rate;                          opar.rate = d->ipar.rate;
                         round = dev_round;                          round = d->round;
                         aproc_setout(conv, obuf);                          aproc_setout(conv, obuf);
                         obuf = abuf_new(nblk * round, &opar);                          obuf = abuf_new(nblk * round, &opar);
                         aproc_setin(conv, obuf);                          aproc_setin(conv, obuf);
Line 987 
Line 1021 
                         obuf = abuf_new(nblk * round, &opar);                          obuf = abuf_new(nblk * round, &opar);
                         aproc_setin(conv, obuf);                          aproc_setin(conv, obuf);
                 }                  }
                 aproc_setout(dev_sub, obuf);                  aproc_setout(d->sub, obuf);
                 obuf->w.sub.xrun = xrun;                  obuf->w.sub.xrun = xrun;
         }          }
         if (mode & MODE_MON) {          if (mode & MODE_MON) {
                 opar = *sopar;                  opar = *sopar;
                 rbuf = LIST_FIRST(&dev_submon->ins);                  rbuf = LIST_FIRST(&d->submon->ins);
                 round = dev_roundof(opar.rate);                  round = dev_roundof(d, opar.rate);
                 nblk = (dev_bufsz / dev_round + 3) / 4;                  nblk = (d->bufsz / d->round + 3) / 4;
                 nch = opar.cmax - opar.cmin + 1;                  nch = opar.cmax - opar.cmin + 1;
                 if (!aparams_eqenc(&opar, &dev_opar)) {                  if (!aparams_eqenc(&opar, &d->opar)) {
                         conv = enc_new(name, &opar);                          conv = enc_new(name, &opar);
                         opar.bps = dev_opar.bps;                          opar.bps = d->opar.bps;
                         opar.bits = dev_opar.bits;                          opar.bits = d->opar.bits;
                         opar.sig = dev_opar.sig;                          opar.sig = d->opar.sig;
                         opar.le = dev_opar.le;                          opar.le = d->opar.le;
                         opar.msb = dev_opar.msb;                          opar.msb = d->opar.msb;
                         aproc_setout(conv, obuf);                          aproc_setout(conv, obuf);
                         obuf = abuf_new(nblk * round, &opar);                          obuf = abuf_new(nblk * round, &opar);
                         aproc_setin(conv, obuf);                          aproc_setin(conv, obuf);
Line 1014 
Line 1048 
                         obuf = abuf_new(nblk * round, &opar);                          obuf = abuf_new(nblk * round, &opar);
                         aproc_setin(conv, obuf);                          aproc_setin(conv, obuf);
                 }                  }
                 if (!aparams_eqrate(&opar, &dev_opar)) {                  if (!aparams_eqrate(&opar, &d->opar)) {
                         conv = resamp_new(name, dev_round, round);                          conv = resamp_new(name, d->round, round);
                         opar.rate = dev_opar.rate;                          opar.rate = d->opar.rate;
                         round = dev_round;                          round = d->round;
                         aproc_setout(conv, obuf);                          aproc_setout(conv, obuf);
                         obuf = abuf_new(nblk * round, &opar);                          obuf = abuf_new(nblk * round, &opar);
                         aproc_setin(conv, obuf);                          aproc_setin(conv, obuf);
Line 1029 
Line 1063 
                         obuf = abuf_new(nblk * round, &opar);                          obuf = abuf_new(nblk * round, &opar);
                         aproc_setin(conv, obuf);                          aproc_setin(conv, obuf);
                 }                  }
                 aproc_setout(dev_submon, obuf);                  aproc_setout(d->submon, obuf);
                 obuf->w.sub.xrun = xrun;                  obuf->w.sub.xrun = xrun;
         }          }
   
Line 1040 
Line 1074 
                 ibuf->duplex = obuf;                  ibuf->duplex = obuf;
                 obuf->duplex = ibuf;                  obuf->duplex = ibuf;
         }          }
         dev_sync(mode, ibuf, obuf);          dev_sync(d, mode, ibuf, obuf);
 }  }
   
 /*  /*
  * Change the playback volume of the given stream.   * Change the playback volume of the given stream.
  */   */
 void  void
 dev_setvol(struct abuf *ibuf, int vol)  dev_setvol(struct dev *d, struct abuf *ibuf, int vol)
 {  {
 #ifdef DEBUG  #ifdef DEBUG
         if (debug_level >= 3) {          if (debug_level >= 3) {
Line 1057 
Line 1091 
                 dbg_puts("\n");                  dbg_puts("\n");
         }          }
 #endif  #endif
         if (!dev_getep(MODE_PLAY, &ibuf, NULL)) {          if (!dev_getep(d, MODE_PLAY, &ibuf, NULL)) {
                 return;                  return;
         }          }
         ibuf->r.mix.vol = vol;          ibuf->r.mix.vol = vol;
Line 1068 
Line 1102 
  * is started, playback and record start in sync.   * is started, playback and record start in sync.
  */   */
 void  void
 dev_clear(void)  dev_clear(struct dev *d)
 {  {
         struct abuf *buf;          struct abuf *buf;
   
         if (APROC_OK(dev_mix)) {          if (APROC_OK(d->mix)) {
 #ifdef DEBUG  #ifdef DEBUG
                 if (!LIST_EMPTY(&dev_mix->ins)) {                  if (!LIST_EMPTY(&d->mix->ins)) {
                         dbg_puts("play end not idle, can't clear device\n");                          dbg_puts("play end not idle, can't clear device\n");
                         dbg_panic();                          dbg_panic();
                 }                  }
 #endif  #endif
                 buf = LIST_FIRST(&dev_mix->outs);                  buf = LIST_FIRST(&d->mix->outs);
                 while (buf) {                  while (buf) {
                         abuf_clear(buf);                          abuf_clear(buf);
                         buf = LIST_FIRST(&buf->rproc->outs);                          buf = LIST_FIRST(&buf->rproc->outs);
                 }                  }
                 mix_clear(dev_mix);                  mix_clear(d->mix);
         }          }
         if (APROC_OK(dev_sub)) {          if (APROC_OK(d->sub)) {
 #ifdef DEBUG  #ifdef DEBUG
                 if (!LIST_EMPTY(&dev_sub->outs)) {                  if (!LIST_EMPTY(&d->sub->outs)) {
                         dbg_puts("record end not idle, can't clear device\n");                          dbg_puts("record end not idle, can't clear device\n");
                         dbg_panic();                          dbg_panic();
                 }                  }
 #endif  #endif
                 buf = LIST_FIRST(&dev_sub->ins);                  buf = LIST_FIRST(&d->sub->ins);
                 while (buf) {                  while (buf) {
                         abuf_clear(buf);                          abuf_clear(buf);
                         buf = LIST_FIRST(&buf->wproc->ins);                          buf = LIST_FIRST(&buf->wproc->ins);
                 }                  }
                 sub_clear(dev_sub);                  sub_clear(d->sub);
         }          }
         if (APROC_OK(dev_submon)) {          if (APROC_OK(d->submon)) {
 #ifdef DEBUG  #ifdef DEBUG
                 dbg_puts("clearing monitor\n");                  dbg_puts("clearing monitor\n");
                 if (!LIST_EMPTY(&dev_submon->outs)) {                  if (!LIST_EMPTY(&d->submon->outs)) {
                         dbg_puts("monitoring end not idle, can't clear device\n");                          dbg_puts("monitoring end not idle, can't clear device\n");
                         dbg_panic();                          dbg_panic();
                 }                  }
 #endif  #endif
                 buf = LIST_FIRST(&dev_submon->ins);                  buf = LIST_FIRST(&d->submon->ins);
                 while (buf) {                  while (buf) {
                         abuf_clear(buf);                          abuf_clear(buf);
                         buf = LIST_FIRST(&buf->wproc->ins);                          buf = LIST_FIRST(&buf->wproc->ins);
                 }                  }
                 sub_clear(dev_submon);                  sub_clear(d->submon);
                 mon_clear(dev_mon);                  mon_clear(d->mon);
         }          }
 }  }
   
Line 1123 
Line 1157 
  * samples to drop   * samples to drop
  */   */
 void  void
 dev_prime(void)  dev_prime(struct dev *d)
 {  {
   
 #ifdef DEBUG  #ifdef DEBUG
         if (debug_level >= 3)          if (debug_level >= 3)
                 dbg_puts("priming device\n");                  dbg_puts("priming device\n");
 #endif  #endif
         if (APROC_OK(dev_mix)) {          if (APROC_OK(d->mix)) {
 #ifdef DEBUG  #ifdef DEBUG
                 if (!LIST_EMPTY(&dev_mix->ins)) {                  if (!LIST_EMPTY(&d->mix->ins)) {
                         dbg_puts("play end not idle, can't prime device\n");                          dbg_puts("play end not idle, can't prime device\n");
                         dbg_panic();                          dbg_panic();
                 }                  }
 #endif  #endif
                 mix_prime(dev_mix);                  mix_prime(d->mix);
         }          }
 }  }

Legend:
Removed from v.1.56  
changed lines
  Added in v.1.57