diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2016-06-07 06:26:25 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2016-06-07 06:26:25 +0000 |
commit | 1dd226a08b4d876846585f80b2a92a01bf92b8c0 (patch) | |
tree | 3cf343643947e1d3ec39815ee3594f993dc76777 | |
parent | 18fe27a4440d3619d5364d76e216fac1e5368c4f (diff) |
Add -g and -p options to control device and file start position.
-rw-r--r-- | usr.bin/aucat/aucat.1 | 16 | ||||
-rw-r--r-- | usr.bin/aucat/aucat.c | 75 |
2 files changed, 79 insertions, 12 deletions
diff --git a/usr.bin/aucat/aucat.1 b/usr.bin/aucat/aucat.1 index 7d8fae1ba90..ab056fd6440 100644 --- a/usr.bin/aucat/aucat.1 +++ b/usr.bin/aucat/aucat.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: aucat.1,v 1.112 2016/01/07 07:41:01 ratchov Exp $ +.\" $OpenBSD: aucat.1,v 1.113 2016/06/07 06:26:24 ratchov Exp $ .\" .\" Copyright (c) 2006 Alexandre Ratchov <alex@caoua.org> .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: January 7 2016 $ +.Dd $Mdocdate: June 7 2016 $ .Dt AUCAT 1 .Os .Sh NAME @@ -27,10 +27,12 @@ .Op Fl c Ar min : Ns Ar max .Op Fl e Ar enc .Op Fl f Ar device +.Op Fl g Ar position .Op Fl h Ar fmt .Op Fl i Ar file .Op Fl j Ar flag .Op Fl o Ar file +.Op Fl p Ar position .Op Fl q Ar port .Op Fl r Ar rate .Op Fl v Ar volume @@ -117,6 +119,11 @@ audio device. Device mode and parameters are determined from audio files. Default is .Pa default . +.It Fl g Ar position +Go to the given time position and start playback or recording there. +This option is equivalent to an incoming MMC relocate message +with the same position. +The position is expressed as the number of samples (at device sample rate). .It Fl h Ar fmt Audio file type. The following file types are supported: @@ -169,6 +176,11 @@ Record into this audio file. If the option argument is .Sq - then standard output will be used. +.It Fl p Ar position +Time offset where the beginning of the file belongs. +The first sample of the file will be played or recorded when the device +reaches the given postion. +The position is expressed as the number of samples (at device sample rate). .It Fl q Ar port Control audio device properties through this MIDI port. This includes per-stream volumes and the ability to diff --git a/usr.bin/aucat/aucat.c b/usr.bin/aucat/aucat.c index 33aad5a2d4c..9014dd90d88 100644 --- a/usr.bin/aucat/aucat.c +++ b/usr.bin/aucat/aucat.c @@ -16,6 +16,7 @@ #include <fcntl.h> #include <errno.h> +#include <limits.h> #include <poll.h> #include <signal.h> #include <sndio.h> @@ -90,6 +91,8 @@ struct slot { #define SLOT_RUN 2 /* playing/recording */ #define SLOT_STOP 3 /* draining (play only) */ int pstate; /* one of above */ + long long skip; /* frames to skip at the beginning */ + long long pos; /* start position (at device rate) */ struct afile afile; /* file desc & friends */ }; @@ -134,8 +137,9 @@ unsigned int voice_len[] = { 3, 3, 3, 3, 2, 2, 3 }; unsigned int common_len[] = { 0, 2, 3, 2, 0, 0, 1, 1 }; char usagestr[] = "usage: aucat [-dn] [-b size] " - "[-c min:max] [-e enc] [-f device] [-h fmt]\n\t" - "[-i file] [-j flag] [-o file] [-q port] [-r rate] [-v volume]\n"; + "[-c min:max] [-e enc] [-f device] [-g position]\n\t" + "[-h fmt] [-i file] [-j flag] [-o file] [-p position] [-q port]\n\t" + "[-r rate] [-v volume]\n"; static void slot_log(struct slot *s) @@ -202,7 +206,7 @@ slot_fill(struct slot *s) static int slot_new(char *path, int mode, struct aparams *par, int hdr, - int cmin, int cmax, int rate, int dup, int vol) + int cmin, int cmax, int rate, int dup, int vol, long long pos) { struct slot *s; @@ -219,6 +223,7 @@ slot_new(char *path, int mode, struct aparams *par, int hdr, s->vol = MIDI_TO_ADATA(vol); s->mode = mode; s->pstate = SLOT_CFG; + s->pos = pos; if (log_level >= 2) { slot_log(s); log_puts(": "); @@ -359,6 +364,13 @@ slot_start(struct slot *s, long long pos) panic(); } #endif + pos -= s->pos; + if (pos < 0) { + s->skip = -pos; + pos = 0; + } else + s->skip = 0; + /* * convert pos to slot sample rate * @@ -415,8 +427,10 @@ slot_del(struct slot *s) } #endif abuf_done(&s->buf); - free(s->resampbuf); - free(s->convbuf); + if (s->resampbuf) + free(s->resampbuf); + if (s->convbuf) + free(s->convbuf); } for (ps = &slot_list; *ps != s; ps = &(*ps)->next) ; /* nothing */ @@ -505,6 +519,15 @@ slot_mix_badd(struct slot *s, adata_t *odata) odone = 0; otodo = dev_round; + if (s->skip > 0) { + ocnt = otodo; + if (ocnt > s->skip) + ocnt = s->skip; + s->skip -= ocnt; + odata += dev_pchan * ocnt; + otodo -= ocnt; + odone += ocnt; + } while (otodo > 0) { idata = (adata_t *)abuf_rgetblk(&s->buf, &len); icnt = len / s->bpf; @@ -570,6 +593,15 @@ slot_sub_bcopy(struct slot *s, adata_t *idata, int itodo) adata_t *odata; int len, icnt, ocnt; + if (s->skip > 0) { + icnt = itodo; + if (icnt > s->skip) + icnt = s->skip; + s->skip -= icnt; + idata += dev_rchan * icnt; + itodo -= icnt; + } + while (itodo > 0) { odata = (adata_t *)abuf_wgetblk(&s->buf, &len); ocnt = len / s->bpf; @@ -658,7 +690,6 @@ dev_open(char *dev, int mode, int bufsz, char *port) dev_rchan = par.rchan; dev_rbuf = xmalloc(sizeof(adata_t) * dev_rchan * dev_round); } - dev_pos = 0; dev_pstate = DEV_STOP; if (log_level >= 2) { log_puts(dev_name); @@ -1018,7 +1049,6 @@ offline(void) dev_pchan = dev_rchan = cmax + 1; dev_pbuf = dev_rbuf = xmalloc(sizeof(adata_t) * dev_pchan * dev_round); dev_pstate = DEV_STOP; - dev_pos = 0; for (s = slot_list; s != NULL; s = s->next) slot_init(s); for (s = slot_list; s != NULL; s = s->next) @@ -1287,6 +1317,20 @@ opt_num(char *s, int min, int max, int *num) return 1; } +static int +opt_pos(char *s, long long *pos) +{ + const char *errstr; + + *pos = strtonum(s, 0, LLONG_MAX, &errstr); + if (errstr) { + log_puts(s); + log_puts(": positive number of samples expected\n"); + return 0; + } + return 1; +} + int main(int argc, char **argv) { @@ -1294,6 +1338,7 @@ main(int argc, char **argv) char *port, *dev; struct aparams par; int n_flag, c; + long long pos; vol = 127; dup = 0; @@ -1307,8 +1352,10 @@ main(int argc, char **argv) port = NULL; dev = NULL; mode = 0; + pos = 0; - while ((c = getopt(argc, argv, "b:c:de:f:h:i:j:no:q:r:t:v:")) != -1) { + while ((c = getopt(argc, argv, + "b:c:de:f:g:h:i:j:no:p:q:r:t:v:")) != -1) { switch (c) { case 'b': if (!opt_num(optarg, 1, RATE_MAX, &bufsz)) @@ -1328,13 +1375,17 @@ main(int argc, char **argv) case 'f': dev = optarg; break; + case 'g': + if (!opt_pos(optarg, &dev_pos)) + return 1; + break; case 'h': if (!opt_hdr(optarg, &hdr)) return 1; break; case 'i': if (!slot_new(optarg, SIO_PLAY, - &par, hdr, cmin, cmax, rate, dup, vol)) + &par, hdr, cmin, cmax, rate, dup, vol, pos)) return 1; mode |= SIO_PLAY; break; @@ -1347,10 +1398,14 @@ main(int argc, char **argv) break; case 'o': if (!slot_new(optarg, SIO_REC, - &par, hdr, cmin, cmax, rate, dup, 0)) + &par, hdr, cmin, cmax, rate, dup, 0, pos)) return 1; mode |= SIO_REC; break; + case 'p': + if (!opt_pos(optarg, &pos)) + return 1; + break; case 'q': port = optarg; break; |