[alsa-devel] [PATCH v2 0/2] amidi delay option
Small improvement to amidi, adding useful functionality.
changes from v1: * remove delay in between any MIDI message, only SysEx * added patch to use getopt_long() arguments
Felipe F. Tonello (2): amidi: add delay option amidi: use GNU getopt_long() proper argument names
amidi/amidi.1 | 14 +++++++++++++ amidi/amidi.c | 66 ++++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 64 insertions(+), 16 deletions(-)
This patch adds a new options to amidi tool to add a delay (in milliseconds) to each MIDI message.
This is very useful when sending firmware updates to a remote device via SysEx or any other use that requires this delay in between messages.
Signed-off-by: Felipe F. Tonello eu@felipetonello.com --- amidi/amidi.1 | 14 ++++++++++++++ amidi/amidi.c | 44 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 5 deletions(-)
diff --git a/amidi/amidi.1 b/amidi/amidi.1 index 1b4cfb1ea956..391008177610 100644 --- a/amidi/amidi.1 +++ b/amidi/amidi.1 @@ -111,6 +111,12 @@ to stop receiving data. Does not ignore Active Sensing bytes (FEh) when saving or printing received MIDI commands.
+.TP +.I -D, --delay=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
.TP @@ -121,6 +127,14 @@ to port .I hw:0.
.TP +.B amidi -p hw:1,0,0 -s firmware.syx -D 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 .B amidi -S 'F0 43 10 4C 00 00 7E 00 F7' sends an XG Reset to the default port.
diff --git a/amidi/amidi.c b/amidi/amidi.c index cedf18c5fd39..f726824723fb 100644 --- a/amidi/amidi.c +++ b/amidi/amidi.c @@ -48,6 +48,7 @@ static int receive_file; static int dump; static int timeout; static int stop; +static int delay; static snd_rawmidi_t *input, **inputp; static snd_rawmidi_t *output, **outputp;
@@ -77,7 +78,8 @@ static void usage(void) "-d, --dump print received data as hexadecimal bytes\n" "-t, --timeout=seconds exits when no data has been received\n" " for the specified duration\n" - "-a, --active-sensing don't ignore active sensing bytes\n"); + "-a, --active-sensing don't ignore active sensing bytes\n" + "-D, --delay=mseconds delay in between each SysEx message\n"); }
static void version(void) @@ -406,7 +408,7 @@ static void add_send_hex_data(const char *str)
int main(int argc, char *argv[]) { - static const char short_options[] = "hVlLp:s:r:S::dt:a"; + static const char short_options[] = "hVlLp:s:r:S::dt:aD:"; static const struct option long_options[] = { {"help", 0, NULL, 'h'}, {"version", 0, NULL, 'V'}, @@ -419,6 +421,7 @@ int main(int argc, char *argv[]) {"dump", 0, NULL, 'd'}, {"timeout", 1, NULL, 't'}, {"active-sensing", 0, NULL, 'a'}, + {"delay", 1, NULL, 'D'}, { } }; int c, err, ok = 0; @@ -463,6 +466,9 @@ int main(int argc, char *argv[]) case 'a': ignore_active_sensing = 0; break; + case 'D': + delay = atoi(optarg); + break; default: error("Try `amidi --help' for more information."); return 1; @@ -538,9 +544,37 @@ int main(int argc, char *argv[]) error("cannot set blocking mode: %s", snd_strerror(err)); goto _exit; } - if ((err = snd_rawmidi_write(output, send_data, send_data_length)) < 0) { - error("cannot send data: %s", snd_strerror(err)); - goto _exit; + if (!delay) { + if ((err = snd_rawmidi_write(output, send_data, send_data_length)) < 0) { + error("cannot send data: %s", snd_strerror(err)); + return err; + } + } else { + char *data = send_data; + + while (data < (send_data + send_data_length)) { + int len = 0; + + if (data > send_data) + usleep(delay * 1000); + + /* find beginning of SysEx and its end */ + while((unsigned char)data[len] != 0xf0 && + (data + len) < (send_data + send_data_length)) + len++; + + while((unsigned char)data[len] != 0xf7 && + (data + len) < (send_data + send_data_length)) + len++; + len++; + + if ((err = snd_rawmidi_write(output, data, len)) < 0) { + error("cannot send data: %s", snd_strerror(err)); + return err; + } + + data += len; + } } }
Felipe F. Tonello wrote:
This patch adds a new options to amidi tool to add a delay (in milliseconds) to each MIDI message.
^^^^ Not anymore.
if (!delay) {
if ((err = snd_rawmidi_write(output, send_data, send_data_length)) < 0) {
error("cannot send data: %s", snd_strerror(err));
return err;
}
} else {
Too much indentation.
/* find beginning of SysEx and its end */
while((unsigned char)data[len] != 0xf0 &&
(data + len) < (send_data + send_data_length))
len++;
while((unsigned char)data[len] != 0xf7 &&
(data + len) < (send_data + send_data_length))
len++;
len++;
It is not necessary to search for both beginning and end.
And the search can be simplified with memchr().
Regards, Clemens
Hi Clemens,
On 13/08/16 12:51, Clemens Ladisch wrote:
Felipe F. Tonello wrote:
This patch adds a new options to amidi tool to add a delay (in milliseconds) to each MIDI message.
^^^^
Not anymore.
Right..
if (!delay) {
if ((err = snd_rawmidi_write(output, send_data, send_data_length)) < 0) {
error("cannot send data: %s", snd_strerror(err));
return err;
}
} else {
Too much indentation.
/* find beginning of SysEx and its end */
while((unsigned char)data[len] != 0xf0 &&
(data + len) < (send_data + send_data_length))
len++;
while((unsigned char)data[len] != 0xf7 &&
(data + len) < (send_data + send_data_length))
len++;
len++;
It is not necessary to search for both beginning and end.
Ok, but it will sleep on malformed SysEx messages, though.
And the search can be simplified with memchr().
Ok.
This has no affect besides more clarity to the code.
Signed-off-by: Felipe F. Tonello eu@felipetonello.com --- amidi/amidi.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/amidi/amidi.c b/amidi/amidi.c index f726824723fb..150d9291f409 100644 --- a/amidi/amidi.c +++ b/amidi/amidi.c @@ -410,18 +410,18 @@ int main(int argc, char *argv[]) { static const char short_options[] = "hVlLp:s:r:S::dt:aD:"; static const struct option long_options[] = { - {"help", 0, NULL, 'h'}, - {"version", 0, NULL, 'V'}, - {"list-devices", 0, NULL, 'l'}, - {"list-rawmidis", 0, NULL, 'L'}, - {"port", 1, NULL, 'p'}, - {"send", 1, NULL, 's'}, - {"receive", 1, NULL, 'r'}, - {"send-hex", 2, NULL, 'S'}, - {"dump", 0, NULL, 'd'}, - {"timeout", 1, NULL, 't'}, - {"active-sensing", 0, NULL, 'a'}, - {"delay", 1, NULL, 'D'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {"list-devices", no_argument, NULL, 'l'}, + {"list-rawmidis", no_argument, NULL, 'L'}, + {"port", required_argument, NULL, 'p'}, + {"send", required_argument, NULL, 's'}, + {"receive", required_argument, NULL, 'r'}, + {"send-hex", optional_argument, NULL, 'S'}, + {"dump", no_argument, NULL, 'd'}, + {"timeout", required_argument, NULL, 't'}, + {"active-sensing", no_argument, NULL, 'a'}, + {"delay", required_argument, NULL, 'D'}, { } }; int c, err, ok = 0;
participants (3)
-
Clemens Ladisch
-
Felipe F. Tonello
-
Felipe Ferreri Tonello