[alsa-devel] [PATCH v3 0/2] amidi delay option
Small improvement to amidi, adding useful functionality.
change from v2: * only check of end of sysex (0xf7) * use memchr() instead of direct loop approach * fixed commit message
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 | 60 +++++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 58 insertions(+), 16 deletions(-)
This patch adds a new options to amidi tool to add a delay (in milliseconds) to each SysEx 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 | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 47 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..a1cb77f362bd 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,31 @@ 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; + + if (data > send_data) + usleep(delay * 1000); + + /* find end of SysEx */ + len = (char *)memchr(data, 0xf7, (send_data + send_data_length) - data) + - data + 1; + + if ((err = snd_rawmidi_write(output, data, len)) < 0) { + error("cannot send data: %s", snd_strerror(err)); + return err; + } + + data += len; + } } }
On 15/08/16 16:36, Felipe F. Tonello wrote:
This patch adds a new options to amidi tool to add a delay (in milliseconds) to each SysEx 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 | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 47 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..a1cb77f362bd 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'},
{ } }; int c, err, ok = 0;{"delay", 1, NULL, 'D'},
@@ -463,6 +466,9 @@ int main(int argc, char *argv[]) case 'a': ignore_active_sensing = 0; break;
case 'D':
delay = atoi(optarg);
default: error("Try `amidi --help' for more information."); return 1;break;
@@ -538,9 +544,31 @@ 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;
if (data > send_data)
usleep(delay * 1000);
/* find end of SysEx */
len = (char *)memchr(data, 0xf7, (send_data + send_data_length) - data)
- data + 1;
There is a bug in here if memchr returns NULL. I will fix it and send a v4.
if ((err = snd_rawmidi_write(output, data, len)) < 0) {
error("cannot send data: %s", snd_strerror(err));
return err;
}
data += len;
} }}
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 a1cb77f362bd..f8a8ca8031e5 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 (2)
-
Felipe F. Tonello
-
Felipe Ferreri Tonello