mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-09 18:05:42 +01:00
amidi: add sysex-interval option
This patch adds a new option to amidi tool: sysex-interval. It adds a delay (in milliseconds) in between each SysEx message - it searches for a 0xF7 byte. This is very useful when sending firmware updates to a remote device via SysEx or any other use that requires this delay in between SysEx messages. `amidi' manual was updated with an example usage as well. Signed-off-by: Felipe F. Tonello <eu@felipetonello.com> Acked-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
7b122fb62a
commit
b59745978f
2 changed files with 86 additions and 18 deletions
|
@ -1,4 +1,4 @@
|
||||||
.TH AMIDI 1 "16 Apr 2016"
|
.TH AMIDI 1 "30 Aug 2016"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
amidi \- read from and write to ALSA RawMIDI ports
|
amidi \- read from and write to ALSA RawMIDI ports
|
||||||
|
@ -120,6 +120,12 @@ received MIDI commands.
|
||||||
Does not ignore Clock bytes (F8h) when saving or printing received
|
Does not ignore Clock bytes (F8h) when saving or printing received
|
||||||
MIDI commands.
|
MIDI commands.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.I \-i, \-\-sysex-interval=mseconds
|
||||||
|
Adds a delay in between each SysEx message sent to a device. It is
|
||||||
|
useful when sending firmware updates via SysEx messages to a remote
|
||||||
|
device.
|
||||||
|
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
|
@ -129,6 +135,14 @@ will send the MIDI commands in
|
||||||
to port
|
to port
|
||||||
.I hw:0.
|
.I hw:0.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B amidi \-p hw:1,0,0 -s firmware.syx \-i 100
|
||||||
|
will send the MIDI commands in
|
||||||
|
.I firmware.syx
|
||||||
|
to port
|
||||||
|
.I hw:1,0,0
|
||||||
|
with 100 milliseconds delay in between each SysEx message.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B amidi \-S 'F0 43 10 4C 00 00 7E 00 F7'
|
.B amidi \-S 'F0 43 10 4C 00 00 7E 00 F7'
|
||||||
sends an XG Reset to the default port.
|
sends an XG Reset to the default port.
|
||||||
|
|
|
@ -52,6 +52,7 @@ static int receive_file;
|
||||||
static int dump;
|
static int dump;
|
||||||
static float timeout;
|
static float timeout;
|
||||||
static int stop;
|
static int stop;
|
||||||
|
static int sysex_interval;
|
||||||
static snd_rawmidi_t *input, **inputp;
|
static snd_rawmidi_t *input, **inputp;
|
||||||
static snd_rawmidi_t *output, **outputp;
|
static snd_rawmidi_t *output, **outputp;
|
||||||
|
|
||||||
|
@ -82,7 +83,8 @@ static void usage(void)
|
||||||
"-t, --timeout=seconds exits when no data has been received\n"
|
"-t, --timeout=seconds exits when no data has been received\n"
|
||||||
" for the specified duration\n"
|
" for the specified duration\n"
|
||||||
"-a, --active-sensing include active sensing bytes\n"
|
"-a, --active-sensing include active sensing bytes\n"
|
||||||
"-c, --clock include clock bytes\n");
|
"-c, --clock include clock bytes\n"
|
||||||
|
"-i, --sysex-interval=mseconds delay in between each SysEx message\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void version(void)
|
static void version(void)
|
||||||
|
@ -230,6 +232,47 @@ static void rawmidi_list(void)
|
||||||
snd_output_close(output);
|
snd_output_close(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int send_midi_interleaved(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
char *data = send_data;
|
||||||
|
size_t buffer_size;
|
||||||
|
snd_rawmidi_params_t *param;
|
||||||
|
snd_rawmidi_status_t *st;
|
||||||
|
|
||||||
|
snd_rawmidi_status_alloca(&st);
|
||||||
|
|
||||||
|
snd_rawmidi_params_alloca(¶m);
|
||||||
|
snd_rawmidi_params_current(output, param);
|
||||||
|
buffer_size = snd_rawmidi_params_get_buffer_size(param);
|
||||||
|
|
||||||
|
while (data < (send_data + send_data_length)) {
|
||||||
|
int len = send_data + send_data_length - data;
|
||||||
|
char *temp;
|
||||||
|
|
||||||
|
if (data > send_data) {
|
||||||
|
snd_rawmidi_status(output, st);
|
||||||
|
do {
|
||||||
|
/* 320 µs per byte as noted in Page 1 of MIDI spec */
|
||||||
|
usleep((buffer_size - snd_rawmidi_status_get_avail(st)) * 320);
|
||||||
|
snd_rawmidi_status(output, st);
|
||||||
|
} while(snd_rawmidi_status_get_avail(st) < buffer_size);
|
||||||
|
usleep(sysex_interval * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find end of SysEx */
|
||||||
|
if ((temp = memchr(data, 0xf7, len)) != NULL)
|
||||||
|
len = temp - data + 1;
|
||||||
|
|
||||||
|
if ((err = snd_rawmidi_write(output, data, len)) < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
data += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void load_file(void)
|
static void load_file(void)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -411,7 +454,7 @@ static void add_send_hex_data(const char *str)
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
static const char short_options[] = "hVlLp:s:r:S::dt:ac";
|
static const char short_options[] = "hVlLp:s:r:S::dt:aci:";
|
||||||
static const struct option long_options[] = {
|
static const struct option long_options[] = {
|
||||||
{"help", 0, NULL, 'h'},
|
{"help", 0, NULL, 'h'},
|
||||||
{"version", 0, NULL, 'V'},
|
{"version", 0, NULL, 'V'},
|
||||||
|
@ -425,6 +468,7 @@ int main(int argc, char *argv[])
|
||||||
{"timeout", 1, NULL, 't'},
|
{"timeout", 1, NULL, 't'},
|
||||||
{"active-sensing", 0, NULL, 'a'},
|
{"active-sensing", 0, NULL, 'a'},
|
||||||
{"clock", 0, NULL, 'c'},
|
{"clock", 0, NULL, 'c'},
|
||||||
|
{"sysex-interval", 1, NULL, 'i'},
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
int c, err, ok = 0;
|
int c, err, ok = 0;
|
||||||
|
@ -474,6 +518,9 @@ int main(int argc, char *argv[])
|
||||||
case 'c':
|
case 'c':
|
||||||
ignore_clock = 0;
|
ignore_clock = 0;
|
||||||
break;
|
break;
|
||||||
|
case 'i':
|
||||||
|
sysex_interval = atoi(optarg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
error("Try `amidi --help' for more information.");
|
error("Try `amidi --help' for more information.");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -549,9 +596,16 @@ int main(int argc, char *argv[])
|
||||||
error("cannot set blocking mode: %s", snd_strerror(err));
|
error("cannot set blocking mode: %s", snd_strerror(err));
|
||||||
goto _exit;
|
goto _exit;
|
||||||
}
|
}
|
||||||
|
if (!sysex_interval) {
|
||||||
if ((err = snd_rawmidi_write(output, send_data, send_data_length)) < 0) {
|
if ((err = snd_rawmidi_write(output, send_data, send_data_length)) < 0) {
|
||||||
error("cannot send data: %s", snd_strerror(err));
|
error("cannot send data: %s", snd_strerror(err));
|
||||||
goto _exit;
|
return err;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((err = send_midi_interleaved()) < 0) {
|
||||||
|
error("cannot send data: %s", snd_strerror(err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue