]> git.alsa-project.org Git - alsa-utils.git/commitdiff
amidi: add timestamp option for dump
authorfolkert van heusden <mail@vanheusden.com>
Tue, 24 Aug 2021 09:49:43 +0000 (11:49 +0200)
committerJaroslav Kysela <perex@perex.cz>
Tue, 24 Aug 2021 10:05:52 +0000 (12:05 +0200)
Added -T / --timestamp option (with parameter "realtime", "monotonic" or "raw") which prints
a timestamp before each received message when using the --dump mode.

Fixes: https://github.com/alsa-project/alsa-utils/pull/108
Signed-off-by: Folkert van Heusden <mail@vanheusden.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
amidi/amidi.c

index 90e77501a04b263ab45504dde1be75782c0d23f5..8e97cb801b7dac71af8814627c356e267f786390 100644 (file)
 #include <unistd.h>
 #include <fcntl.h>
 #include <alsa/asoundlib.h>
+#include <time.h>
 #include "aconfig.h"
 #include "version.h"
 
 #define NSEC_PER_SEC 1000000000L
 
+static int do_print_timestamp = 0;
 static int do_device_list, do_rawmidi_list;
 static char *port_name = "default";
 static char *send_file_name;
@@ -80,6 +82,10 @@ static void usage(void)
                "-r, --receive=file              write received data into a file\n"
                "-S, --send-hex=\"...\"            send hexadecimal bytes\n"
                "-d, --dump                      print received data as hexadecimal bytes\n"
+               "-T, --timestamp=...             adds a timestamp in front of each dumped message\n"
+               "                realtime\n"
+               "                monotonic\n"
+               "                raw\n"
                "-t, --timeout=seconds           exits when no data has been received\n"
                "                                for the specified duration\n"
                "-a, --active-sensing            include active sensing bytes\n"
@@ -356,7 +362,7 @@ static void parse_data(void)
 /*
  * prints MIDI commands, formatting them nicely
  */
-static void print_byte(unsigned char byte)
+static void print_byte(unsigned char byte, struct timespec *ts)
 {
        static enum {
                STATE_UNKNOWN,
@@ -426,7 +432,18 @@ static void print_byte(unsigned char byte)
                if (running_status)
                        fputs("\n  ", stdout);
        }
-       printf("%c%02X", newline ? '\n' : ' ', byte);
+
+       if (newline) {
+               printf("\n");
+
+               /* Nanoseconds does not make a lot of sense for serial MIDI (the
+                * 31250 bps one) but I'm not sure about MIDI over USB.
+                */
+               if (do_print_timestamp)
+                       printf("%lld.%.9ld) ", (long long)ts->tv_sec, ts->tv_nsec);
+       }
+
+       printf("%02X", byte);
 }
 
 static void sig_handler(int dummy)
@@ -454,7 +471,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:aci:";
+       static const char short_options[] = "hVlLp:s:r:S::dt:aci:T:";
        static const struct option long_options[] = {
                {"help", 0, NULL, 'h'},
                {"version", 0, NULL, 'V'},
@@ -465,6 +482,7 @@ int main(int argc, char *argv[])
                {"receive", 1, NULL, 'r'},
                {"send-hex", 2, NULL, 'S'},
                {"dump", 0, NULL, 'd'},
+               {"timestamp", 1, NULL, 'T'},
                {"timeout", 1, NULL, 't'},
                {"active-sensing", 0, NULL, 'a'},
                {"clock", 0, NULL, 'c'},
@@ -475,6 +493,7 @@ int main(int argc, char *argv[])
        int ignore_active_sensing = 1;
        int ignore_clock = 1;
        int do_send_hex = 0;
+       clockid_t cid = CLOCK_REALTIME;
        struct itimerspec itimerspec = { .it_interval = { 0, 0 } };
 
        while ((c = getopt_long(argc, argv, short_options,
@@ -509,6 +528,19 @@ int main(int argc, char *argv[])
                case 'd':
                        dump = 1;
                        break;
+               case 'T':
+                       do_print_timestamp = 1;
+                       if (optarg == NULL)
+                               error("Clock type missing");
+                       else if (strcasecmp(optarg, "realtime") == 0)
+                               cid = CLOCK_REALTIME;
+                       else if (strcasecmp(optarg, "monotonic") == 0)
+                               cid = CLOCK_MONOTONIC;
+                       else if (strcasecmp(optarg, "raw") == 0)
+                               cid = CLOCK_MONOTONIC_RAW;
+                       else
+                               error("Clock type not known");
+                       break;
                case 't':
                        if (optarg)
                                timeout = atof(optarg);
@@ -611,6 +643,7 @@ int main(int argc, char *argv[])
        }
 
        if (inputp) {
+               int need_timestamp = 0;
                int read = 0;
                int npfds;
                struct pollfd *pfds;
@@ -644,10 +677,12 @@ int main(int argc, char *argv[])
                                goto _exit;
                        }
                }
+
                for (;;) {
                        unsigned char buf[256];
                        int i, length;
                        unsigned short revents;
+                       struct timespec ts;
 
                        err = poll(pfds, npfds, -1);
                        if (stop || (err < 0 && errno == EINTR))
@@ -657,6 +692,11 @@ int main(int argc, char *argv[])
                                break;
                        }
 
+                       if (clock_gettime(cid, &ts) < 0) {
+                               error("clock_getres (%d) failed: %s", cid, strerror(errno));
+                               break;
+                       }
+
                        err = snd_rawmidi_poll_descriptors_revents(input, &pfds[1], npfds - 1, &revents);
                        if (err < 0) {
                                error("cannot get poll events: %s", snd_strerror(errno));
@@ -688,14 +728,12 @@ int main(int argc, char *argv[])
                                continue;
                        read += length;
 
-                       if (receive_file != -1) {
-                               ssize_t wlength = write(receive_file, buf, length);
-                               if (wlength != length)
-                                       error("write error: %s", wlength < 0 ? strerror(errno) : "short");
-                       }
+                       if (receive_file != -1)
+                               write(receive_file, buf, length);
                        if (dump) {
                                for (i = 0; i < length; ++i)
-                                       print_byte(buf[i]);
+                                       print_byte(buf[i], &ts);
+
                                fflush(stdout);
                        }