1 /*
2 * Copyright (c) 2008-2014 Alexandre Ratchov <alex@caoua.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <err.h>
18 #include <errno.h>
19 #include <limits.h>
20 #include <poll.h>
21 #include <signal.h>
22 #include <sndio.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include "abuf.h"
28 #include "afile.h"
29 #include "dsp.h"
30 #include "sysex.h"
31 #include "utils.h"
32
33 /*
34 * masks to extract command and channel of status byte
35 */
36 #define MIDI_CMDMASK 0xf0
37 #define MIDI_CHANMASK 0x0f
38
39 /*
40 * MIDI status bytes of voice messages
41 */
42 #define MIDI_NOFF 0x80 /* note off */
43 #define MIDI_NON 0x90 /* note on */
44 #define MIDI_KAT 0xa0 /* key after touch */
45 #define MIDI_CTL 0xb0 /* controller */
46 #define MIDI_PC 0xc0 /* program change */
47 #define MIDI_CAT 0xd0 /* channel after touch */
48 #define MIDI_BEND 0xe0 /* pitch bend */
49 #define MIDI_ACK 0xfe /* active sensing message */
50
51 /*
52 * MIDI controller numbers
53 */
54 #define MIDI_CTL_VOL 7
55
56 /*
57 * Max coarse value
58 */
59 #define MIDI_MAXCTL 127
60
61 /*
62 * MIDI status bytes for sysex
63 */
64 #define MIDI_SX_START 0xf0
65 #define MIDI_SX_STOP 0xf7
66
67 /*
68 * audio device defaults
69 */
70 #define DEFAULT_RATE 48000
71 #define DEFAULT_BUFSZ_MS 200
72
73 struct slot {
74 struct slot *next; /* next on the play/rec list */
75 int vol; /* dynamic range */
76 int volctl; /* volume in the 0..127 range */
77 struct abuf buf; /* file i/o buffer */
78 int bpf; /* bytes per frame */
79 int imin, imax, omin, omax; /* channel mapping ranges */
80 struct cmap cmap; /* channel mapper state */
81 struct resamp resamp; /* resampler state */
82 struct conv conv; /* format encoder state */
83 int join; /* channel join factor */
84 int expand; /* channel expand factor */
85 void *resampbuf, *convbuf; /* conversion tmp buffers */
86 int dup; /* compat with legacy -j option */
87 int round; /* slot-side block size */
88 int mode; /* MODE_{PLAY,REC} */
89 #define SLOT_CFG 0 /* buffers not allocated yet */
90 #define SLOT_INIT 1 /* not trying to do anything */
91 #define SLOT_RUN 2 /* playing/recording */
92 #define SLOT_STOP 3 /* draining (play only) */
93 int pstate; /* one of above */
94 long long skip; /* frames to skip at the beginning */
95 long long pos; /* start position (at device rate) */
96 struct afile afile; /* file desc & friends */
97 };
98
99 /*
100 * device properties
101 */
102 unsigned int dev_mode; /* bitmap of SIO_{PLAY,REC} */
103 unsigned int dev_bufsz; /* device buffer size */
104 unsigned int dev_round; /* device block size */
105 int dev_rate; /* device sample rate (Hz) */
106 unsigned int dev_pchan, dev_rchan; /* play & rec channels count */
107 adata_t *dev_pbuf, *dev_rbuf; /* play & rec buffers */
108 struct aparams dev_par; /* device sample format */
109 struct conv dev_enc, dev_dec; /* format conversions */
110 unsigned char *dev_encbuf, *dev_decbuf; /* buf for format conversions */
111 long long dev_pos; /* last MMC position in frames */
112 #define DEV_STOP 0 /* stopped */
113 #define DEV_START 1 /* started */
114 unsigned int dev_pstate; /* one of above */
115 char *dev_name; /* device sndio(7) name */
116 char *dev_port; /* control port sndio(7) name */
117 struct sio_hdl *dev_sh; /* device handle */
118 struct mio_hdl *dev_mh; /* MIDI control port handle */
119 unsigned int dev_volctl = MIDI_MAXCTL; /* master volume */
120
121 /*
122 * MIDI parser state
123 */
124 #define MIDI_MSGMAX 32 /* max size of MIDI msg */
125 unsigned char dev_msg[MIDI_MSGMAX]; /* parsed input message */
126 unsigned int dev_mst; /* input MIDI running status */
127 unsigned int dev_mused; /* bytes used in ``msg'' */
128 unsigned int dev_midx; /* current ``msg'' size */
129 unsigned int dev_mlen; /* expected ``msg'' length */
130 unsigned int dev_prime; /* blocks to write to start */
131
132 unsigned int log_level = 1;
133 volatile sig_atomic_t quit_flag = 0;
134 struct slot *slot_list = NULL;
135
136 /*
137 * length of voice and common MIDI messages (status byte included)
138 */
139 const unsigned int voice_len[] = { 3, 3, 3, 3, 2, 2, 3 };
140 const unsigned int common_len[] = { 0, 2, 3, 2, 0, 0, 1, 1 };
141
142 char usagestr[] = "usage: aucat [-dn] [-b size] "
143 "[-c channels] [-e enc] [-f device] [-g position]\n\t"
144 "[-h fmt] [-i file] [-m min:max/min:max] [-o file] [-p position]\n\t"
145 "[-q port] [-r rate] [-v volume]\n";
146
147 static void *
allocbuf(int nfr,int nch,int bps)148 allocbuf(int nfr, int nch, int bps)
149 {
150 size_t fsize;
151 void *ptr;
152
153 if (nch < 0 || nch > NCHAN_MAX || bps < 0 || bps > 4) {
154 logx(1, "allocbuf: bogus channels or bytes per sample count\n");
155 panic();
156 }
157 fsize = nch * bps;
158
159 ptr = reallocarray(NULL, nfr, fsize);
160 if (ptr == NULL)
161 err(1, "reallocarray");
162 return ptr;
163 }
164
165 static size_t
chans_fmt(char * buf,size_t size,int mode,int pmin,int pmax,int rmin,int rmax)166 chans_fmt(char *buf, size_t size, int mode, int pmin, int pmax, int rmin, int rmax)
167 {
168 const char *sep = "";
169 char *end = buf + size;
170 char *p = buf;
171
172 if (mode & SIO_PLAY) {
173 p += snprintf(p, p < end ? end - p : 0, "play %d:%d", pmin, pmax);
174 sep = ", ";
175 }
176 if (mode & SIO_REC) {
177 p += snprintf(p, p < end ? end - p : 0, "%srec %d:%d", sep, rmin, rmax);
178 }
179
180 return p - buf;
181 }
182
183 static size_t
slot_fmt(char * buf,size_t size,struct slot * s)184 slot_fmt(char *buf, size_t size, struct slot *s)
185 {
186 char enc[ENCMAX];
187 char *end = buf + size;
188 char *p = buf;
189
190 switch (s->afile.fmt) {
191 case AFILE_FMT_PCM:
192 aparams_enctostr(&s->afile.par, enc);
193 break;
194 case AFILE_FMT_ULAW:
195 strlcpy(enc, "ulaw", sizeof(enc));
196 break;
197 case AFILE_FMT_ALAW:
198 strlcpy(enc, "alaw", sizeof(enc));
199 break;
200 case AFILE_FMT_FLOAT:
201 strlcpy(enc, "f32le", sizeof(enc));
202 break;
203 default:
204 enc[0] = 0;
205 }
206
207 p += snprintf(p, p < end ? end - p : 0,
208 "%s, %uch (%u:%u/%u:%u), %uHz, %s",
209 s->mode == SIO_PLAY ? "play" : "rec",
210 s->afile.nch, s->imin, s->imax, s->omin, s->omax,
211 s->afile.rate, enc);
212
213 if (s->mode == SIO_PLAY) {
214 if (s->afile.endpos >= 0) {
215 p += snprintf(p, p < end ? end - p : 0,
216 ", bytes %lld..%lld",
217 s->afile.startpos,
218 s->afile.endpos);
219 }
220 p += snprintf(p, p < end ? end - p : 0, ", vol %d", s->vol);
221 }
222 return p - buf;
223 }
224
225 static void
slot_flush(struct slot * s)226 slot_flush(struct slot *s)
227 {
228 int count, n;
229 unsigned char *data;
230
231 for (;;) {
232 data = abuf_rgetblk(&s->buf, &count);
233 if (count == 0)
234 break;
235 n = afile_write(&s->afile, data, count);
236 if (n == 0) {
237 logx(1, "%s: can't write, disabled", s->afile.path);
238 s->pstate = SLOT_INIT;
239 return;
240 }
241 abuf_rdiscard(&s->buf, n);
242 }
243 }
244
245 static void
slot_fill(struct slot * s)246 slot_fill(struct slot *s)
247 {
248 int count, n;
249 unsigned char *data;
250
251 for (;;) {
252 data = abuf_wgetblk(&s->buf, &count);
253 if (count == 0)
254 break;
255 n = afile_read(&s->afile, data, count);
256 if (n == 0) {
257 #ifdef DEBUG
258 logx(3, "%s: eof reached, stopping", s->afile.path);
259 #endif
260 s->pstate = SLOT_STOP;
261 break;
262 }
263 abuf_wcommit(&s->buf, n);
264 }
265 }
266
267 static int
slot_new(char * path,int mode,struct aparams * par,int hdr,int imin,int imax,int omin,int omax,int nch,int rate,int dup,int vol,long long pos)268 slot_new(char *path, int mode, struct aparams *par, int hdr,
269 int imin, int imax, int omin, int omax, int nch,
270 int rate, int dup, int vol, long long pos)
271 {
272 struct slot *s, **ps;
273 char str[64];
274
275 s = xmalloc(sizeof(struct slot));
276 if (!afile_open(&s->afile, path, hdr,
277 mode == SIO_PLAY ? AFILE_FREAD : AFILE_FWRITE,
278 par, rate, nch)) {
279 xfree(s);
280 return 0;
281 }
282 s->imin = (imin != -1) ? imin : 0;
283 s->imax = (imax != -1) ? imax : s->imin + s->afile.nch - 1;
284 s->omin = (omin != -1) ? omin : 0;
285 s->omax = (omax != -1) ? omax : s->omin + s->afile.nch - 1;
286 s->dup = dup;
287 s->vol = MIDI_TO_ADATA(vol);
288 s->mode = mode;
289 s->pstate = SLOT_CFG;
290 s->pos = pos;
291
292 logx(2, "%s: %s", s->afile.path, (slot_fmt(str, sizeof(str), s), str));
293
294 for (ps = &slot_list; *ps != NULL; ps = &(*ps)->next)
295 ;
296 s->next = NULL;
297 *ps = s;
298 return 1;
299 }
300
301 static void
slot_init(struct slot * s)302 slot_init(struct slot *s)
303 {
304 unsigned int inch, onch, bufsz;
305
306 #ifdef DEBUG
307 if (s->pstate != SLOT_CFG) {
308 logx(1, "%s: slot_init: wrong state", s->afile.path);
309 panic();
310 }
311 #endif
312 s->bpf = s->afile.par.bps * s->afile.nch;
313 s->round = ((long long)dev_round * s->afile.rate +
314 dev_rate - 1) / dev_rate;
315
316 bufsz = s->round * (dev_bufsz / dev_round);
317 bufsz -= bufsz % s->round;
318 if (bufsz == 0)
319 bufsz = s->round;
320 abuf_init(&s->buf, bufsz * s->bpf);
321 #ifdef DEBUG
322 logx(3, "%s: allocated %u frame buffer", s->afile.path, bufsz);
323 #endif
324
325 s->convbuf = NULL;
326 s->resampbuf = NULL;
327 s->join = 1;
328 s->expand = 1;
329 inch = s->imax - s->imin + 1;
330 onch = s->omax - s->omin + 1;
331 if (s->dup) {
332 /* compat with legacy -j option */
333 if (s->mode == SIO_PLAY)
334 onch = dev_pchan;
335 else
336 inch = dev_rchan;
337 }
338 if (onch > inch)
339 s->expand = onch / inch;
340 else if (onch < inch)
341 s->join = inch / onch;
342 if (s->mode & SIO_PLAY) {
343 cmap_init(&s->cmap,
344 0, s->afile.nch - 1, s->imin, s->imax,
345 0, dev_pchan - 1, s->omin, s->omax);
346 if (s->afile.fmt != AFILE_FMT_PCM ||
347 !aparams_native(&s->afile.par)) {
348 dec_init(&s->conv, &s->afile.par, s->afile.nch);
349 s->convbuf = allocbuf(s->round, s->afile.nch, sizeof(adata_t));
350 }
351 if (s->afile.rate != dev_rate) {
352 resamp_init(&s->resamp, s->afile.rate, dev_rate,
353 s->afile.nch);
354 s->resampbuf = allocbuf(dev_round, s->afile.nch, sizeof(adata_t));
355 }
356 }
357 if (s->mode & SIO_REC) {
358 cmap_init(&s->cmap,
359 0, dev_rchan - 1, s->imin, s->imax,
360 0, s->afile.nch - 1, s->omin, s->omax);
361 if (s->afile.rate != dev_rate) {
362 resamp_init(&s->resamp, dev_rate, s->afile.rate,
363 s->afile.nch);
364 s->resampbuf = allocbuf(dev_round, s->afile.nch, sizeof(adata_t));
365 }
366 if (!aparams_native(&s->afile.par)) {
367 enc_init(&s->conv, &s->afile.par, s->afile.nch);
368 s->convbuf = allocbuf(s->round, s->afile.nch, sizeof(adata_t));
369 }
370
371 /*
372 * cmap_copy() doesn't write samples in all channels,
373 * for instance when mono->stereo conversion is
374 * disabled. So we have to prefill cmap_copy() output
375 * with silence.
376 */
377 if (s->resampbuf) {
378 memset(s->resampbuf, 0,
379 dev_round * s->afile.nch * sizeof(adata_t));
380 } else if (s->convbuf) {
381 memset(s->convbuf, 0,
382 s->round * s->afile.nch * sizeof(adata_t));
383 } else {
384 memset(s->buf.data, 0,
385 bufsz * s->afile.nch * sizeof(adata_t));
386 }
387 }
388 s->pstate = SLOT_INIT;
389 #ifdef DEBUG
390 logx(3, "%s: chain initialized", s->afile.path);
391 #endif
392 }
393
394 static void
slot_start(struct slot * s,long long pos)395 slot_start(struct slot *s, long long pos)
396 {
397 #ifdef DEBUG
398 if (s->pstate != SLOT_INIT) {
399 logx(1, "%s: slot_start: wrong state", s->afile.path);
400 panic();
401 }
402 #endif
403 pos -= s->pos;
404 if (pos < 0) {
405 s->skip = -pos;
406 pos = 0;
407 } else
408 s->skip = 0;
409
410 /*
411 * convert pos to slot sample rate
412 *
413 * At this stage, we could adjust s->resamp.diff to get
414 * sub-frame accuracy.
415 */
416 pos = pos * s->afile.rate / dev_rate;
417
418 if (!afile_seek(&s->afile, pos * s->bpf)) {
419 s->pstate = SLOT_INIT;
420 return;
421 }
422 s->pstate = SLOT_RUN;
423 if (s->mode & SIO_PLAY)
424 slot_fill(s);
425 #ifdef DEBUG
426 logx(2, "%s: started", s->afile.path);
427 #endif
428 }
429
430 static void
slot_stop(struct slot * s)431 slot_stop(struct slot *s)
432 {
433 if (s->pstate == SLOT_INIT)
434 return;
435 if (s->mode & SIO_REC)
436 slot_flush(s);
437 if (s->mode & SIO_PLAY)
438 s->buf.used = s->buf.start = 0;
439 s->pstate = SLOT_INIT;
440 #ifdef DEBUG
441 logx(2, "%s: stopped", s->afile.path);
442 #endif
443 }
444
445 static void
slot_del(struct slot * s)446 slot_del(struct slot *s)
447 {
448 struct slot **ps;
449
450 if (s->pstate != SLOT_CFG) {
451 slot_stop(s);
452 afile_close(&s->afile);
453 #ifdef DEBUG
454 logx(3, "%s: closed", s->afile.path);
455 #endif
456 abuf_done(&s->buf);
457 if (s->resampbuf)
458 xfree(s->resampbuf);
459 if (s->convbuf)
460 xfree(s->convbuf);
461 }
462 for (ps = &slot_list; *ps != s; ps = &(*ps)->next)
463 ; /* nothing */
464 *ps = s->next;
465 xfree(s);
466 }
467
468 static void
slot_getcnt(struct slot * s,int * icnt,int * ocnt)469 slot_getcnt(struct slot *s, int *icnt, int *ocnt)
470 {
471 int cnt;
472
473 if (s->resampbuf)
474 resamp_getcnt(&s->resamp, icnt, ocnt);
475 else {
476 cnt = (*icnt < *ocnt) ? *icnt : *ocnt;
477 *icnt = cnt;
478 *ocnt = cnt;
479 }
480 }
481
482 static void
play_filt_resamp(struct slot * s,void * res_in,void * out,int icnt,int ocnt)483 play_filt_resamp(struct slot *s, void *res_in, void *out, int icnt, int ocnt)
484 {
485 int i, offs, vol, inch, onch;
486 void *in;
487
488 if (s->resampbuf) {
489 resamp_do(&s->resamp, res_in, s->resampbuf, icnt, ocnt);
490 in = s->resampbuf;
491 } else
492 in = res_in;
493
494 inch = s->imax - s->imin + 1;
495 onch = s->omax - s->omin + 1;
496 vol = s->vol / s->join; /* XXX */
497 cmap_add(&s->cmap, in, out, vol, ocnt);
498
499 offs = 0;
500 for (i = s->join - 1; i > 0; i--) {
501 offs += onch;
502 if (offs + s->cmap.nch > s->afile.nch)
503 break;
504 cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, ocnt);
505 }
506
507 offs = 0;
508 for (i = s->expand - 1; i > 0; i--) {
509 offs += inch;
510 if (offs + s->cmap.nch > dev_pchan)
511 break;
512 cmap_add(&s->cmap, in, (adata_t *)out + offs, vol, ocnt);
513 }
514 }
515
516 static void
play_filt_dec(struct slot * s,void * in,void * out,int icnt,int ocnt)517 play_filt_dec(struct slot *s, void *in, void *out, int icnt, int ocnt)
518 {
519 void *tmp;
520
521 tmp = s->convbuf;
522 if (tmp) {
523 switch (s->afile.fmt) {
524 case AFILE_FMT_PCM:
525 dec_do(&s->conv, in, tmp, icnt);
526 break;
527 case AFILE_FMT_ULAW:
528 dec_do_ulaw(&s->conv, in, tmp, icnt, 0);
529 break;
530 case AFILE_FMT_ALAW:
531 dec_do_ulaw(&s->conv, in, tmp, icnt, 1);
532 break;
533 case AFILE_FMT_FLOAT:
534 dec_do_float(&s->conv, in, tmp, icnt);
535 break;
536 }
537 } else
538 tmp = in;
539 play_filt_resamp(s, tmp, out, icnt, ocnt);
540 }
541
542 /*
543 * Mix as many as possible frames (but not more than a block) from the
544 * slot buffer to the given location. Return the number of frames mixed
545 * in the output buffer
546 */
547 static int
slot_mix_badd(struct slot * s,adata_t * odata)548 slot_mix_badd(struct slot *s, adata_t *odata)
549 {
550 adata_t *idata;
551 int len, icnt, ocnt, otodo, odone;
552
553 odone = 0;
554 otodo = dev_round;
555 if (s->skip > 0) {
556 ocnt = otodo;
557 if (ocnt > s->skip)
558 ocnt = s->skip;
559 s->skip -= ocnt;
560 odata += dev_pchan * ocnt;
561 otodo -= ocnt;
562 odone += ocnt;
563 }
564 while (otodo > 0) {
565 idata = (adata_t *)abuf_rgetblk(&s->buf, &len);
566 icnt = len / s->bpf;
567 if (icnt > s->round)
568 icnt = s->round;
569 ocnt = otodo;
570 slot_getcnt(s, &icnt, &ocnt);
571 if (icnt == 0)
572 break;
573 play_filt_dec(s, idata, odata, icnt, ocnt);
574 abuf_rdiscard(&s->buf, icnt * s->bpf);
575 otodo -= ocnt;
576 odone += ocnt;
577 odata += ocnt * dev_pchan;
578 }
579 return odone;
580 }
581
582 static void
rec_filt_resamp(struct slot * s,void * in,void * res_out,int icnt,int ocnt)583 rec_filt_resamp(struct slot *s, void *in, void *res_out, int icnt, int ocnt)
584 {
585 int i, vol, offs, inch, onch;
586 void *out = res_out;
587
588 out = (s->resampbuf) ? s->resampbuf : res_out;
589
590 inch = s->imax - s->imin + 1;
591 onch = s->omax - s->omin + 1;
592 vol = ADATA_UNIT / s->join;
593 cmap_copy(&s->cmap, in, out, vol, icnt);
594
595 offs = 0;
596 for (i = s->join - 1; i > 0; i--) {
597 offs += onch;
598 if (offs + s->cmap.nch > dev_rchan)
599 break;
600 cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, icnt);
601 }
602 offs = 0;
603 for (i = s->expand - 1; i > 0; i--) {
604 offs += inch;
605 if (offs + s->cmap.nch > s->afile.nch)
606 break;
607 cmap_copy(&s->cmap, in, (adata_t *)out + offs, vol, icnt);
608 }
609 if (s->resampbuf)
610 resamp_do(&s->resamp, s->resampbuf, res_out, icnt, ocnt);
611 else
612 ocnt = icnt;
613 }
614
615 static void
rec_filt_enc(struct slot * s,void * in,void * out,int icnt,int ocnt)616 rec_filt_enc(struct slot *s, void *in, void *out, int icnt, int ocnt)
617 {
618 void *tmp;
619
620 tmp = s->convbuf;
621 rec_filt_resamp(s, in, tmp ? tmp : out, icnt, ocnt);
622 if (tmp)
623 enc_do(&s->conv, tmp, out, ocnt);
624 }
625
626 /*
627 * Copy "todo" frames from the given buffer to the slot buffer,
628 * but not more than a block.
629 */
630 static void
slot_sub_bcopy(struct slot * s,adata_t * idata,int itodo)631 slot_sub_bcopy(struct slot *s, adata_t *idata, int itodo)
632 {
633 adata_t *odata;
634 int len, icnt, ocnt;
635
636 if (s->skip > 0) {
637 icnt = itodo;
638 if (icnt > s->skip)
639 icnt = s->skip;
640 s->skip -= icnt;
641 idata += dev_rchan * icnt;
642 itodo -= icnt;
643 }
644
645 while (itodo > 0) {
646 odata = (adata_t *)abuf_wgetblk(&s->buf, &len);
647 ocnt = len / s->bpf;
648 if (ocnt > s->round)
649 ocnt = s->round;
650 icnt = itodo;
651 slot_getcnt(s, &icnt, &ocnt);
652 if (ocnt == 0)
653 break;
654 rec_filt_enc(s, idata, odata, icnt, ocnt);
655 abuf_wcommit(&s->buf, ocnt * s->bpf);
656 itodo -= icnt;
657 idata += icnt * dev_rchan;
658 }
659 }
660
661 static int
dev_open(char * dev,int mode,int bufsz,char * port)662 dev_open(char *dev, int mode, int bufsz, char *port)
663 {
664 int rate, pmax, rmax;
665 struct sio_par par;
666 char enc_str[ENCMAX], chans_str[64];
667 struct slot *s;
668
669 if (port) {
670 dev_port = port;
671 dev_mh = mio_open(dev_port, MIO_IN, 0);
672 if (dev_mh == NULL) {
673 logx(1, "%s: couldn't open midi port", port);
674 return 0;
675 }
676 } else
677 dev_mh = NULL;
678
679 dev_name = dev;
680 dev_sh = sio_open(dev, mode, 0);
681 if (dev_sh == NULL) {
682 logx(1, "%s: couldn't open audio device", dev_name);
683 return 0;
684 }
685
686 rate = pmax = rmax = 0;
687 for (s = slot_list; s != NULL; s = s->next) {
688 if (s->afile.rate > rate)
689 rate = s->afile.rate;
690 if (s->mode == SIO_PLAY) {
691 if (s->omax > pmax)
692 pmax = s->omax;
693 }
694 if (s->mode == SIO_REC) {
695 if (s->imax > rmax)
696 rmax = s->imax;
697 }
698 }
699 sio_initpar(&par);
700 par.bits = ADATA_BITS;
701 par.bps = sizeof(adata_t);
702 par.msb = 0;
703 par.le = SIO_LE_NATIVE;
704 par.rate = rate;
705 if (mode & SIO_PLAY)
706 par.pchan = pmax + 1;
707 if (mode & SIO_REC)
708 par.rchan = rmax + 1;
709 par.appbufsz = bufsz > 0 ? bufsz : rate * DEFAULT_BUFSZ_MS / 1000;
710 if (!sio_setpar(dev_sh, &par) || !sio_getpar(dev_sh, &par)) {
711 logx(1, "%s: couldn't set audio params", dev_name);
712 return 0;
713 }
714 dev_par.bits = par.bits;
715 dev_par.bps = par.bps;
716 dev_par.sig = par.sig;
717 dev_par.le = par.le;
718 dev_par.msb = par.msb;
719 dev_mode = mode;
720 dev_rate = par.rate;
721 dev_bufsz = par.bufsz;
722 dev_round = par.round;
723 if (mode & SIO_PLAY) {
724 dev_pchan = par.pchan;
725 dev_pbuf = allocbuf(dev_round, dev_pchan, sizeof(adata_t));
726 }
727 if (mode & SIO_REC) {
728 dev_rchan = par.rchan;
729 dev_rbuf = allocbuf(dev_round, dev_rchan, sizeof(adata_t));
730 }
731 if (!aparams_native(&dev_par)) {
732 if (mode & SIO_PLAY) {
733 dev_encbuf = allocbuf(dev_round, dev_pchan, dev_par.bps);
734 enc_init(&dev_enc, &dev_par, dev_pchan);
735 }
736 if (mode & SIO_REC) {
737 dev_decbuf = allocbuf(dev_round, dev_rchan, dev_par.bps);
738 dec_init(&dev_dec, &dev_par, dev_rchan);
739 }
740 }
741 dev_pstate = DEV_STOP;
742 logx(2, "%s: %uHz, %s, %s, %u blocks of %u frames", dev_name, dev_rate,
743 (aparams_enctostr(&dev_par, enc_str), enc_str),
744 (chans_fmt(chans_str, sizeof(chans_str),
745 dev_mode, 0, dev_pchan - 1, 0, dev_rchan - 1), chans_str),
746 dev_bufsz / dev_round, dev_round);
747 return 1;
748 }
749
750 static void
dev_close(void)751 dev_close(void)
752 {
753 sio_close(dev_sh);
754 if (dev_mh)
755 mio_close(dev_mh);
756 if (dev_mode & SIO_PLAY)
757 xfree(dev_pbuf);
758 if (dev_mode & SIO_REC)
759 xfree(dev_rbuf);
760 }
761
762 static void
dev_master(int val)763 dev_master(int val)
764 {
765 struct slot *s;
766 int mastervol, slotvol;
767
768 mastervol = MIDI_TO_ADATA(dev_volctl);
769 for (s = slot_list; s != NULL; s = s->next) {
770 slotvol = MIDI_TO_ADATA(val);
771 s->vol = ADATA_MUL(mastervol, slotvol);
772 }
773 #ifdef DEBUG
774 logx(3, "master volume set to %u", val);
775 #endif
776 }
777
778 static void
dev_slotvol(int midich,int val)779 dev_slotvol(int midich, int val)
780 {
781 struct slot *s;
782 int mastervol, slotvol;
783
784 for (s = slot_list; s != NULL; s = s->next) {
785 if (midich == 0) {
786 mastervol = MIDI_TO_ADATA(dev_volctl);
787 slotvol = MIDI_TO_ADATA(val);
788 s->vol = ADATA_MUL(mastervol, slotvol);
789 #ifdef DEBUG
790 logx(3, "%s: volume set to %u", s->afile.path, val);
791 #endif
792 break;
793 }
794 midich--;
795 }
796 }
797
798 /*
799 * start all slots simultaneously
800 */
801 static void
dev_mmcstart(void)802 dev_mmcstart(void)
803 {
804 struct slot *s;
805
806 if (dev_pstate == DEV_STOP) {
807 dev_pstate = DEV_START;
808 for (s = slot_list; s != NULL; s = s->next)
809 slot_start(s, dev_pos);
810 dev_prime = (dev_mode & SIO_PLAY) ? dev_bufsz / dev_round : 0;
811 sio_start(dev_sh);
812 logx(2, "started");
813 } else {
814 #ifdef DEBUG
815 logx(3, "ignoring mmc start");
816 #endif
817 }
818 }
819
820 /*
821 * stop all slots simultaneously
822 */
823 static void
dev_mmcstop(void)824 dev_mmcstop(void)
825 {
826 struct slot *s;
827
828 if (dev_pstate == DEV_START) {
829 dev_pstate = DEV_STOP;
830 for (s = slot_list; s != NULL; s = s->next)
831 slot_stop(s);
832 sio_stop(dev_sh);
833 logx(2, "stopped");
834 } else {
835 #ifdef DEBUG
836 logx(3, "ignored mmc stop\n");
837 #endif
838 }
839 }
840
841 /*
842 * relocate all slots simultaneously
843 */
844 static void
dev_mmcloc(int hr,int min,int sec,int fr,int cent,int fps)845 dev_mmcloc(int hr, int min, int sec, int fr, int cent, int fps)
846 {
847 long long pos;
848
849 pos = (long long)dev_rate * hr * 3600 +
850 (long long)dev_rate * min * 60 +
851 (long long)dev_rate * sec +
852 (long long)dev_rate * fr / fps +
853 (long long)dev_rate * cent / (100 * fps);
854 if (dev_pos == pos)
855 return;
856 dev_pos = pos;
857 logx(2, "relocated to %u:%u:%u.%u.%u at %u fps", hr, min, sec, fr, cent, fps);
858 if (dev_pstate == DEV_START) {
859 dev_mmcstop();
860 dev_mmcstart();
861 }
862 }
863
864 static void
dev_imsg(unsigned char * msg,unsigned int len)865 dev_imsg(unsigned char *msg, unsigned int len)
866 {
867 struct sysex *x;
868 unsigned int fps, chan;
869
870 if ((msg[0] & MIDI_CMDMASK) == MIDI_CTL && msg[1] == MIDI_CTL_VOL) {
871 chan = msg[0] & MIDI_CHANMASK;
872 dev_slotvol(chan, msg[2]);
873 return;
874 }
875 x = (struct sysex *)msg;
876 if (x->start != SYSEX_START)
877 return;
878 if (len < SYSEX_SIZE(empty))
879 return;
880 if (x->type != SYSEX_TYPE_RT)
881 return;
882 if (x->id0 == SYSEX_CONTROL && x->id1 == SYSEX_MASTER) {
883 if (len == SYSEX_SIZE(master))
884 dev_master(x->u.master.coarse);
885 return;
886 }
887 if (x->id0 != SYSEX_MMC)
888 return;
889 switch (x->id1) {
890 case SYSEX_MMC_STOP:
891 if (len != SYSEX_SIZE(stop))
892 return;
893 dev_mmcstop();
894 break;
895 case SYSEX_MMC_START:
896 if (len != SYSEX_SIZE(start))
897 return;
898 dev_mmcstart();
899 break;
900 case SYSEX_MMC_LOC:
901 if (len != SYSEX_SIZE(loc) ||
902 x->u.loc.len != SYSEX_MMC_LOC_LEN ||
903 x->u.loc.cmd != SYSEX_MMC_LOC_CMD)
904 return;
905 switch (x->u.loc.hr >> 5) {
906 case MTC_FPS_24:
907 fps = 24;
908 break;
909 case MTC_FPS_25:
910 fps = 25;
911 break;
912 case MTC_FPS_30:
913 fps = 30;
914 break;
915 default:
916 dev_mmcstop();
917 return;
918 }
919 dev_mmcloc(x->u.loc.hr & 0x1f,
920 x->u.loc.min,
921 x->u.loc.sec,
922 x->u.loc.fr,
923 x->u.loc.cent,
924 fps);
925 break;
926 }
927 }
928
929 /*
930 * parse the given data chunk and call imsg() for each message
931 */
932 static void
midi_in(unsigned char * idata,int icount)933 midi_in(unsigned char *idata, int icount)
934 {
935 int i;
936 unsigned char c;
937
938 for (i = 0; i < icount; i++) {
939 c = *idata++;
940 if (c >= 0xf8) {
941 /* we don't use real-time events */
942 } else if (c == SYSEX_END) {
943 if (dev_mst == SYSEX_START) {
944 dev_msg[dev_midx++] = c;
945 dev_imsg(dev_msg, dev_midx);
946 }
947 dev_mst = 0;
948 dev_midx = 0;
949 } else if (c >= 0xf0) {
950 dev_msg[0] = c;
951 dev_mlen = common_len[c & 7];
952 dev_mst = c;
953 dev_midx = 1;
954 } else if (c >= 0x80) {
955 dev_msg[0] = c;
956 dev_mlen = voice_len[(c >> 4) & 7];
957 dev_mst = c;
958 dev_midx = 1;
959 } else if (dev_mst) {
960 if (dev_midx == 0 && dev_mst != SYSEX_START)
961 dev_msg[dev_midx++] = dev_mst;
962 dev_msg[dev_midx++] = c;
963 if (dev_midx == dev_mlen) {
964 dev_imsg(dev_msg, dev_midx);
965 if (dev_mst >= 0xf0)
966 dev_mst = 0;
967 dev_midx = 0;
968 } else if (dev_midx == MIDI_MSGMAX) {
969 /* sysex too long */
970 dev_mst = 0;
971 }
972 }
973 }
974 }
975
976 static int
slot_list_mix(unsigned int round,unsigned int pchan,adata_t * pbuf)977 slot_list_mix(unsigned int round, unsigned int pchan, adata_t *pbuf)
978 {
979 unsigned int done, n;
980 struct slot *s;
981
982 memset(pbuf, 0, pchan * round * sizeof(adata_t));
983 done = 0;
984 for (s = slot_list; s != NULL; s = s->next) {
985 if (s->pstate == SLOT_INIT || !(s->mode & SIO_PLAY))
986 continue;
987 if (s->pstate == SLOT_STOP && s->buf.used < s->bpf) {
988 #ifdef DEBUG
989 logx(3, "%s: drained, done", s->afile.path);
990 #endif
991 slot_stop(s);
992 continue;
993 }
994 n = slot_mix_badd(s, dev_pbuf);
995 if (n > done)
996 done = n;
997 }
998 return done;
999 }
1000
1001 static int
slot_list_copy(unsigned int count,unsigned int rchan,adata_t * rbuf)1002 slot_list_copy(unsigned int count, unsigned int rchan, adata_t *rbuf)
1003 {
1004 unsigned int done;
1005 struct slot *s;
1006
1007 done = 0;
1008 for (s = slot_list; s != NULL; s = s->next) {
1009 if (s->pstate == SLOT_INIT || !(s->mode & SIO_REC))
1010 continue;
1011 slot_sub_bcopy(s, rbuf, count);
1012 done = count;
1013 }
1014 return done;
1015 }
1016
1017 static void
slot_list_iodo(void)1018 slot_list_iodo(void)
1019 {
1020 struct slot *s;
1021
1022 for (s = slot_list; s != NULL; s = s->next) {
1023 if (s->pstate != SLOT_RUN)
1024 continue;
1025 if ((s->mode & SIO_PLAY) &&
1026 (s->buf.used < s->round * s->bpf))
1027 slot_fill(s);
1028 if ((s->mode & SIO_REC) &&
1029 (s->buf.len - s->buf.used < s->round * s->bpf))
1030 slot_flush(s);
1031 }
1032 }
1033
1034 static int
offline(void)1035 offline(void)
1036 {
1037 unsigned int todo;
1038 int rate, cmax;
1039 struct slot *s;
1040
1041 if (pledge("stdio", NULL) == -1)
1042 err(1, "pledge");
1043
1044 rate = cmax = 0;
1045 for (s = slot_list; s != NULL; s = s->next) {
1046 if (s->afile.rate > rate)
1047 rate = s->afile.rate;
1048 if (s->imax > cmax)
1049 cmax = s->imax;
1050 if (s->omax > cmax)
1051 cmax = s->omax;
1052 }
1053 dev_sh = NULL;
1054 dev_name = "offline";
1055 dev_mode = SIO_PLAY | SIO_REC;
1056 dev_rate = rate;
1057 dev_bufsz = rate;
1058 dev_round = rate;
1059 dev_pchan = dev_rchan = cmax + 1;
1060 dev_pbuf = dev_rbuf = allocbuf(dev_round, dev_pchan, sizeof(adata_t));
1061 dev_pstate = DEV_STOP;
1062 for (s = slot_list; s != NULL; s = s->next)
1063 slot_init(s);
1064 for (s = slot_list; s != NULL; s = s->next)
1065 slot_start(s, 0);
1066 for (;;) {
1067 todo = slot_list_mix(dev_round, dev_pchan, dev_pbuf);
1068 if (todo == 0)
1069 break;
1070 slot_list_copy(todo, dev_pchan, dev_pbuf);
1071 slot_list_iodo();
1072 }
1073 xfree(dev_pbuf);
1074 while (slot_list)
1075 slot_del(slot_list);
1076 return 1;
1077 }
1078
1079 static int
playrec_cycle(void)1080 playrec_cycle(void)
1081 {
1082 unsigned int n, todo;
1083 unsigned char *p;
1084 int pcnt, rcnt;
1085
1086 #ifdef DEBUG
1087 logx(4, "%s: cycle, prime = %u", dev_name, dev_prime);
1088 #endif
1089 pcnt = rcnt = 0;
1090 if (dev_mode & SIO_REC) {
1091 if (dev_prime > 0)
1092 dev_prime--;
1093 else {
1094 todo = dev_round * dev_rchan * dev_par.bps;
1095 p = dev_decbuf ? dev_decbuf : (unsigned char *)dev_rbuf;
1096 while (todo > 0) {
1097 n = sio_read(dev_sh, p, todo);
1098 if (n == 0) {
1099 logx(1, "%s: failed to read", dev_name);
1100 return 0;
1101 }
1102 p += n;
1103 todo -= n;
1104 }
1105 rcnt = slot_list_copy(dev_round, dev_rchan, dev_rbuf);
1106 if (dev_decbuf) {
1107 dec_do(&dev_dec,
1108 dev_decbuf, (unsigned char *)dev_rbuf,
1109 dev_round);
1110 }
1111 }
1112 }
1113 if (dev_mode & SIO_PLAY) {
1114 pcnt = slot_list_mix(dev_round, dev_pchan, dev_pbuf);
1115 todo = dev_par.bps * dev_pchan * dev_round;
1116 if (dev_encbuf) {
1117 enc_do(&dev_enc,
1118 (unsigned char *)dev_pbuf, dev_encbuf,
1119 dev_round);
1120 p = dev_encbuf;
1121 } else
1122 p = (unsigned char *)dev_pbuf;
1123 n = sio_write(dev_sh, p, todo);
1124 if (n == 0) {
1125 logx(1, "%s: failed to write to device", dev_name);
1126 return 0;
1127 }
1128 }
1129 slot_list_iodo();
1130 return pcnt > 0 || rcnt > 0;
1131 }
1132
1133 static void
sigint(int s)1134 sigint(int s)
1135 {
1136 if (quit_flag)
1137 _exit(1);
1138 quit_flag = 1;
1139 }
1140
1141 static int
playrec(char * dev,int mode,int bufsz,char * port)1142 playrec(char *dev, int mode, int bufsz, char *port)
1143 {
1144 #define MIDIBUFSZ 0x100
1145 unsigned char mbuf[MIDIBUFSZ];
1146 struct sigaction sa;
1147 struct pollfd *pfds;
1148 struct slot *s;
1149 int n, ns, nm, ev;
1150
1151 if (!dev_open(dev, mode, bufsz, port))
1152 return 0;
1153 if (pledge("stdio audio", NULL) == -1)
1154 err(1, "pledge");
1155
1156 n = sio_nfds(dev_sh);
1157 if (dev_mh)
1158 n += mio_nfds(dev_mh);
1159 pfds = reallocarray(NULL, n, sizeof(struct pollfd));
1160 if (pfds == NULL)
1161 err(1, "malloc");
1162
1163 for (s = slot_list; s != NULL; s = s->next)
1164 slot_init(s);
1165 if (dev_mh == NULL)
1166 dev_mmcstart();
1167 else
1168 logx(2, "ready, waiting for mmc messages");
1169
1170 quit_flag = 0;
1171 sigfillset(&sa.sa_mask);
1172 sa.sa_flags = SA_RESTART;
1173 sa.sa_handler = sigint;
1174 sigaction(SIGINT, &sa, NULL);
1175 sigaction(SIGTERM, &sa, NULL);
1176 sigaction(SIGHUP, &sa, NULL);
1177 while (!quit_flag) {
1178 if (dev_pstate == DEV_START) {
1179 ev = 0;
1180 if (mode & SIO_PLAY)
1181 ev |= POLLOUT;
1182 if (mode & SIO_REC)
1183 ev |= POLLIN;
1184 ns = sio_pollfd(dev_sh, pfds, ev);
1185 } else
1186 ns = 0;
1187 if (dev_mh)
1188 nm = mio_pollfd(dev_mh, pfds + ns, POLLIN);
1189 else
1190 nm = 0;
1191 if (poll(pfds, ns + nm, -1) == -1) {
1192 if (errno == EINTR)
1193 continue;
1194 logx(1, "poll failed");
1195 panic();
1196 }
1197 if (dev_pstate == DEV_START) {
1198 ev = sio_revents(dev_sh, pfds);
1199 if (ev & POLLHUP) {
1200 logx(1, "%s: audio device gone, stopping", dev);
1201 break;
1202 }
1203 if (ev & (POLLIN | POLLOUT)) {
1204 if (!playrec_cycle() && dev_mh == NULL)
1205 break;
1206 }
1207 }
1208 if (dev_mh) {
1209 ev = mio_revents(dev_mh, pfds + ns);
1210 if (ev & POLLHUP) {
1211 logx(1, "%s: midi port gone, stopping", dev_port);
1212 break;
1213 }
1214 if (ev & POLLIN) {
1215 n = mio_read(dev_mh, mbuf, MIDIBUFSZ);
1216 midi_in(mbuf, n);
1217 }
1218 }
1219 }
1220 sigfillset(&sa.sa_mask);
1221 sa.sa_flags = SA_RESTART;
1222 sa.sa_handler = SIG_DFL;
1223 sigaction(SIGINT, &sa, NULL);
1224 sigaction(SIGTERM, &sa, NULL);
1225 sigaction(SIGHUP, &sa, NULL);
1226
1227 if (dev_pstate == DEV_START)
1228 dev_mmcstop();
1229 xfree(pfds);
1230 dev_close();
1231 while (slot_list)
1232 slot_del(slot_list);
1233 return 1;
1234 }
1235
1236 static int
opt_onoff(char * s,int * flag)1237 opt_onoff(char *s, int *flag)
1238 {
1239 if (strcmp("off", s) == 0) {
1240 *flag = 0;
1241 return 1;
1242 }
1243 if (strcmp("on", s) == 0) {
1244 *flag = 1;
1245 return 1;
1246 }
1247 logx(1, "%s: on/off expected", s);
1248 return 0;
1249 }
1250
1251 static int
opt_enc(char * s,struct aparams * par)1252 opt_enc(char *s, struct aparams *par)
1253 {
1254 int len;
1255
1256 len = aparams_strtoenc(par, s);
1257 if (len == 0 || s[len] != '\0') {
1258 logx(1, "%s: bad encoding", s);
1259 return 0;
1260 }
1261 return 1;
1262 }
1263
1264 static int
opt_hdr(char * s,int * hdr)1265 opt_hdr(char *s, int *hdr)
1266 {
1267 if (strcmp("auto", s) == 0) {
1268 *hdr = AFILE_HDR_AUTO;
1269 return 1;
1270 }
1271 if (strcmp("raw", s) == 0) {
1272 *hdr = AFILE_HDR_RAW;
1273 return 1;
1274 }
1275 if (strcmp("wav", s) == 0) {
1276 *hdr = AFILE_HDR_WAV;
1277 return 1;
1278 }
1279 if (strcmp("aiff", s) == 0) {
1280 *hdr = AFILE_HDR_AIFF;
1281 return 1;
1282 }
1283 if (strcmp("au", s) == 0) {
1284 *hdr = AFILE_HDR_AU;
1285 return 1;
1286 }
1287 logx(1, "%s: bad header type", s);
1288 return 0;
1289 }
1290
1291 static int
opt_map(char * str,int * rimin,int * rimax,int * romin,int * romax)1292 opt_map(char *str, int *rimin, int *rimax, int *romin, int *romax)
1293 {
1294 char *s, *next;
1295 long imin, imax, omin, omax;
1296
1297 errno = 0;
1298 s = str;
1299 imin = strtol(s, &next, 10);
1300 if (next == s || *next != ':')
1301 goto failed;
1302 s = next + 1;
1303 imax = strtol(s, &next, 10);
1304 if (next == s || *next != '/')
1305 goto failed;
1306 s = next + 1;
1307 omin = strtol(s, &next, 10);
1308 if (next == s || *next != ':')
1309 goto failed;
1310 s = next + 1;
1311 omax = strtol(s, &next, 10);
1312 if (next == s || *next != '\0')
1313 goto failed;
1314 if (imin < 0 || imax < imin || imax >= NCHAN_MAX)
1315 goto failed;
1316 if (omin < 0 || omax < omin || omax >= NCHAN_MAX)
1317 goto failed;
1318 *rimin = imin;
1319 *rimax = imax;
1320 *romin = omin;
1321 *romax = omax;
1322 return 1;
1323 failed:
1324 logx(1, "%s: channel mapping expected", str);
1325 return 0;
1326 }
1327
1328 static int
opt_nch(char * str,int * rnch,int * roff)1329 opt_nch(char *str, int *rnch, int *roff)
1330 {
1331 char *s, *next;
1332 long nch, off, cmin, cmax;
1333
1334 errno = 0;
1335 s = str;
1336 nch = strtol(s, &next, 10);
1337 if (next == s)
1338 goto failed;
1339 if (*next == ':') {
1340 /* compat with legacy -c syntax */
1341 s = next + 1;
1342 cmin = nch;
1343 cmax = strtol(s, &next, 10);
1344 if (next == s)
1345 goto failed;
1346 if (cmin < 0 || cmax < cmin || cmax >= NCHAN_MAX)
1347 goto failed;
1348 nch = cmax - cmin + 1;
1349 off = cmin;
1350 } else {
1351 off = 0;
1352 if (nch < 0 || nch >= NCHAN_MAX)
1353 goto failed;
1354 }
1355 if (*next != '\0')
1356 goto failed;
1357 *rnch = nch;
1358 *roff = off;
1359 return 1;
1360 failed:
1361 logx(1, "%s: channel count expected", str);
1362 return 0;
1363 }
1364
1365 static int
opt_num(char * s,int min,int max,int * num)1366 opt_num(char *s, int min, int max, int *num)
1367 {
1368 const char *errstr;
1369
1370 *num = strtonum(s, min, max, &errstr);
1371 if (errstr) {
1372 logx(1, "%s: expected integer between %d and %d", s, min, max);
1373 return 0;
1374 }
1375 return 1;
1376 }
1377
1378 static int
opt_pos(char * s,long long * pos)1379 opt_pos(char *s, long long *pos)
1380 {
1381 const char *errstr;
1382
1383 *pos = strtonum(s, 0, LLONG_MAX, &errstr);
1384 if (errstr) {
1385 logx(1, "%s: positive number of samples expected", s);
1386 return 0;
1387 }
1388 return 1;
1389 }
1390
1391 int
main(int argc,char ** argv)1392 main(int argc, char **argv)
1393 {
1394 int dup, imin, imax, omin, omax, nch, off, rate, vol, bufsz, hdr, mode;
1395 char *port, *dev;
1396 struct aparams par;
1397 int n_flag, c;
1398 long long pos;
1399
1400 if (pledge("stdio rpath wpath cpath inet unix dns audio", NULL) == -1)
1401 err(1, "pledge");
1402
1403 vol = 127;
1404 dup = 0;
1405 bufsz = 0;
1406 nch = 2;
1407 off = 0;
1408 rate = DEFAULT_RATE;
1409 imin = imax = omin = omax = -1;
1410 par.bits = ADATA_BITS;
1411 par.bps = APARAMS_BPS(par.bits);
1412 par.le = ADATA_LE;
1413 par.sig = 1;
1414 par.msb = 1;
1415 hdr = AFILE_HDR_AUTO;
1416 n_flag = 0;
1417 port = NULL;
1418 dev = NULL;
1419 mode = 0;
1420 pos = 0;
1421
1422 while ((c = getopt(argc, argv,
1423 "b:c:de:f:g:h:i:j:m:no:p:q:r:t:v:")) != -1) {
1424 switch (c) {
1425 case 'b':
1426 if (!opt_num(optarg, 1, RATE_MAX, &bufsz))
1427 return 1;
1428 break;
1429 case 'c':
1430 if (!opt_nch(optarg, &nch, &off))
1431 return 1;
1432 break;
1433 case 'd':
1434 log_level++;
1435 break;
1436 case 'e':
1437 if (!opt_enc(optarg, &par))
1438 return 1;
1439 break;
1440 case 'f':
1441 dev = optarg;
1442 break;
1443 case 'g':
1444 if (!opt_pos(optarg, &dev_pos))
1445 return 1;
1446 break;
1447 case 'h':
1448 if (!opt_hdr(optarg, &hdr))
1449 return 1;
1450 break;
1451 case 'i':
1452 if (off > 0) {
1453 /* compat with legacy -c syntax */
1454 omin = off;
1455 omax = off + nch - 1;
1456 }
1457 if (!slot_new(optarg, SIO_PLAY,
1458 &par, hdr, imin, imax, omin, omax,
1459 nch, rate, dup, vol, pos))
1460 return 1;
1461 mode |= SIO_PLAY;
1462 imin = imax = omin = omax = -1;
1463 break;
1464 case 'j':
1465 /* compat with legacy -j option */
1466 if (!opt_onoff(optarg, &dup))
1467 return 1;
1468 break;
1469 case 'm':
1470 if (!opt_map(optarg, &imin, &imax, &omin, &omax))
1471 return 1;
1472 break;
1473 case 'n':
1474 n_flag = 1;
1475 break;
1476 case 'o':
1477 if (off > 0) {
1478 /* compat with legacy -c syntax */
1479 imin = off;
1480 imax = off + nch - 1;
1481 }
1482 if (!slot_new(optarg, SIO_REC,
1483 &par, hdr, imin, imax, omin, omax,
1484 nch, rate, dup, 0, pos))
1485 return 1;
1486 imin = imax = omin = omax = -1;
1487 mode |= SIO_REC;
1488 break;
1489 case 'p':
1490 if (!opt_pos(optarg, &pos))
1491 return 1;
1492 break;
1493 case 'q':
1494 port = optarg;
1495 break;
1496 case 'r':
1497 if (!opt_num(optarg, RATE_MIN, RATE_MAX, &rate))
1498 return 1;
1499 break;
1500 case 'v':
1501 if (!opt_num(optarg, 0, MIDI_MAXCTL, &vol))
1502 return 1;
1503 break;
1504 default:
1505 goto bad_usage;
1506 }
1507 }
1508 argc -= optind;
1509 argv += optind;
1510 if (argc != 0) {
1511 bad_usage:
1512 logx(1, "%s", usagestr);
1513 return 1;
1514 }
1515 if (n_flag) {
1516 if (dev != NULL || port != NULL) {
1517 logx(1, "-f and -q make no sense in off-line mode");
1518 return 1;
1519 }
1520 if (mode != (SIO_PLAY | SIO_REC)) {
1521 logx(1, "both -i and -o required");
1522 return 1;
1523 }
1524 if (!offline())
1525 return 1;
1526 } else {
1527 if (dev == NULL)
1528 dev = SIO_DEVANY;
1529 if (mode == 0) {
1530 logx(1, "at least -i or -o required");
1531 return 1;
1532 }
1533 if (!playrec(dev, mode, bufsz, port))
1534 return 1;
1535 }
1536 return 0;
1537 }
1538