Use -io options to specify files and -q option to specify one

or two ports, allowing port-to-port transfers.
This commit is contained in:
Alexandre Ratchov 2017-01-18 10:26:27 +01:00
parent 044421aad7
commit 3d710ac721
2 changed files with 153 additions and 53 deletions

View File

@ -24,8 +24,9 @@
.Nm midicat .Nm midicat
.Bk -words .Bk -words
.Op Fl d .Op Fl d
.Op Fl i Ar port .Op Fl i Ar file
.Op Fl o Ar port .Op Fl o Ar file
.Op Fl q Ar port
.Ek .Ek
.Sh DESCRIPTION .Sh DESCRIPTION
The The
@ -36,21 +37,39 @@ The options are as follows:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Fl d .It Fl d
Dump transferred data in hex on stderr. Dump transferred data in hex on stderr.
.It Fl i Ar port .It Fl i Ar file
Read MIDI data from this file instead of receiving it from the MIDI port.
If the option argument is
.Sq -
then standard input will be used.
.It Fl o Ar file
Write MIDI data to this file instead of sending it to the MIDI port.
If the option argument is
.Sq -
then standard output will be used.
.It Fl q Ar port
Use this Use this
.Xr sndio 7 .Xr sndio 7
MIDI port as input instead of stdin. MIDI port for input/output.
.It Fl o Ar port If the option is used twice, the first one specifies
Use this the input port and the second one the output port.
.Xr sndio 7
MIDI port as output instead of stdout.
.El .El
.Pp
If no files are specified, then
.Nm
transfers data from the MIDI input port to the MIDI output port.
.Sh EXAMPLES .Sh EXAMPLES
Send the given file to
.Pa rmidi/0 :
.Bd -literal -offset indent
$ midicat -i file.syx -q rmidi/0
.Ed
.Pp
Dump data received from Dump data received from
.Pa rmidi/0 .Pa rmidi/0
to stderr: to stderr:
.Bd -literal -offset indent .Bd -literal -offset indent
$ midicat -di rmidi/0 >/dev/null $ midicat -d -q rmidi/0 -o /dev/null
.Ed .Ed
.Pp .Pp
Send data from Send data from
@ -58,8 +77,9 @@ Send data from
to to
.Pa midithru/0: .Pa midithru/0:
.Bd -literal -offset indent .Bd -literal -offset indent
$ midicat -i rmidi/0 -o midithru/0 $ midicat -q rmidi/0 -q midithru/0
.Ed .Ed
.Sh SEE ALSO .Sh SEE ALSO
.Xr midi 4 , .Xr midi 4 ,
.Xr sndio 7 .Xr sndio 7 ,
.Xr sndiod 8

View File

@ -18,9 +18,11 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <string.h>
#include "bsd-compat.h" #include "bsd-compat.h"
char usagestr[] = "usage: midicat [-d] [-i port] [-o port]\n"; char usagestr[] = "usage: midicat [-d] [-i in-file] [-o out-file] "
"[-q in-port] [-q out-port]\n";
int int
main(int argc, char **argv) main(int argc, char **argv)
@ -28,25 +30,35 @@ main(int argc, char **argv)
#define MIDI_BUFSZ 1024 #define MIDI_BUFSZ 1024
unsigned char buf[MIDI_BUFSZ]; unsigned char buf[MIDI_BUFSZ];
struct mio_hdl *ih, *oh; struct mio_hdl *ih, *oh;
char *in, *out; char *port0, *port1, *ifile, *ofile;
int dump, c, i, len, sep; int ifd, ofd;
int dump, c, i, len, n, sep, mode;
dump = 0; dump = 0;
in = NULL; port0 = port1 = ifile = ofile = NULL;
out = NULL; ih = oh = NULL;
ih = NULL; ifd = ofd = -1;
oh = NULL;
while ((c = getopt(argc, argv, "di:o:q:")) != -1) {
while ((c = getopt(argc, argv, "di:o:")) != -1) {
switch (c) { switch (c) {
case 'd': case 'd':
dump = 1; dump = 1;
break; break;
case 'q':
if (port0 == NULL)
port0 = optarg;
else if (port1 == NULL)
port1 = optarg;
else {
fputs("too many -q options\n", stderr);
return 1;
}
break;
case 'i': case 'i':
in = optarg; ifile = optarg;
break; break;
case 'o': case 'o':
out = optarg; ofile = optarg;
break; break;
default: default:
goto bad_usage; goto bad_usage;
@ -59,44 +71,106 @@ main(int argc, char **argv)
fputs(usagestr, stderr); fputs(usagestr, stderr);
return 1; return 1;
} }
if (in == NULL && out == NULL) {
fputs("either -i or -o required\n", stderr); /* we don't support more than one data flow */
exit(1); if (ifile != NULL && ofile != NULL) {
fputs("-i and -o are exclusive\n", stderr);
return 1;
} }
if (in) {
ih = mio_open(in, MIO_IN, 0); /* second port makes sense only for port-to-port transfers */
if (ih == NULL) { if (port1 != NULL && !(ifile == NULL && ofile == NULL)) {
fprintf(stderr, "%s: couldn't open MIDI in\n", in); fputs("too many -q options\n", stderr);
exit(1); return 1;
}
} }
if (out) {
oh = mio_open(out, MIO_OUT, 0); /* if there're neither files nor ports, then we've nothing to do */
if (oh == NULL) { if (port0 == NULL && ifile == NULL && ofile == NULL)
fprintf(stderr, "%s: couldn't open MIDI out\n", out); goto bad_usage;
exit(1);
} /* if no port specified, use default one */
} if (port0 == NULL)
for (;;) { port0 = MIO_PORTANY;
if (in) {
len = mio_read(ih, buf, sizeof(buf)); /* open input or output file (if any) */
if (len == 0) { if (ifile) {
fprintf(stderr, "%s: disconnected\n", in); if (strcmp(ifile, "-") == 0)
break; ifd = STDIN_FILENO;
else {
ifd = open(ifile, O_RDONLY, 0);
if (ifd < 0) {
perror(ifile);
return 1;
} }
} else { }
len = read(STDIN_FILENO, buf, sizeof(buf)); } else if (ofile) {
if (strcmp(ofile, "-") == 0)
ofd = STDOUT_FILENO;
else {
ofd = open(ofile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (ofd < 0) {
perror(ofile);
return 1;
}
}
}
/* open first port for input and output (if output needed) */
if (ofile)
mode = MIO_IN;
else if (ifile)
mode = MIO_OUT;
else if (port1 == NULL)
mode = MIO_IN | MIO_OUT;
else
mode = MIO_IN;
ih = mio_open(port0, mode, 0);
if (ih == NULL) {
fprintf(stderr, "%s: couldn't open port\n", port0);
return 1;
}
/* open second port, output only */
if (port1 == NULL)
oh = ih;
else {
oh = mio_open(port1, MIO_OUT, 0);
if (oh == NULL) {
fprintf(stderr, "%s: couldn't open port\n", port1);
exit(1);
}
}
/* transfer until end-of-file or error */
for (;;) {
if (ifile != NULL) {
len = read(ifd, buf, sizeof(buf));
if (len == 0) if (len == 0)
break; break;
if (len < 0) { if (len < 0) {
perror("stdin"); perror("stdin");
exit(1); break;
}
} else {
len = mio_read(ih, buf, sizeof(buf));
if (len == 0) {
fprintf(stderr, "%s: disconnected\n", port0);
break;
}
}
if (ofile != NULL) {
n = write(ofd, buf, len);
if (n != len) {
fprintf(stderr, "%s: short write\n", ofile);
break;
}
} else {
n = mio_write(oh, buf, len);
if (n != len) {
fprintf(stderr, "%s: disconnected\n", port1);
break;
} }
} }
if (out)
mio_write(oh, buf, len);
else
write(STDOUT_FILENO, buf, len);
if (dump) { if (dump) {
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
sep = (i % 16 == 15 || i == len - 1) ? sep = (i % 16 == 15 || i == len - 1) ?
@ -105,9 +179,15 @@ main(int argc, char **argv)
} }
} }
} }
if (in)
/* clean-up */
if (port0)
mio_close(ih); mio_close(ih);
if (out) if (port1)
mio_close(oh); mio_close(oh);
if (ifile)
close(ifd);
if (ofile)
close(ofd);
return 0; return 0;
} }