mirror of
https://github.com/ericonr/sndio.git
synced 2024-02-18 04:45:21 -06:00
add -g and -p option to control device and file start position
This commit is contained in:
parent
a6fdc3b5ed
commit
2562fa7eb4
@ -27,10 +27,12 @@
|
|||||||
.Op Fl c Ar min : Ns Ar max
|
.Op Fl c Ar min : Ns Ar max
|
||||||
.Op Fl e Ar enc
|
.Op Fl e Ar enc
|
||||||
.Op Fl f Ar device
|
.Op Fl f Ar device
|
||||||
|
.Op Fl g Ar position
|
||||||
.Op Fl h Ar fmt
|
.Op Fl h Ar fmt
|
||||||
.Op Fl i Ar file
|
.Op Fl i Ar file
|
||||||
.Op Fl j Ar flag
|
.Op Fl j Ar flag
|
||||||
.Op Fl o Ar file
|
.Op Fl o Ar file
|
||||||
|
.Op Fl p Ar position
|
||||||
.Op Fl q Ar port
|
.Op Fl q Ar port
|
||||||
.Op Fl r Ar rate
|
.Op Fl r Ar rate
|
||||||
.Op Fl v Ar volume
|
.Op Fl v Ar volume
|
||||||
@ -117,6 +119,11 @@ audio device.
|
|||||||
Device mode and parameters are determined from audio files.
|
Device mode and parameters are determined from audio files.
|
||||||
Default is
|
Default is
|
||||||
.Pa default .
|
.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
|
.It Fl h Ar fmt
|
||||||
Audio file type.
|
Audio file type.
|
||||||
The following file types are supported:
|
The following file types are supported:
|
||||||
@ -169,6 +176,11 @@ Record into this audio file.
|
|||||||
If the option argument is
|
If the option argument is
|
||||||
.Sq -
|
.Sq -
|
||||||
then standard output will be used.
|
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
|
.It Fl q Ar port
|
||||||
Control audio device properties through this MIDI port.
|
Control audio device properties through this MIDI port.
|
||||||
This includes per-stream volumes and the ability to
|
This includes per-stream volumes and the ability to
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sndio.h>
|
#include <sndio.h>
|
||||||
@ -91,6 +92,8 @@ struct slot {
|
|||||||
#define SLOT_RUN 2 /* playing/recording */
|
#define SLOT_RUN 2 /* playing/recording */
|
||||||
#define SLOT_STOP 3 /* draining (play only) */
|
#define SLOT_STOP 3 /* draining (play only) */
|
||||||
int pstate; /* one of above */
|
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 */
|
struct afile afile; /* file desc & friends */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -135,8 +138,9 @@ unsigned int voice_len[] = { 3, 3, 3, 3, 2, 2, 3 };
|
|||||||
unsigned int common_len[] = { 0, 2, 3, 2, 0, 0, 1, 1 };
|
unsigned int common_len[] = { 0, 2, 3, 2, 0, 0, 1, 1 };
|
||||||
|
|
||||||
char usagestr[] = "usage: aucat [-dn] [-b size] "
|
char usagestr[] = "usage: aucat [-dn] [-b size] "
|
||||||
"[-c min:max] [-e enc] [-f device] [-h fmt]\n\t"
|
"[-c min:max] [-e enc] [-f device] [-g position]\n\t"
|
||||||
"[-i file] [-j flag] [-o file] [-q port] [-r rate] [-v volume]\n";
|
"[-h fmt] [-i file] [-j flag] [-o file] [-p position] [-q port]\n\t"
|
||||||
|
"[-r rate] [-v volume]\n";
|
||||||
|
|
||||||
static void
|
static void
|
||||||
slot_log(struct slot *s)
|
slot_log(struct slot *s)
|
||||||
@ -203,7 +207,7 @@ slot_fill(struct slot *s)
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
slot_new(char *path, int mode, struct aparams *par, int hdr,
|
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;
|
struct slot *s;
|
||||||
|
|
||||||
@ -220,6 +224,7 @@ slot_new(char *path, int mode, struct aparams *par, int hdr,
|
|||||||
s->vol = MIDI_TO_ADATA(vol);
|
s->vol = MIDI_TO_ADATA(vol);
|
||||||
s->mode = mode;
|
s->mode = mode;
|
||||||
s->pstate = SLOT_CFG;
|
s->pstate = SLOT_CFG;
|
||||||
|
s->pos = pos;
|
||||||
if (log_level >= 2) {
|
if (log_level >= 2) {
|
||||||
slot_log(s);
|
slot_log(s);
|
||||||
log_puts(": ");
|
log_puts(": ");
|
||||||
@ -360,6 +365,13 @@ slot_start(struct slot *s, long long pos)
|
|||||||
panic();
|
panic();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
pos -= s->pos;
|
||||||
|
if (pos < 0) {
|
||||||
|
s->skip = -pos;
|
||||||
|
pos = 0;
|
||||||
|
} else
|
||||||
|
s->skip = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* convert pos to slot sample rate
|
* convert pos to slot sample rate
|
||||||
*
|
*
|
||||||
@ -506,6 +518,15 @@ slot_mix_badd(struct slot *s, adata_t *odata)
|
|||||||
|
|
||||||
odone = 0;
|
odone = 0;
|
||||||
otodo = dev_round;
|
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) {
|
while (otodo > 0) {
|
||||||
idata = (adata_t *)abuf_rgetblk(&s->buf, &len);
|
idata = (adata_t *)abuf_rgetblk(&s->buf, &len);
|
||||||
|
|
||||||
@ -575,6 +596,15 @@ slot_sub_bcopy(struct slot *s, adata_t *idata, int itodo)
|
|||||||
adata_t *odata;
|
adata_t *odata;
|
||||||
int len, icnt, ocnt;
|
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) {
|
while (itodo > 0) {
|
||||||
odata = (adata_t *)abuf_wgetblk(&s->buf, &len);
|
odata = (adata_t *)abuf_wgetblk(&s->buf, &len);
|
||||||
|
|
||||||
@ -667,7 +697,6 @@ dev_open(char *dev, int mode, int bufsz, char *port)
|
|||||||
dev_rchan = par.rchan;
|
dev_rchan = par.rchan;
|
||||||
dev_rbuf = xmalloc(sizeof(adata_t) * dev_rchan * dev_round);
|
dev_rbuf = xmalloc(sizeof(adata_t) * dev_rchan * dev_round);
|
||||||
}
|
}
|
||||||
dev_pos = 0;
|
|
||||||
dev_pstate = DEV_STOP;
|
dev_pstate = DEV_STOP;
|
||||||
if (log_level >= 2) {
|
if (log_level >= 2) {
|
||||||
log_puts(dev_name);
|
log_puts(dev_name);
|
||||||
@ -1027,7 +1056,6 @@ offline(void)
|
|||||||
dev_pchan = dev_rchan = cmax + 1;
|
dev_pchan = dev_rchan = cmax + 1;
|
||||||
dev_pbuf = dev_rbuf = xmalloc(sizeof(adata_t) * dev_pchan * dev_round);
|
dev_pbuf = dev_rbuf = xmalloc(sizeof(adata_t) * dev_pchan * dev_round);
|
||||||
dev_pstate = DEV_STOP;
|
dev_pstate = DEV_STOP;
|
||||||
dev_pos = 0;
|
|
||||||
for (s = slot_list; s != NULL; s = s->next)
|
for (s = slot_list; s != NULL; s = s->next)
|
||||||
slot_init(s);
|
slot_init(s);
|
||||||
for (s = slot_list; s != NULL; s = s->next)
|
for (s = slot_list; s != NULL; s = s->next)
|
||||||
@ -1296,6 +1324,20 @@ opt_num(char *s, int min, int max, int *num)
|
|||||||
return 1;
|
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
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -1303,6 +1345,7 @@ main(int argc, char **argv)
|
|||||||
char *port, *dev;
|
char *port, *dev;
|
||||||
struct aparams par;
|
struct aparams par;
|
||||||
int n_flag, c;
|
int n_flag, c;
|
||||||
|
long long pos;
|
||||||
|
|
||||||
vol = 127;
|
vol = 127;
|
||||||
dup = 0;
|
dup = 0;
|
||||||
@ -1316,8 +1359,10 @@ main(int argc, char **argv)
|
|||||||
port = NULL;
|
port = NULL;
|
||||||
dev = NULL;
|
dev = NULL;
|
||||||
mode = 0;
|
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) {
|
switch (c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
if (!opt_num(optarg, 1, RATE_MAX, &bufsz))
|
if (!opt_num(optarg, 1, RATE_MAX, &bufsz))
|
||||||
@ -1337,13 +1382,17 @@ main(int argc, char **argv)
|
|||||||
case 'f':
|
case 'f':
|
||||||
dev = optarg;
|
dev = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'g':
|
||||||
|
if (!opt_pos(optarg, &dev_pos))
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
if (!opt_hdr(optarg, &hdr))
|
if (!opt_hdr(optarg, &hdr))
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
if (!slot_new(optarg, SIO_PLAY,
|
if (!slot_new(optarg, SIO_PLAY,
|
||||||
&par, hdr, cmin, cmax, rate, dup, vol))
|
&par, hdr, cmin, cmax, rate, dup, vol, pos))
|
||||||
return 1;
|
return 1;
|
||||||
mode |= SIO_PLAY;
|
mode |= SIO_PLAY;
|
||||||
break;
|
break;
|
||||||
@ -1356,10 +1405,14 @@ main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
if (!slot_new(optarg, SIO_REC,
|
if (!slot_new(optarg, SIO_REC,
|
||||||
&par, hdr, cmin, cmax, rate, dup, 0))
|
&par, hdr, cmin, cmax, rate, dup, 0, pos))
|
||||||
return 1;
|
return 1;
|
||||||
mode |= SIO_REC;
|
mode |= SIO_REC;
|
||||||
break;
|
break;
|
||||||
|
case 'p':
|
||||||
|
if (!opt_pos(optarg, &pos))
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
port = optarg;
|
port = optarg;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user