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

Diff for /src/usr.bin/sndiod/dev.c between version 1.102 and 1.103

version 1.102, 2021/05/03 04:29:50 version 1.103, 2021/11/01 14:43:24
Line 45 
Line 45 
     unsigned int, unsigned int, unsigned int, unsigned int);      unsigned int, unsigned int, unsigned int, unsigned int);
 void dev_adjpar(struct dev *, int, int, int);  void dev_adjpar(struct dev *, int, int, int);
 int dev_allocbufs(struct dev *);  int dev_allocbufs(struct dev *);
 int dev_open(struct dev *);  
 void dev_freebufs(struct dev *);  void dev_freebufs(struct dev *);
 void dev_close(struct dev *);  
 int dev_ref(struct dev *);  int dev_ref(struct dev *);
 void dev_unref(struct dev *);  void dev_unref(struct dev *);
 int dev_init(struct dev *);  int dev_init(struct dev *);
 void dev_done(struct dev *);  void dev_done(struct dev *);
 struct dev *dev_bynum(int);  struct dev *dev_bynum(int);
 void dev_del(struct dev *);  void dev_del(struct dev *);
 void dev_setalt(struct dev *, unsigned int);  
 unsigned int dev_roundof(struct dev *, unsigned int);  unsigned int dev_roundof(struct dev *, unsigned int);
 void dev_wakeup(struct dev *);  void dev_wakeup(struct dev *);
   
Line 930 
Line 927 
                 return NULL;                  return NULL;
         }          }
         d = xmalloc(sizeof(struct dev));          d = xmalloc(sizeof(struct dev));
         d->alt_list = NULL;          d->path = path;
         dev_addname(d,path);  
         d->num = dev_sndnum++;          d->num = dev_sndnum++;
         d->alt_num = -1;  
   
         d->reqpar = *par;          d->reqpar = *par;
         d->reqmode = mode;          d->reqmode = mode;
Line 948 
Line 943 
         d->slot_list = NULL;          d->slot_list = NULL;
         d->master = MIDI_MAXCTL;          d->master = MIDI_MAXCTL;
         d->master_enabled = 0;          d->master_enabled = 0;
           d->alt_next = d;
         snprintf(d->name, CTL_NAMEMAX, "%u", d->num);          snprintf(d->name, CTL_NAMEMAX, "%u", d->num);
         for (pd = &dev_list; *pd != NULL; pd = &(*pd)->next)          for (pd = &dev_list; *pd != NULL; pd = &(*pd)->next)
                 ;                  ;
Line 957 
Line 953 
 }  }
   
 /*  /*
  * add a alternate name  
  */  
 int  
 dev_addname(struct dev *d, char *name)  
 {  
         struct dev_alt *a;  
   
         if (d->alt_list != NULL && d->alt_list->idx == DEV_NMAX - 1) {  
                 log_puts(name);  
                 log_puts(": too many alternate names\n");  
                 return 0;  
         }  
         a = xmalloc(sizeof(struct dev_alt));  
         a->name = name;  
         a->idx = (d->alt_list == NULL) ? 0 : d->alt_list->idx + 1;  
         a->next = d->alt_list;  
         d->alt_list = a;  
         return 1;  
 }  
   
 /*  
  * set prefered alt device name  
  */  
 void  
 dev_setalt(struct dev *d, unsigned int idx)  
 {  
         struct dev_alt **pa, *a;  
   
         /* find alt with given index */  
         for (pa = &d->alt_list; (a = *pa)->idx != idx; pa = &a->next)  
                 ;  
   
         /* detach from list */  
         *pa = a->next;  
   
         /* attach at head */  
         a->next = d->alt_list;  
         d->alt_list = a;  
   
         /* reopen device with the new alt */  
         if (idx != d->alt_num)  
                 dev_reopen(d);  
 }  
   
 /*  
  * adjust device parameters and mode   * adjust device parameters and mode
  */   */
 void  void
Line 1099 
Line 1050 
 int  int
 dev_open(struct dev *d)  dev_open(struct dev *d)
 {  {
         char name[CTL_NAMEMAX];  
         struct dev_alt *a;  
   
         d->mode = d->reqmode;          d->mode = d->reqmode;
         d->round = d->reqround;          d->round = d->reqround;
         d->bufsz = d->reqbufsz;          d->bufsz = d->reqbufsz;
Line 1123 
Line 1071 
         if (!dev_allocbufs(d))          if (!dev_allocbufs(d))
                 return 0;                  return 0;
   
         /* if there are multiple alt devs, add server.device knob */  
         if (d->alt_list->next != NULL) {  
                 for (a = d->alt_list; a != NULL; a = a->next) {  
                         snprintf(name, sizeof(name), "%d", a->idx);  
                         ctl_new(CTL_DEV_ALT, d, &a->idx,  
                             CTL_SEL, d->name, "server", -1, "device",  
                             name, -1, 1, a->idx == d->alt_num);  
                 }  
         }  
   
         d->pstate = DEV_INIT;          d->pstate = DEV_INIT;
         return 1;          return 1;
 }  }
Line 1158 
Line 1096 
         }          }
         d->slot_list = NULL;          d->slot_list = NULL;
   
         for (c = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, c++) {  
                 if (c->ops == NULL)  
                         continue;  
                 if (c->opt->dev != d)  
                         continue;  
                 c->ops->exit(c->arg);  
                 c->ops = NULL;  
         }  
   
         for (o = opt_list; o != NULL; o = o->next) {          for (o = opt_list; o != NULL; o = o->next) {
                 if (o->dev != d)                  if (o->dev != d)
                         continue;                          continue;
                   for (c = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, c++) {
                           if (c->ops == NULL)
                                   continue;
                           if (c->opt == o) {
                                   c->ops->exit(s->arg);
                                   c->ops = NULL;
                           }
                   }
   
                 midi_abort(o->midi);                  midi_abort(o->midi);
         }          }
   
Line 1208 
Line 1146 
 void  void
 dev_close(struct dev *d)  dev_close(struct dev *d)
 {  {
         struct dev_alt *a;  
         unsigned int idx;  
   
         d->pstate = DEV_CFG;          d->pstate = DEV_CFG;
         dev_sio_close(d);          dev_sio_close(d);
         dev_freebufs(d);          dev_freebufs(d);
Line 1219 
Line 1154 
                 d->master_enabled = 0;                  d->master_enabled = 0;
                 ctl_del(CTL_DEV_MASTER, d, NULL);                  ctl_del(CTL_DEV_MASTER, d, NULL);
         }          }
         for (idx = 0, a = d->alt_list; a != NULL; idx++, a = a->next)  
                 ctl_del(CTL_DEV_ALT, d, &idx);  
 }  }
   
 /*  
  * Close the device, but attempt to migrate everything to a new sndio  
  * device.  
  */  
 int  int
 dev_reopen(struct dev *d)  
 {  
         struct mtc *mtc;  
         struct slot *s;  
         long long pos;  
         unsigned int pstate;  
         int delta;  
   
         /* not opened */  
         if (d->pstate == DEV_CFG)  
                 return 1;  
   
         /* save state */  
         delta = d->delta;  
         pstate = d->pstate;  
   
         if (!dev_sio_reopen(d))  
                 return 0;  
   
         /* reopen returns a stopped device */  
         d->pstate = DEV_INIT;  
   
         /* reallocate new buffers, with new parameters */  
         dev_freebufs(d);  
         dev_allocbufs(d);  
   
         /*  
          * adjust time positions, make anything go back delta ticks, so  
          * that the new device can start at zero  
          */  
         for (s = d->slot_list; s != NULL; s = s->next) {  
                 pos = (long long)s->delta * d->round + s->delta_rem;  
                 pos -= (long long)delta * s->round;  
                 s->delta_rem = pos % (int)d->round;  
                 s->delta = pos / (int)d->round;  
                 if (log_level >= 3) {  
                         slot_log(s);  
                         log_puts(": adjusted: delta -> ");  
                         log_puti(s->delta);  
                         log_puts(", delta_rem -> ");  
                         log_puti(s->delta_rem);  
                         log_puts("\n");  
                 }  
   
                 /* reinitilize the format conversion chain */  
                 slot_initconv(s);  
         }  
         mtc = &mtc_array[0];  
         if (mtc->dev == d && mtc->tstate == MTC_RUN) {  
                 mtc->delta -= delta * MTC_SEC;  
                 if (log_level >= 2) {  
                         dev_log(mtc->dev);  
                         log_puts(": adjusted mtc: delta ->");  
                         log_puti(mtc->delta);  
                         log_puts("\n");  
                 }  
         }  
   
         /* remove old controls and add new ones */  
         dev_sioctl_close(d);  
         dev_sioctl_open(d);  
   
         /* start the device if needed */  
         if (pstate == DEV_RUN)  
                 dev_wakeup(d);  
   
         return 1;  
 }  
   
 int  
 dev_ref(struct dev *d)  dev_ref(struct dev *d)
 {  {
 #ifdef DEBUG  #ifdef DEBUG
Line 1381 
Line 1240 
 dev_del(struct dev *d)  dev_del(struct dev *d)
 {  {
         struct dev **p;          struct dev **p;
         struct dev_alt *a;  
   
 #ifdef DEBUG  #ifdef DEBUG
         if (log_level >= 3) {          if (log_level >= 3) {
Line 1401 
Line 1259 
 #endif  #endif
         }          }
         *p = d->next;          *p = d->next;
         while ((a = d->alt_list) != NULL) {  
                 d->alt_list = a->next;  
                 xfree(a);  
         }  
         xfree(d);          xfree(d);
 }  }
   
Line 1444 
Line 1298 
 }  }
   
 /*  /*
    * Return true if both of the given devices can run the same
    * clients
    */
   int
   dev_iscompat(struct dev *o, struct dev *n)
   {
           if (((long long)o->round * n->rate != (long long)n->round * o->rate) ||
               ((long long)o->bufsz * n->rate != (long long)n->bufsz * o->rate)) {
                   if (log_level >= 1) {
                           log_puts(n->name);
                           log_puts(": not compatible with ");
                           log_puts(o->name);
                           log_puts("\n");
                   }
                   return 0;
           }
           return 1;
   }
   
   /*
    * Close the device, but attempt to migrate everything to a new sndio
    * device.
    */
   struct dev *
   dev_migrate(struct dev *odev)
   {
           struct dev *ndev;
           struct opt *o;
           struct slot *s;
           int i;
   
           /* not opened */
           if (odev->pstate == DEV_CFG)
                   return odev;
   
           ndev = odev;
           while (1) {
                   /* try next one, circulating through the list */
                   ndev = ndev->alt_next;
                   if (ndev == odev) {
                           if (log_level >= 1) {
                                   dev_log(odev);
                                   log_puts(": no fall-back device found\n");
                           }
                           return NULL;
                   }
   
   
                   if (!dev_ref(ndev))
                           continue;
   
                   /* check if new parameters are compatible with old ones */
                   if (!dev_iscompat(odev, ndev)) {
                           dev_unref(ndev);
                           continue;
                   }
   
                   /* found it!*/
                   break;
           }
   
           if (log_level >= 1) {
                   dev_log(odev);
                   log_puts(": switching to ");
                   dev_log(ndev);
                   log_puts("\n");
           }
   
           if (mtc_array[0].dev == odev)
                   mtc_setdev(&mtc_array[0], ndev);
   
           /* move opts to new device (also moves clients using the opts) */
           for (o = opt_list; o != NULL; o = o->next) {
                   if (o->dev != odev)
                           continue;
                   if (strcmp(o->name, o->dev->name) == 0)
                           continue;
                   opt_setdev(o, ndev);
           }
   
           /* terminate remaining clients */
           for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
                   if (s->opt == NULL || s->opt->dev != odev)
                           continue;
                   if (s->ops != NULL) {
                           s->ops->exit(s);
                           s->ops = NULL;
                   }
           }
   
           /* slots and/or MMC hold refs, drop ours */
           dev_unref(ndev);
   
           return ndev;
   }
   
   /*
  * check that all clients controlled by MMC are ready to start, if so,   * check that all clients controlled by MMC are ready to start, if so,
  * attach them all at the same position   * attach them all at the same position
  */   */
Line 1552 
Line 1503 
 }  }
   
 /*  /*
    * set MMC device
    */
   void
   mtc_setdev(struct mtc *mtc, struct dev *d)
   {
           struct opt *o;
   
           if (mtc->dev == d)
                   return;
   
           if (log_level >= 2) {
                   dev_log(d);
                   log_puts(": set to be MIDI clock source\n");
           }
   
           /* adjust clock and ref counter, if needed */
           if (mtc->tstate == MTC_RUN) {
                   mtc->delta -= mtc->dev->delta;
                   dev_unref(mtc->dev);
           }
   
           mtc->dev = d;
   
           if (mtc->tstate == MTC_RUN) {
                   mtc->delta += mtc->dev->delta;
                   dev_ref(mtc->dev);
                   dev_wakeup(mtc->dev);
           }
   
           /* move in once anything using MMC */
           for (o = opt_list; o != NULL; o = o->next) {
                   if (o->mtc == mtc)
                           opt_setdev(o, mtc->dev);
           }
   }
   
   /*
  * allocate buffers & conversion chain   * allocate buffers & conversion chain
  */   */
 void  void
Line 1787 
Line 1775 
             NULL, -1, 127, s->vol);              NULL, -1, 127, s->vol);
   
 found:  found:
         if (!dev_ref(opt->dev))          /* open device, this may change opt's device */
           if (!opt_ref(s->opt))
                 return NULL;                  return NULL;
         s->opt = opt;          s->opt = opt;
         s->ops = ops;          s->ops = ops;
Line 1809 
Line 1798 
         if (log_level >= 3) {          if (log_level >= 3) {
                 slot_log(s);                  slot_log(s);
                 log_puts(": using ");                  log_puts(": using ");
                 dev_log(s->opt->dev);  
                 log_puts(".");  
                 log_puts(s->opt->name);                  log_puts(s->opt->name);
                 log_puts(", mode = ");                  log_puts(", mode = ");
                 log_putx(mode);                  log_putx(mode);
Line 1839 
Line 1826 
                 slot_stop(s, 0);                  slot_stop(s, 0);
                 break;                  break;
         }          }
         dev_unref(s->opt->dev);          opt_unref(s->opt);
 }  }
   
 /*  /*
Line 1861 
Line 1848 
 }  }
   
 /*  /*
    * set device for this slot
    */
   void
   slot_setopt(struct slot *s, struct opt *o)
   {
           struct opt *t;
           struct dev *odev, *ndev;
           struct ctl *c;
   
           if (s->opt == NULL || s->opt == o)
                   return;
   
           if (log_level >= 2) {
                   slot_log(s);
                   log_puts(": moving to opt ");
                   log_puts(o->name);
                   log_puts("\n");
           }
   
           odev = s->opt->dev;
           if (s->ops != NULL) {
                   ndev = opt_ref(o);
                   if (ndev == NULL)
                           return;
   
                   if (!dev_iscompat(odev, ndev)) {
                           opt_unref(o);
                           return;
                   }
           }
   
           if (s->pstate == SLOT_RUN || s->pstate == SLOT_STOP)
                   slot_detach(s);
   
           t = s->opt;
           s->opt = o;
   
           c = ctl_find(CTL_SLOT_LEVEL, s, NULL);
           ctl_update(c);
   
           if (o->dev != t->dev) {
                   dev_midi_slotdesc(odev, s);
                   dev_midi_slotdesc(ndev, s);
                   dev_midi_vol(ndev, s);
           }
   
           if (s->pstate == SLOT_RUN || s->pstate == SLOT_STOP)
                   slot_attach(s);
   
           if (s->ops != NULL) {
                   opt_unref(t);
                   return;
           }
   }
   
   /*
  * attach the slot to the device (ie start playing & recording   * attach the slot to the device (ie start playing & recording
  */   */
 void  void
Line 2202 
Line 2245 
         }          }
         s->opt = o;          s->opt = o;
         s->self = 1 << i;          s->self = 1 << i;
         if (!dev_ref(o->dev))          if (!opt_ref(o))
                 return NULL;                  return NULL;
         s->ops = ops;          s->ops = ops;
         s->arg = arg;          s->arg = arg;
Line 2232 
Line 2275 
                         pc = &c->next;                          pc = &c->next;
         }          }
         s->ops = NULL;          s->ops = NULL;
         dev_unref(s->opt->dev);          opt_unref(s->opt);
 }  }
   
 int  int
Line 2243 
Line 2286 
         switch (c->scope) {          switch (c->scope) {
         case CTL_HW:          case CTL_HW:
         case CTL_DEV_MASTER:          case CTL_DEV_MASTER:
         case CTL_DEV_ALT:  
                 return (s->opt->dev == c->u.any.arg0);                  return (s->opt->dev == c->u.any.arg0);
           case CTL_OPT_DEV:
                   return (s->opt == c->u.any.arg0);
         case CTL_SLOT_LEVEL:          case CTL_SLOT_LEVEL:
                 return (s->opt->dev == c->u.slot_level.slot->opt->dev);                  return (s->opt->dev == c->u.slot_level.slot->opt->dev);
         default:          default:
Line 2271 
Line 2315 
 }  }
   
 void  void
   ctlslot_update(struct ctlslot *s)
   {
           struct ctl *c;
           unsigned int refs_mask;
   
           for (c = ctl_list; c != NULL; c = c->next) {
                   if (c->type == CTL_NONE)
                           continue;
                   refs_mask = ctlslot_visible(s, c) ? s->self : 0;
   
                   /* nothing to do if no visibility change */
                   if (((c->refs_mask & s->self) ^ refs_mask) == 0)
                           continue;
                   /* if control becomes visble */
                   if (refs_mask)
                           c->refs_mask |= s->self;
                   /* if control is hidden */
                   c->desc_mask |= s->self;
           }
   }
   
   void
 ctl_node_log(struct ctl_node *c)  ctl_node_log(struct ctl_node *c)
 {  {
         log_puts(c->name);          log_puts(c->name);
Line 2318 
Line 2384 
                 log_puts("dev_master:");                  log_puts("dev_master:");
                 log_puts(c->u.dev_master.dev->name);                  log_puts(c->u.dev_master.dev->name);
                 break;                  break;
         case CTL_DEV_ALT:  
                 log_puts("dev_alt:");  
                 log_puts(c->u.dev_alt.dev->name);  
                 log_putu(c->u.dev_alt.idx);  
                 break;  
         case CTL_SLOT_LEVEL:          case CTL_SLOT_LEVEL:
                 log_puts("slot_level:");                  log_puts("slot_level:");
                 log_puts(c->u.slot_level.slot->name);                  log_puts(c->u.slot_level.slot->name);
                 log_putu(c->u.slot_level.slot->unit);                  log_putu(c->u.slot_level.slot->unit);
                 break;                  break;
           case CTL_OPT_DEV:
                   log_puts("opt_dev:");
                   log_puts(c->u.opt_dev.opt->name);
                   log_puts("/");
                   log_puts(c->u.opt_dev.dev->name);
                   break;
         default:          default:
                 log_puts("unknown");                  log_puts("unknown");
         }          }
Line 2368 
Line 2435 
                 c->val_mask = ~0U;                  c->val_mask = ~0U;
                 c->curval = val;                  c->curval = val;
                 return 1;                  return 1;
         case CTL_DEV_ALT:  
                 dev_setalt (c->u.dev_alt.dev, c->u.dev_alt.idx);  
                 return 1;  
         case CTL_SLOT_LEVEL:          case CTL_SLOT_LEVEL:
                 slot_setvol(c->u.slot_level.slot, val);                  slot_setvol(c->u.slot_level.slot, val);
                 // XXX change dev_midi_vol() into slot_midi_vol()                  // XXX change dev_midi_vol() into slot_midi_vol()
Line 2378 
Line 2442 
                 c->val_mask = ~0U;                  c->val_mask = ~0U;
                 c->curval = val;                  c->curval = val;
                 return 1;                  return 1;
           case CTL_OPT_DEV:
                   c->u.opt_dev.opt->alt_first = c->u.opt_dev.dev;
                   opt_setdev(c->u.opt_dev.opt, c->u.opt_dev.dev);
                   return 1;
         default:          default:
                 if (log_level >= 2) {                  if (log_level >= 2) {
                         ctl_log(c);                          ctl_log(c);
Line 2429 
Line 2497 
         case CTL_HW:          case CTL_HW:
                 c->u.hw.addr = *(unsigned int *)arg1;                  c->u.hw.addr = *(unsigned int *)arg1;
                 break;                  break;
         case CTL_DEV_ALT:          case CTL_OPT_DEV:
                 c->u.dev_alt.idx = *(unsigned int *)arg1;                  c->u.any.arg1 = arg1;
                 break;                  break;
         default:          default:
                 c->u.any.arg1 = NULL;                  c->u.any.arg1 = NULL;
Line 2494 
Line 2562 
                 if (arg1 != NULL && c->u.hw.addr != *(unsigned int *)arg1)                  if (arg1 != NULL && c->u.hw.addr != *(unsigned int *)arg1)
                         return 0;                          return 0;
                 break;                  break;
         case CTL_DEV_ALT:          case CTL_OPT_DEV:
                 if (arg1 != NULL && c->u.dev_alt.idx != *(unsigned int *)arg1)                  if (arg1 != NULL && c->u.any.arg1 != arg1)
                         return 0;                          return 0;
                 break;                  break;
         }          }
Line 2600 
Line 2668 
                         s->ops->sync(s->arg);                          s->ops->sync(s->arg);
         }          }
 }  }
   

Legend:
Removed from v.1.102  
changed lines
  Added in v.1.103