mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-10 00:35:42 +01:00
amidi: add timestamp option for dump
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>
This commit is contained in:
parent
dea51861a8
commit
9a8fcec5aa
1 changed files with 47 additions and 9 deletions
|
@ -36,11 +36,13 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <alsa/asoundlib.h>
|
#include <alsa/asoundlib.h>
|
||||||
|
#include <time.h>
|
||||||
#include "aconfig.h"
|
#include "aconfig.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#define NSEC_PER_SEC 1000000000L
|
#define NSEC_PER_SEC 1000000000L
|
||||||
|
|
||||||
|
static int do_print_timestamp = 0;
|
||||||
static int do_device_list, do_rawmidi_list;
|
static int do_device_list, do_rawmidi_list;
|
||||||
static char *port_name = "default";
|
static char *port_name = "default";
|
||||||
static char *send_file_name;
|
static char *send_file_name;
|
||||||
|
@ -80,6 +82,10 @@ static void usage(void)
|
||||||
"-r, --receive=file write received data into a file\n"
|
"-r, --receive=file write received data into a file\n"
|
||||||
"-S, --send-hex=\"...\" send hexadecimal bytes\n"
|
"-S, --send-hex=\"...\" send hexadecimal bytes\n"
|
||||||
"-d, --dump print received data as 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"
|
"-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"
|
||||||
|
@ -356,7 +362,7 @@ static void parse_data(void)
|
||||||
/*
|
/*
|
||||||
* prints MIDI commands, formatting them nicely
|
* 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 {
|
static enum {
|
||||||
STATE_UNKNOWN,
|
STATE_UNKNOWN,
|
||||||
|
@ -426,7 +432,18 @@ static void print_byte(unsigned char byte)
|
||||||
if (running_status)
|
if (running_status)
|
||||||
fputs("\n ", stdout);
|
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)
|
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[])
|
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[] = {
|
static const struct option long_options[] = {
|
||||||
{"help", 0, NULL, 'h'},
|
{"help", 0, NULL, 'h'},
|
||||||
{"version", 0, NULL, 'V'},
|
{"version", 0, NULL, 'V'},
|
||||||
|
@ -465,6 +482,7 @@ int main(int argc, char *argv[])
|
||||||
{"receive", 1, NULL, 'r'},
|
{"receive", 1, NULL, 'r'},
|
||||||
{"send-hex", 2, NULL, 'S'},
|
{"send-hex", 2, NULL, 'S'},
|
||||||
{"dump", 0, NULL, 'd'},
|
{"dump", 0, NULL, 'd'},
|
||||||
|
{"timestamp", 1, NULL, 'T'},
|
||||||
{"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'},
|
||||||
|
@ -475,6 +493,7 @@ int main(int argc, char *argv[])
|
||||||
int ignore_active_sensing = 1;
|
int ignore_active_sensing = 1;
|
||||||
int ignore_clock = 1;
|
int ignore_clock = 1;
|
||||||
int do_send_hex = 0;
|
int do_send_hex = 0;
|
||||||
|
clockid_t cid = CLOCK_REALTIME;
|
||||||
struct itimerspec itimerspec = { .it_interval = { 0, 0 } };
|
struct itimerspec itimerspec = { .it_interval = { 0, 0 } };
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, short_options,
|
while ((c = getopt_long(argc, argv, short_options,
|
||||||
|
@ -509,6 +528,19 @@ int main(int argc, char *argv[])
|
||||||
case 'd':
|
case 'd':
|
||||||
dump = 1;
|
dump = 1;
|
||||||
break;
|
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':
|
case 't':
|
||||||
if (optarg)
|
if (optarg)
|
||||||
timeout = atof(optarg);
|
timeout = atof(optarg);
|
||||||
|
@ -611,6 +643,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inputp) {
|
if (inputp) {
|
||||||
|
int need_timestamp = 0;
|
||||||
int read = 0;
|
int read = 0;
|
||||||
int npfds;
|
int npfds;
|
||||||
struct pollfd *pfds;
|
struct pollfd *pfds;
|
||||||
|
@ -644,10 +677,12 @@ int main(int argc, char *argv[])
|
||||||
goto _exit;
|
goto _exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
unsigned char buf[256];
|
unsigned char buf[256];
|
||||||
int i, length;
|
int i, length;
|
||||||
unsigned short revents;
|
unsigned short revents;
|
||||||
|
struct timespec ts;
|
||||||
|
|
||||||
err = poll(pfds, npfds, -1);
|
err = poll(pfds, npfds, -1);
|
||||||
if (stop || (err < 0 && errno == EINTR))
|
if (stop || (err < 0 && errno == EINTR))
|
||||||
|
@ -657,6 +692,11 @@ int main(int argc, char *argv[])
|
||||||
break;
|
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);
|
err = snd_rawmidi_poll_descriptors_revents(input, &pfds[1], npfds - 1, &revents);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
error("cannot get poll events: %s", snd_strerror(errno));
|
error("cannot get poll events: %s", snd_strerror(errno));
|
||||||
|
@ -688,14 +728,12 @@ int main(int argc, char *argv[])
|
||||||
continue;
|
continue;
|
||||||
read += length;
|
read += length;
|
||||||
|
|
||||||
if (receive_file != -1) {
|
if (receive_file != -1)
|
||||||
ssize_t wlength = write(receive_file, buf, length);
|
write(receive_file, buf, length);
|
||||||
if (wlength != length)
|
|
||||||
error("write error: %s", wlength < 0 ? strerror(errno) : "short");
|
|
||||||
}
|
|
||||||
if (dump) {
|
if (dump) {
|
||||||
for (i = 0; i < length; ++i)
|
for (i = 0; i < length; ++i)
|
||||||
print_byte(buf[i]);
|
print_byte(buf[i], &ts);
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue