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

Diff for /src/usr.bin/aucat/aucat.c between version 1.91 and 1.92

version 1.91, 2010/05/08 15:35:45 version 1.92, 2010/06/04 06:15:28
Line 108 
Line 108 
         cmin = strtol(optarg, &next, 10);          cmin = strtol(optarg, &next, 10);
         if (next == optarg || *next != ':')          if (next == optarg || *next != ':')
                 goto failed;                  goto failed;
         if (errno == ERANGE && (cmin == LONG_MIN || cmin == LONG_MAX))  
                 goto failed;  
         cmax = strtol(++next, &end, 10);          cmax = strtol(++next, &end, 10);
         if (end == next || *end != '\0')          if (end == next || *end != '\0')
                 goto failed;                  goto failed;
         if (errno == ERANGE && (cmax == LONG_MIN || cmax == LONG_MAX))  
                 goto failed;  
         if (cmin < 0 || cmax < cmin || cmax > NCHAN_MAX)          if (cmin < 0 || cmax < cmin || cmax > NCHAN_MAX)
                 goto failed;                  goto failed;
         par->cmin = cmin;          par->cmin = cmin;
Line 208 
Line 204 
 }  }
   
 /*  /*
  * Arguments of -i, -o and -s options are stored in a list.   * stream configuration
  */   */
 struct farg {  struct cfstr {
         SLIST_ENTRY(farg) entry;          SLIST_ENTRY(cfstr) entry;
         struct aparams ipar;    /* input (read) parameters */          unsigned mode;                  /* bitmap of MODE_XXX */
         struct aparams opar;    /* output (write) parameters */          struct aparams ipar;            /* input (read) parameters */
         unsigned vol;           /* last requested volume */          struct aparams opar;            /* output (write) parameters */
         char *name;             /* optarg pointer (no need to copy it */          unsigned vol;                   /* last requested volume */
         int hdr;                /* header format */          int hdr;                        /* header format */
         int xrun;               /* overrun/underrun policy */          int xrun;                       /* overrun/underrun policy */
         int mmc;                /* MMC mode */          int mmc;                        /* MMC mode */
         int join;               /* join/expand enabled */          int join;                       /* join/expand enabled */
         unsigned mode;          char *path;                     /* static path (no need to copy it) */
 };  };
   
 SLIST_HEAD(farglist, farg);  SLIST_HEAD(cfstrlist, cfstr);
   
 /*  /*
  * Add a farg entry to the given list, corresponding   * midi device (control stream)
  * to the given file name.  
  */   */
   struct cfmid {
           SLIST_ENTRY(cfmid) entry;
           char *path;                     /* static path (no need to copy it) */
   };
   
   SLIST_HEAD(cfmidlist, cfmid);
   
   /*
    * audio device configuration
    */
   struct cfdev {
           SLIST_ENTRY(cfdev) entry;
           struct cfstrlist ins;           /* files to play */
           struct cfstrlist outs;          /* files to record */
           struct cfstrlist opts;          /* subdevices to expose */
           struct cfmidlist mids;          /* midi ports to subscribe */
           struct aparams ipar;            /* input (read) parameters */
           struct aparams opar;            /* output (write) parameters */
           unsigned hold;          /* open immediately */
           unsigned bufsz;                 /* par.bufsz for sio device */
           unsigned round;                 /* par.round for sio device */
           unsigned mode;                  /* bitmap of MODE_XXX */
           char *path;                     /* static path (no need to copy it) */
   };
   
   SLIST_HEAD(cfdevlist, cfdev);
   
 void  void
 farg_add(struct farglist *list,  cfdev_add(struct cfdevlist *list, struct cfdev *templ, char *path)
     struct aparams *ipar, struct aparams *opar, unsigned vol,  
     int hdr, int xrun, int mmc, int join, unsigned mode, char *name)  
 {  {
         struct farg *fa;          struct cfdev *cd;
         size_t namelen;  
   
         fa = malloc(sizeof(struct farg));          cd = malloc(sizeof(struct cfdev));
         if (fa == NULL)          if (cd == NULL) {
                 err(1, "%s", name);                  perror("malloc");
                   abort();
           }
           *cd = *templ;
           cd->path = path;
           SLIST_INSERT_HEAD(list, cd, entry);
           SLIST_INIT(&templ->ins);
           SLIST_INIT(&templ->outs);
           SLIST_INIT(&templ->opts);
           SLIST_INIT(&templ->mids);
   }
   
         if (hdr == HDR_AUTO) {  void
                 if (name != NULL && (namelen = strlen(name)) >= 4 &&  cfstr_add(struct cfstrlist *list, struct cfstr *templ, char *path)
                     strcasecmp(name + namelen - 4, ".wav") == 0) {  {
                         fa->hdr = HDR_WAV;          size_t len;
                 } else {          struct cfstr *cs;
                         fa->hdr = HDR_RAW;          unsigned hdr;
                 }  
           if (strcmp(path, "-") == 0) {
                   path = NULL;
                   hdr = HDR_RAW;
           } else if (templ->hdr == HDR_AUTO) {
                   len = strlen(path);
                   if (len >= 4 && strcasecmp(path + len - 4, ".wav") == 0)
                           hdr = HDR_WAV;
                   else
                           hdr = HDR_RAW;
         } else          } else
                 fa->hdr = hdr;                  hdr = templ->hdr;
         if (mmc && xrun == XRUN_IGNORE)          cs = malloc(sizeof(struct cfstr));
                 xrun = XRUN_SYNC;          if (cs == NULL) {
         fa->xrun = xrun;                  perror("malloc");
         fa->ipar = *ipar;                  abort();
         fa->opar = *opar;          }
         fa->vol = vol;          *cs = *templ;
         fa->name = name;          cs->path = path;
         fa->mmc = mmc;          cs->hdr = hdr;
         fa->join = join;          SLIST_INSERT_HEAD(list, cs, entry);
         fa->mode = mode;  
         SLIST_INSERT_HEAD(list, fa, entry);  
 }  }
   
 void  void
   cfmid_add(struct cfmidlist *list, char *path)
   {
           struct cfmid *cm;
   
           cm = malloc(sizeof(struct cfmid));
           if (cm == NULL) {
                   perror("malloc");
                   abort();
           }
           cm->path = path;
           SLIST_INSERT_HEAD(list, cm, entry);
   }
   
   void
 setsig(void)  setsig(void)
 {  {
         struct sigaction sa;          struct sigaction sa;
Line 356 
Line 406 
 }  }
   
 void  void
 stopall(void)  
 {  
         struct file *f;  
   
   restart:  
         LIST_FOREACH(f, &file_list, entry) {  
                 /*  
                  * skip connected streams (handled by dev_close())  
                  */  
                 if (APROC_OK(dev_mix)) {  
                         if (f->rproc && aproc_depend(dev_mix, f->rproc))  
                                 continue;  
                         if (f->wproc && aproc_depend(f->wproc, dev_mix))  
                                 continue;  
                 }  
                 if (APROC_OK(dev_sub)) {  
                         if (f->rproc && aproc_depend(dev_sub, f->rproc))  
                                 continue;  
                         if (f->wproc && aproc_depend(f->wproc, dev_sub))  
                                 continue;  
                 }  
                 if (APROC_OK(dev_submon)) {  
                         if (f->rproc && aproc_depend(dev_submon, f->rproc))  
                                 continue;  
                         if (f->wproc && aproc_depend(f->wproc, dev_submon))  
                                 continue;  
                 }  
                 if (APROC_OK(dev_midi)) {  
                         if (f->rproc && aproc_depend(dev_midi, f->rproc))  
                                 continue;  
                         if (f->wproc && aproc_depend(f->wproc, dev_midi))  
                                 continue;  
                 }  
                 /*  
                  * kill anything else  
                  */  
                 file_close(f);  
                 goto restart;  
         }  
 }  
   
 void  
 aucat_usage(void)  aucat_usage(void)
 {  {
         (void)fputs("usage: " PROG_AUCAT " [-dlnu] [-b nframes] "          (void)fputs("usage: " PROG_AUCAT " [-dlnu] [-a flag] [-b nframes] "
             "[-C min:max] [-c min:max] [-e enc]\n\t"              "[-C min:max] [-c min:max] [-e enc]\n\t"
             "[-f device] [-h fmt] [-i file] [-j flag] [-m mode]"              "[-f device] [-h fmt] [-i file] [-j flag] [-m mode]"
             "[-o file] [-q device]\n\t"              "[-o file] [-q device]\n\t"
Line 413 
Line 421 
 int  int
 aucat_main(int argc, char **argv)  aucat_main(int argc, char **argv)
 {  {
         int c, u_flag, d_flag, l_flag, n_flag, hdr, xrun, unit;          struct cfdevlist cfdevs;
         struct farg *fa;          struct cfmid *cm;
         struct farglist ifiles, ofiles, sfiles, qfiles;          struct cfstr *cs;
         struct aparams ipar, opar, dipar, dopar;          struct cfdev *cd;
         char base[PATH_MAX], path[PATH_MAX], *file;          struct listen *listen = NULL;
         unsigned bufsz, round, mode;          int c, u_flag, d_flag, l_flag, n_flag, unit;
         char *devpath;          char base[PATH_MAX], path[PATH_MAX];
           unsigned mode, rate;
         const char *str;          const char *str;
         unsigned volctl;          char *legacy_path;
         int mmc, autostart, join;          int autostart, legacy;
           struct dev *d, *dnext;
           unsigned active;
   
         aparams_init(&ipar, 0, 1, 44100);          /*
         aparams_init(&opar, 0, 1, 44100);           * global options defaults
            */
           unit = -1;
         u_flag = 0;          u_flag = 0;
         d_flag = 0;          d_flag = 0;
         l_flag = 0;          l_flag = 0;
         n_flag = 0;          n_flag = 0;
         unit = -1;          legacy = 1;
         mmc = 0;          legacy_path = NULL;
         devpath = NULL;          SLIST_INIT(&cfdevs);
         SLIST_INIT(&ifiles);  
         SLIST_INIT(&ofiles);  
         SLIST_INIT(&sfiles);  
         SLIST_INIT(&qfiles);  
         hdr = HDR_AUTO;  
         xrun = XRUN_IGNORE;  
         volctl = MIDI_MAXCTL;  
         mode = MODE_PLAY | MODE_REC;  
         bufsz = 0;  
         round = 0;  
         autostart = 1;  
         join = 1;  
   
         while ((c = getopt(argc, argv, "dnb:c:C:e:r:h:x:v:i:o:f:m:luq:s:U:t:j:z:")) != -1) {          /*
            * default stream params
            */
           cs = malloc(sizeof(struct cfstr));
           if (cs == NULL) {
                   perror("malloc");
                   exit(1);
           }
           aparams_init(&cs->ipar, 0, 1, 44100);
           aparams_init(&cs->opar, 0, 1, 44100);
           cs->mmc = 0;
           cs->hdr = HDR_AUTO;
           cs->xrun = XRUN_IGNORE;
           cs->vol = MIDI_MAXCTL;
           cs->mode = MODE_PLAY | MODE_REC;
           cs->join = 1;
   
           /*
            * default device
            */
           cd = malloc(sizeof(struct cfdev));
           if (cd == NULL) {
                   perror("malloc");
                   exit(1);
           }
           aparams_init(&cd->ipar, 0, 1, 44100);
           aparams_init(&cd->opar, 0, 1, 44100);
           SLIST_INIT(&cd->ins);
           SLIST_INIT(&cd->outs);
           SLIST_INIT(&cd->opts);
           SLIST_INIT(&cd->mids);
           cd->path = NULL;
           cd->bufsz = 0;
           cd->round = 0;
           cd->hold = 1;
   
           while ((c = getopt(argc, argv, "a:dnb:c:C:e:r:h:x:v:i:o:f:m:luq:s:U:t:j:z:")) != -1) {
                 switch (c) {                  switch (c) {
                 case 'd':                  case 'd':
 #ifdef DEBUG  #ifdef DEBUG
Line 456 
Line 493 
                         d_flag = 1;                          d_flag = 1;
                         break;                          break;
                 case 'n':                  case 'n':
                           legacy = 0;
                         n_flag = 1;                          n_flag = 1;
                         break;                          break;
                   case 'u':
                           legacy = 0;
                           u_flag = 1;
                           break;
                   case 'U':
                           legacy = 0;
                           unit = strtonum(optarg, 0, MIDI_MAXCTL, &str);
                           if (str)
                                   errx(1, "%s: unit number is %s", optarg, str);
                           break;
                 case 'm':                  case 'm':
                         mode = opt_mode();                          legacy = 0;
                           cs->mode = opt_mode();
                           cd->mode = cs->mode;
                         break;                          break;
                 case 'h':                  case 'h':
                         hdr = opt_hdr();                          legacy = 0;
                           cs->hdr = opt_hdr();
                         break;                          break;
                 case 'x':                  case 'x':
                         xrun = opt_xrun();                          legacy = 0;
                           cs->xrun = opt_xrun();
                         break;                          break;
                 case 'j':                  case 'j':
                         join = opt_onoff();                          legacy = 0;
                           cs->join = opt_onoff();
                         break;                          break;
                 case 't':                  case 't':
                         mmc = opt_mmc();                          legacy = 0;
                         if (mmc)                          cs->mmc = opt_mmc();
                                 autostart = 0;  
                         break;                          break;
                 case 'c':                  case 'c':
                         opt_ch(&ipar);                          legacy = 0;
                           opt_ch(&cs->ipar);
                           cd->opar.cmin = cs->ipar.cmin;
                           cd->opar.cmax = cs->ipar.cmax;
                         break;                          break;
                 case 'C':                  case 'C':
                         opt_ch(&opar);                          legacy = 0;
                           opt_ch(&cs->opar);
                           cd->ipar.cmin = cs->opar.cmin;
                           cd->ipar.cmax = cs->opar.cmax;
                         break;                          break;
                 case 'e':                  case 'e':
                         opt_enc(&ipar);                          legacy = 0;
                         aparams_copyenc(&opar, &ipar);                          opt_enc(&cs->ipar);
                           aparams_copyenc(&cs->opar, &cs->ipar);
                         break;                          break;
                 case 'r':                  case 'r':
                         ipar.rate = strtonum(optarg, RATE_MIN, RATE_MAX, &str);                          legacy = 0;
                           rate = strtonum(optarg, RATE_MIN, RATE_MAX, &str);
                         if (str)                          if (str)
                                 errx(1, "%s: rate is %s", optarg, str);                                  errx(1, "%s: rate is %s", optarg, str);
                         opar.rate = ipar.rate;                          cs->opar.rate = cs->ipar.rate = rate;
                           cd->ipar.rate = cd->opar.rate = rate;
                         break;                          break;
                 case 'v':                  case 'v':
                         volctl = strtonum(optarg, 0, MIDI_MAXCTL, &str);                          legacy = 0;
                           cs->vol = strtonum(optarg, 0, MIDI_MAXCTL, &str);
                         if (str)                          if (str)
                                 errx(1, "%s: volume is %s", optarg, str);                                  errx(1, "%s: volume is %s", optarg, str);
                         break;                          break;
                 case 'i':                  case 'i':
                         file = optarg;                          legacy = 0;
                         if (strcmp(file, "-") == 0)                          cfstr_add(&cd->ins, cs, optarg);
                                 file = NULL;  
                         farg_add(&ifiles, &ipar, &opar, volctl,  
                             hdr, xrun, mmc, join, mode & MODE_PLAY, file);  
                         break;                          break;
                 case 'o':                  case 'o':
                         file = optarg;                          legacy = 0;
                         if (strcmp(file, "-") == 0)                          cfstr_add(&cd->outs, cs, optarg);
                                 file = NULL;  
                         farg_add(&ofiles, &ipar, &opar, volctl,  
                             hdr, xrun, mmc, join, mode & MODE_RECMASK, file);  
                         break;                          break;
                 case 's':                  case 's':
                         farg_add(&sfiles, &ipar, &opar, volctl,                          legacy = 0;
                             hdr, xrun, mmc, join, mode, optarg);                          cfstr_add(&cd->opts, cs, optarg);
                         break;                          break;
                   case 'a':
                           legacy = 0;
                           cd->hold = opt_onoff();
                           break;
                 case 'q':                  case 'q':
                         farg_add(&qfiles, &aparams_none, &aparams_none,                          legacy = 0;
                             0, HDR_RAW, 0, 0, 0, 0, optarg);                          cfmid_add(&cd->mids, optarg);
                         break;                          break;
                 case 'f':  
                         if (devpath)  
                                 err(1, "only one -f allowed");  
                         devpath = optarg;  
                         dipar = opar;  
                         dopar = ipar;  
                         break;  
                 case 'l':  
                         l_flag = 1;  
                         autostart = 0;  
                         break;  
                 case 'u':  
                         u_flag = 1;  
                         break;  
                 case 'b':                  case 'b':
                         bufsz = strtonum(optarg, 1, RATE_MAX * 5, &str);                          legacy = 0;
                           cd->bufsz = strtonum(optarg, 1, RATE_MAX * 5, &str);
                         if (str)                          if (str)
                                 errx(1, "%s: buffer size is %s", optarg, str);                                  errx(1, "%s: buffer size is %s", optarg, str);
                         break;                          break;
                 case 'U':  
                         unit = strtonum(optarg, 0, MIDI_MAXCTL, &str);  
                         if (str)  
                                 errx(1, "%s: device number is %s", optarg, str);  
                         break;  
                 case 'z':                  case 'z':
                         round = strtonum(optarg, 1, SHRT_MAX, &str);                          legacy = 0;
                           cd->round = strtonum(optarg, 1, SHRT_MAX, &str);
                         if (str)                          if (str)
                                 errx(1, "%s: block size is %s", optarg, str);                                  errx(1, "%s: block size is %s", optarg, str);
                         break;                          break;
                   case 'f':
                           legacy = 0;
                           legacy_path = optarg;
                           cfdev_add(&cfdevs, cd, optarg);
                           break;
                   case 'l':
                           legacy = 0;
                           l_flag = 1;
                           autostart = 0;
                           break;
                 default:                  default:
                         aucat_usage();                          aucat_usage();
                         exit(1);                          exit(1);
Line 555 
Line 608 
         argc -= optind;          argc -= optind;
         argv += optind;          argv += optind;
   
         if (!devpath) {  #ifdef DEBUG
                 dopar = ipar;          if (debug_level == 0)
                 dipar = opar;                  debug_level = 1;
         }  #endif
         if (!l_flag && SLIST_EMPTY(&ifiles) && SLIST_EMPTY(&ofiles)) {          if (argc > 0) {
                 if (argc > 0) {                  if (!legacy) {
                         /*  
                          * Legacy mode: if no -i or -o options are provided, and  
                          * there are arguments then assume the arguments are files  
                          * to play.  
                          */  
                         for (c = 0; c < argc; c++)  
                                 if (legacy_play(devpath, argv[c]) != 0) {  
                                         errx(1, "%s: could not play\n", argv[c]);  
                                 }  
                         exit(0);  
                 } else {  
                         aucat_usage();                          aucat_usage();
                         exit(1);                          exit(1);
                 }                  }
                   for (c = 0; c < argc; c++)
                           if (legacy_play(legacy_path, argv[c]) != 0) {
                                   errx(1, "%s: could not play\n", argv[c]);
                           }
                   exit(0);
         }          }
   
         if (!l_flag && (!SLIST_EMPTY(&sfiles) || unit >= 0))          if (!l_flag && unit >= 0)
                 errx(1, "can't use -s or -U without -l");                  errx(1, "can't use -U without -l");
         if (l_flag && (!SLIST_EMPTY(&ofiles) || !SLIST_EMPTY(&ifiles)))  
                 errx(1, "can't use -l, and -s with -o or -i");  
         if (n_flag) {          if (n_flag) {
                 if (devpath != NULL || !SLIST_EMPTY(&qfiles) ||                  if (!SLIST_EMPTY(&cfdevs) || l_flag ||
                     l_flag || !autostart)                      !SLIST_EMPTY(&cd->opts) || !SLIST_EMPTY(&cd->mids))
                         errx(1, "can't use -n with -f, -q, -t or -l");                          errx(1, "can't use -n with -l, -f, -q or -s");
                 if (SLIST_EMPTY(&ifiles) || SLIST_EMPTY(&ofiles))                  if (SLIST_EMPTY(&cd->ins) || SLIST_EMPTY(&cd->outs))
                         errx(1, "both -i and -o are required with -n");                          errx(1, "both -i and -o are required with -n");
         }          }
   
         /*          /*
            * if no device is given, add the default one
            */
           if (SLIST_EMPTY(&cfdevs)) {
                   if (!cd->hold)
                           errx(1, "-a not compatible with default device");
                   cfdev_add(&cfdevs, cd, "default");
           }
   
           /*
          * If there are no sockets paths provided use the default.           * If there are no sockets paths provided use the default.
          */           */
         if (l_flag && SLIST_EMPTY(&sfiles)) {          if (l_flag) {
                 farg_add(&sfiles, &ipar, &opar,                  SLIST_FOREACH(cd, &cfdevs, entry) {
                     volctl, HDR_RAW, XRUN_IGNORE, mmc, join, mode, DEFAULT_OPT);                          if (!SLIST_EMPTY(&cd->opts))
                                   continue;
                           cfstr_add(&cd->opts, cs, DEFAULT_OPT);
                           break;
                   }
         }          }
   
         /*          /*
Line 602 
Line 660 
          * inputs and outputs and find the maximum sample rate and channel           * inputs and outputs and find the maximum sample rate and channel
          * number.           * number.
          */           */
         mode = 0;          SLIST_FOREACH(cd, &cfdevs, entry) {
         aparams_init(&dipar, dipar.cmin, dipar.cmax, dipar.rate);                  mode = 0;
         aparams_init(&dopar, dopar.cmin, dopar.cmax, dopar.rate);                  SLIST_FOREACH(cs, &cd->ins, entry) {
         SLIST_FOREACH(fa, &ifiles, entry) {                          if (cs->mode == 0)
                 if (fa->mode == 0)                                  errx(1, "%s: not in play mode", cs->path);
                         errx(1, "%s: not in play mode", fa->name);                          mode |= (cs->mode & MODE_PLAY);
                 mode |= fa->mode;                          if (!u_flag)
                 if (!u_flag)                                  aparams_grow(&cd->opar, &cs->ipar);
                         aparams_grow(&dopar, &fa->ipar);  
         }  
         SLIST_FOREACH(fa, &ofiles, entry) {  
                 if (fa->mode == 0)  
                         errx(1, "%s: not in rec/mon mode", fa->name);  
                 if ((fa->mode & MODE_REC) && (fa->mode & MODE_MON))  
                         errx(1, "%s: can't record and monitor", fa->name);  
                 mode |= fa->mode;  
                 if (!u_flag)  
                         aparams_grow(&dipar, &fa->opar);  
         }  
         SLIST_FOREACH(fa, &sfiles, entry) {  
                 if ((fa->mode & MODE_REC) && (fa->mode & MODE_MON))  
                         errx(1, "%s: can't record and monitor", fa->name);  
                 mode |= fa->mode;  
                 if (!u_flag) {  
                         aparams_grow(&dopar, &fa->ipar);  
                         aparams_grow(&dipar, &fa->opar);  
                 }                  }
                   SLIST_FOREACH(cs, &cd->outs, entry) {
                           if (cs->mode == 0)
                                   errx(1, "%s: not in rec/mon mode", cs->path);
                           if ((cs->mode & MODE_REC) && (cs->mode & MODE_MON))
                                   errx(1, "%s: can't rec and mon", cs->path);
                           mode |= (cs->mode & MODE_RECMASK);
                           if (!u_flag)
                                   aparams_grow(&cd->ipar, &cs->opar);
                   }
                   SLIST_FOREACH(cs, &cd->opts, entry) {
                           if ((cs->mode & MODE_REC) && (cs->mode & MODE_MON))
                                   errx(1, "%s: can't rec and mon", cs->path);
                           mode |= (cs->mode & (MODE_RECMASK | MODE_PLAY));
                           if (!u_flag) {
                                   aparams_grow(&cd->opar, &cs->ipar);
                                   aparams_grow(&cd->ipar, &cs->opar);
                           }
                   }
                   if (l_flag && SLIST_EMPTY(&cd->opts))
                           errx(1, "%s: no subdevs for this device", cd->path);
                   if (!l_flag && SLIST_EMPTY(&cd->ins) && SLIST_EMPTY(&cd->outs))
                           errx(1, "%s: no files for this device", cd->path);
                   if (n_flag && (mode & MODE_MON))
                           errx(1, "monitoring not allowed in loopback mode");
                   if ((mode & MODE_MON) && !(mode & MODE_PLAY))
                           errx(1, "no playback stream to monitor");
                   rate = (mode & MODE_REC) ? cd->ipar.rate : cd->opar.rate;
                   if (!cd->round)
                           cd->round = rate / 15;
                   if (!cd->bufsz)
                           cd->bufsz = rate / 15 * 4;
                   cd->mode = mode;
         }          }
   
         if (!round)  
                 round = ((mode & MODE_REC) ? dipar.rate : dopar.rate) / 15;  
         if (!bufsz)  
                 bufsz = ((mode & MODE_REC) ? dipar.rate : dopar.rate) * 4 / 15;  
   
         if (l_flag) {          if (l_flag) {
                 getbasepath(base, sizeof(base));                  getbasepath(base, sizeof(base));
                 if (unit < 0)                  if (unit < 0)
Line 645 
Line 712 
         filelist_init();          filelist_init();
   
         /*          /*
          * Open the device           * Open devices
          */           */
         if (n_flag) {          while (!SLIST_EMPTY(&cfdevs)) {
                 if (mode & MODE_MON)                  cd = SLIST_FIRST(&cfdevs);
                         errx(1, "monitoring not allowed in loopback mode");                  SLIST_REMOVE_HEAD(&cfdevs, entry);
                 dev_init_loop(&dipar, &dopar, bufsz);  
         } else {  
                 if (l_flag)  
                         dev_reqprime = 1;  
                 if ((mode & MODE_MON) && !(mode & MODE_PLAY))  
                         errx(1, "no playback stream to monitor");  
                 dev_init_sio(devpath, mode, &dipar, &dopar, bufsz, round);  
         }  
         if (!dev_ref()) {  
                 errx(1, "%s: can't open device",  
                     devpath ? devpath : "<default>");  
         }  
   
         /*                  if (n_flag) {
          * Create buffers for all input and output pipes.                          d = dev_new_loop(&cd->ipar, &cd->opar, cd->bufsz);
          */                  } else {
         while (!SLIST_EMPTY(&qfiles)) {                          d = dev_new_sio(cd->path, cd->mode,
                 fa = SLIST_FIRST(&qfiles);                              &cd->ipar, &cd->opar, cd->bufsz, cd->round,
                 SLIST_REMOVE_HEAD(&qfiles, entry);                              cd->hold, l_flag);
                 if (!dev_thruadd(fa->name, 1, 1))                  }
                         errx(1, "%s: can't open device", fa->name);                  if (d == NULL)
                 free(fa);                          errx(1, "%s: can't open device", cd->path);
   
                   /*
                    * register midi devices
                    */
                   while (!SLIST_EMPTY(&cd->mids)) {
                           cm = SLIST_FIRST(&cd->mids);
                           SLIST_REMOVE_HEAD(&cd->mids, entry);
                           if (!dev_thruadd(d, cm->path, 1, 1))
                                   errx(1, "%s: can't open device", cm->path);
                           free(cm);
                   }
   
                   /*
                    * register files
                    */
                   autostart = 0;
                   while (!SLIST_EMPTY(&cd->ins)) {
                           cs = SLIST_FIRST(&cd->ins);
                           SLIST_REMOVE_HEAD(&cd->ins, entry);
                           if (!cs->mmc)
                                   autostart = 1;
                           if (!wav_new_in(&wav_ops, d, cs->mode & MODE_PLAY,
                                   cs->path, cs->hdr, &cs->ipar, cs->xrun,
                                   cs->vol, cs->mmc, cs->join))
                                   exit(1);
                           free(cs);
                   }
                   while (!SLIST_EMPTY(&cd->outs)) {
                           cs = SLIST_FIRST(&cd->outs);
                           SLIST_REMOVE_HEAD(&cd->outs, entry);
                           if (!cs->mmc)
                                   autostart = 1;
                           if (!wav_new_out(&wav_ops, d, cs->mode & MODE_RECMASK,
                                   cs->path, cs->hdr, &cs->opar, cs->xrun,
                                   cs->mmc, cs->join))
                                   exit(1);
                           free(cs);
                   }
                   while (!SLIST_EMPTY(&cd->opts)) {
                           cs = SLIST_FIRST(&cd->opts);
                           SLIST_REMOVE_HEAD(&cd->opts, entry);
                           opt_new(cs->path, d, &cs->opar, &cs->ipar,
                               MIDI_TO_ADATA(cs->vol), cs->mmc,
                               cs->join, cs->mode);
                           free(cs);
                   }
                   free(cd);
                   if (autostart) {
                           /*
                            * inject artificial mmc start
                            */
                           ctl_start(d->midi);
                   }
         }          }
         while (!SLIST_EMPTY(&ifiles)) {  
                 fa = SLIST_FIRST(&ifiles);  
                 SLIST_REMOVE_HEAD(&ifiles, entry);  
                 if (!wav_new_in(&wav_ops, fa->mode, fa->name,  
                         fa->hdr, &fa->ipar, fa->xrun, fa->vol, fa->mmc,  
                         fa->join))  
                         exit(1);  
                 free(fa);  
         }  
         while (!SLIST_EMPTY(&ofiles)) {  
                 fa = SLIST_FIRST(&ofiles);  
                 SLIST_REMOVE_HEAD(&ofiles, entry);  
                 if (!wav_new_out(&wav_ops, fa->mode, fa->name,  
                         fa->hdr, &fa->opar, fa->xrun, fa->mmc,  
                         fa->join))  
                 free(fa);  
         }  
         while (!SLIST_EMPTY(&sfiles)) {  
                 fa = SLIST_FIRST(&sfiles);  
                 SLIST_REMOVE_HEAD(&sfiles, entry);  
                 opt_new(fa->name, &fa->opar, &fa->ipar,  
                     MIDI_TO_ADATA(fa->vol), fa->mmc, fa->join, fa->mode);  
                 free(fa);  
         }  
         if (l_flag) {          if (l_flag) {
                 snprintf(path, sizeof(path), "%s/%s%u", base,                  snprintf(path, sizeof(path), "%s/%s%u", base,
                     DEFAULT_SOFTAUDIO, unit);                      DEFAULT_SOFTAUDIO, unit);
                 listen_new(&listen_ops, path);                  listen = listen_new(&listen_ops, path);
                   if (listen == 0)
                           exit(1);
                 if (geteuid() == 0)                  if (geteuid() == 0)
                         privdrop();                          privdrop();
                 if (!d_flag && daemon(0, 0) < 0)                  if (!d_flag && daemon(0, 0) < 0)
                         err(1, "daemon");                          err(1, "daemon");
         }          }
         if (autostart) {  
                 /*  
                  * inject artificial mmc start  
                  */  
                 ctl_start(dev_midi);  
         }  
   
         /*          /*
          * Loop, start audio.           * Loop, start audio.
Line 719 
Line 799 
         for (;;) {          for (;;) {
                 if (quit_flag)                  if (quit_flag)
                         break;                          break;
                 if (!dev_run())                  active = 0;
                   for (d = dev_list; d != NULL; d = dnext) {
                           dnext = d->next;
                           if (!dev_run(d))
                                   goto fatal;
                           if (!ctl_idle(d->midi))
                                   active = 1;
                   }
                   if (dev_list == NULL)
                         break;                          break;
                 if (!l_flag && ctl_idle(dev_midi))                  if (!l_flag && !active)
                         break;                          break;
                 if (!file_poll())                  if (!file_poll())
                         break;                          break;
         }          }
         dev_unref();    fatal:
         stopall();          if (l_flag)
         dev_done();                  file_close(&listen->file);
           while (dev_list)
                   dev_del(dev_list);
   
         /*          /*
          * give a chance to drain           * give a chance to drain
          */           */
Line 750 
Line 841 
             "[-i file] [-o file] [-q device] [-U unit]\n",              "[-i file] [-o file] [-q device] [-U unit]\n",
             stderr);              stderr);
 }  }
   
 int  int
 midicat_main(int argc, char **argv)  midicat_main(int argc, char **argv)
 {  {
           struct cfmidlist mids, ins, outs;
           struct cfmid *cm;
           struct listen *listen = NULL;
         int c, d_flag, l_flag, unit, fd;          int c, d_flag, l_flag, unit, fd;
         struct farglist dfiles, ifiles, ofiles;  
         char base[PATH_MAX], path[PATH_MAX];          char base[PATH_MAX], path[PATH_MAX];
         struct farg *fa;  
         struct file *stdx;          struct file *stdx;
         struct aproc *p;          struct aproc *p;
         struct abuf *buf;          struct abuf *buf;
         const char *str;          const char *str;
           struct dev *d;
   
           /*
            * global options defaults
            */
           unit = -1;
         d_flag = 0;          d_flag = 0;
         l_flag = 0;          l_flag = 0;
         unit = -1;          SLIST_INIT(&mids);
         SLIST_INIT(&dfiles);          SLIST_INIT(&ins);
         SLIST_INIT(&ifiles);          SLIST_INIT(&outs);
         SLIST_INIT(&ofiles);  
   
         while ((c = getopt(argc, argv, "di:o:lf:q:U:")) != -1) {          while ((c = getopt(argc, argv, "di:o:lf:q:U:")) != -1) {
                 switch (c) {                  switch (c) {
Line 779 
Line 876 
                         d_flag = 1;                          d_flag = 1;
                         break;                          break;
                 case 'i':                  case 'i':
                         farg_add(&ifiles, &aparams_none, &aparams_none,                          cfmid_add(&ins, optarg);
                             0, HDR_RAW, 0, 0, 0, 0, optarg);  
                         break;                          break;
                 case 'o':                  case 'o':
                         farg_add(&ofiles, &aparams_none, &aparams_none,                          cfmid_add(&outs, optarg);
                             0, HDR_RAW, 0, 0, 0, 0, optarg);  
                         break;                          break;
                         /* XXX: backward compat, remove this */                          /* XXX: backward compat, remove this */
                 case 'f':                  case 'f':
                 case 'q':                  case 'q':
                         farg_add(&dfiles, &aparams_none, &aparams_none,                          cfmid_add(&mids, optarg);
                             0, HDR_RAW, 0, 0, 0, 0, optarg);  
                         break;                          break;
                 case 'l':                  case 'l':
                         l_flag = 1;                          l_flag = 1;
Line 798 
Line 892 
                 case 'U':                  case 'U':
                         unit = strtonum(optarg, 0, MIDI_MAXCTL, &str);                          unit = strtonum(optarg, 0, MIDI_MAXCTL, &str);
                         if (str)                          if (str)
                                 errx(1, "%s: device number is %s", optarg, str);                                  errx(1, "%s: unit number is %s", optarg, str);
                         break;                          break;
                 default:                  default:
                         midicat_usage();                          midicat_usage();
Line 808 
Line 902 
         argc -= optind;          argc -= optind;
         argv += optind;          argv += optind;
   
         if (argc > 0 || (SLIST_EMPTY(&ifiles) && SLIST_EMPTY(&ofiles) &&          if (argc > 0 || (SLIST_EMPTY(&ins) && SLIST_EMPTY(&outs) && !l_flag)) {
             !l_flag)) {  
                 midicat_usage();                  midicat_usage();
                 exit(1);                  exit(1);
         }          }
         if (!l_flag && unit >= 0)          if (!l_flag && unit >= 0)
                 errx(1, "can't use -U without -l");                  errx(1, "can't use -U without -l");
         if (l_flag) {          if (l_flag) {
                 if (!SLIST_EMPTY(&ifiles) || !SLIST_EMPTY(&ofiles))                  if (!SLIST_EMPTY(&ins) || !SLIST_EMPTY(&outs))
                         errx(1, "can't use -i or -o with -l");                          errx(1, "can't use -i or -o with -l");
                 getbasepath(base, sizeof(path));                  getbasepath(base, sizeof(path));
                 if (unit < 0)                  if (unit < 0)
Line 825 
Line 918 
         setsig();          setsig();
         filelist_init();          filelist_init();
   
         dev_init_thru();          d = dev_new_thru();
         if (0 && !dev_ref())          if (!dev_ref(d))
                 errx(1, "couldn't opem midi thru box");                  errx(1, "couldn't open midi thru box");
         if (!l_flag && APROC_OK(dev_midi))          if (!l_flag && APROC_OK(d->midi))
                 dev_midi->flags |= APROC_QUIT;                  d->midi->flags |= APROC_QUIT;
         if ((!SLIST_EMPTY(&ifiles) || !SLIST_EMPTY(&ofiles)) &&          if ((!SLIST_EMPTY(&ins) || !SLIST_EMPTY(&outs)) && SLIST_EMPTY(&mids)) {
             SLIST_EMPTY(&dfiles)) {                  cfmid_add(&mids, "default");
                 farg_add(&dfiles, &aparams_none, &aparams_none,  
                     0, HDR_RAW, 0, 0, 0, 0, NULL);  
         }          }
         while (!SLIST_EMPTY(&dfiles)) {          while (!SLIST_EMPTY(&mids)) {
                 fa = SLIST_FIRST(&dfiles);                  cm = SLIST_FIRST(&mids);
                 SLIST_REMOVE_HEAD(&dfiles, entry);                  SLIST_REMOVE_HEAD(&mids, entry);
                 if (!dev_thruadd(fa->name,                  if (!dev_thruadd(d, cm->path,
                         !SLIST_EMPTY(&ofiles) || l_flag,                          !SLIST_EMPTY(&ins) || l_flag,
                         !SLIST_EMPTY(&ifiles) || l_flag)) {                          !SLIST_EMPTY(&outs) || l_flag)) {
                         errx(1, "%s: can't open device",                          errx(1, "%s: can't open device", cm->path);
                             fa->name ? fa->name : "<default>");  
                 }                  }
                 free(fa);                  free(cm);
         }          }
         if (l_flag) {          if (l_flag) {
                   opt_new(DEFAULT_OPT, d, NULL, NULL, 0, 0, 0, 0);
                 snprintf(path, sizeof(path), "%s/%s%u", base,                  snprintf(path, sizeof(path), "%s/%s%u", base,
                     DEFAULT_MIDITHRU, unit);                      DEFAULT_MIDITHRU, unit);
                 listen_new(&listen_ops, path);                  listen = listen_new(&listen_ops, path);
                 if (geteuid() == 0)                  if (geteuid() == 0)
                         privdrop();                          privdrop();
                 if (!d_flag && daemon(0, 0) < 0)                  if (!d_flag && daemon(0, 0) < 0)
                         err(1, "daemon");                          err(1, "daemon");
         }          }
         while (!SLIST_EMPTY(&ifiles)) {          while (!SLIST_EMPTY(&ins)) {
                 fa = SLIST_FIRST(&ifiles);                  cm = SLIST_FIRST(&ins);
                 SLIST_REMOVE_HEAD(&ifiles, entry);                  SLIST_REMOVE_HEAD(&ins, entry);
                 if (strcmp(fa->name, "-") == 0) {                  if (strcmp(cm->path, "-") == 0) {
                         fd = STDIN_FILENO;                          fd = STDIN_FILENO;
                         if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)                          if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
                                 warn("stdin");                                  warn("stdin");
                 } else {                  } else {
                         fd = open(fa->name, O_RDONLY | O_NONBLOCK, 0666);                          fd = open(cm->path, O_RDONLY | O_NONBLOCK, 0666);
                         if (fd < 0)                          if (fd < 0)
                                 err(1, "%s", fa->name);                                  err(1, "%s", cm->path);
                 }                  }
                 stdx = (struct file *)pipe_new(&pipe_ops, fd, fa->name);                  stdx = (struct file *)pipe_new(&pipe_ops, fd, cm->path);
                 p = rfile_new(stdx);                  p = rfile_new(stdx);
                 buf = abuf_new(MIDI_BUFSZ, &aparams_none);                  buf = abuf_new(MIDI_BUFSZ, &aparams_none);
                 aproc_setout(p, buf);                  aproc_setout(p, buf);
                 dev_midiattach(buf, NULL);                  dev_midiattach(d, buf, NULL);
                 free(fa);                  free(cm);
         }          }
         while (!SLIST_EMPTY(&ofiles)) {          while (!SLIST_EMPTY(&outs)) {
                 fa = SLIST_FIRST(&ofiles);                  cm = SLIST_FIRST(&outs);
                 SLIST_REMOVE_HEAD(&ofiles, entry);                  SLIST_REMOVE_HEAD(&outs, entry);
                 if (strcmp(fa->name, "-") == 0) {                  if (strcmp(cm->path, "-") == 0) {
                         fd = STDOUT_FILENO;                          fd = STDOUT_FILENO;
                         if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)                          if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
                                 warn("stdout");                                  warn("stdout");
                 } else {                  } else {
                         fd = open(fa->name,                          fd = open(cm->path,
                             O_WRONLY | O_TRUNC | O_CREAT | O_NONBLOCK, 0666);                              O_WRONLY | O_TRUNC | O_CREAT | O_NONBLOCK, 0666);
                         if (fd < 0)                          if (fd < 0)
                                 err(1, "%s", fa->name);                                  err(1, "%s", cm->path);
                 }                  }
                 stdx = (struct file *)pipe_new(&pipe_ops, fd, fa->name);                  stdx = (struct file *)pipe_new(&pipe_ops, fd, cm->path);
                 p = wfile_new(stdx);                  p = wfile_new(stdx);
                 buf = abuf_new(MIDI_BUFSZ, &aparams_none);                  buf = abuf_new(MIDI_BUFSZ, &aparams_none);
                 aproc_setin(p, buf);                  aproc_setin(p, buf);
                 dev_midiattach(NULL, buf);                  dev_midiattach(d, NULL, buf);
                 free(fa);                  free(cm);
         }          }
         /*          /*
          * loop, start processing           * loop, start processing
Line 900 
Line 991 
         for (;;) {          for (;;) {
                 if (quit_flag)                  if (quit_flag)
                         break;                          break;
                 if (!dev_run())                  if (!dev_run(d))
                         break;                          break;
                 if (!file_poll())                  if (!file_poll())
                         break;                          break;
         }          }
         stopall();          if (l_flag)
         if (0)                  file_close(&listen->file);
                 dev_unref();          dev_unref(d);
         dev_done();          dev_del(d);
         /*          /*
          * drain           * drain
          */           */
Line 922 
Line 1013 
         unsetsig();          unsetsig();
         return 0;          return 0;
 }  }
   
   
 int  int
 main(int argc, char **argv)  main(int argc, char **argv)

Legend:
Removed from v.1.91  
changed lines
  Added in v.1.92