-
Notifications
You must be signed in to change notification settings - Fork 0
/
rmidid
executable file
·148 lines (127 loc) · 3.73 KB
/
rmidid
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/perl
# vi:set sw=2 ai sm:
# TEST program to shuffle MIDI messages between two Linux boxes
use strict;
use integer;
use JSON;
use MIDI::ALSA(':CONSTS');
use IO::Socket::INET;
use Getopt::Long;
use Time::HiRes;
use Data::Dumper;
use vars qw( $appName );
$appName = 'rmidid';
use vars qw( $from $to );
use vars qw( $verbose_p );
use vars qw( $get_data $send_data );
use vars qw( $port );
use vars qw( $remote_input_p );
$port = 19798;
$remote_input_p = 0;
sub display_help_and_exit (;$) {
my($st) = @_;
my $h = $st? *STDERR: *STDOUT;
print $h <<EOF;
Usage: $appName [OPTION]...
Send and receive MIDI events between ALSA or UDP peers.
-f, --from=NAME get MIDI input from ALSA port or network address NAME
-t, --to=NAME send MIDI output to ALSA port or network address NAME
-v, --verbose display debug messages
--help display this help and exit
This is just a test program to make sure communication is possible.
EOF
exit $st;
}
sub log_something ($$) {
my($s, $flag) = @_;
no integer;
$s =~ s/\n+$//s;
printf "%10.4f%s\t%s\n", Time::HiRes::time, $flag, $s;
}
sub log_input ($) { log_something($_[0], '<') }
sub log_output ($) { log_something($_[0], '>') }
sub log_debug ($) { log_something($_[0], '#') }
Getopt::Long::Configure('bundling');
$Data::Dumper::Indent = 0;
$Data::Dumper::Terse = 1;
GetOptions(
'from|f|i=s' => \$from,
'to|t|o=s' => \$to,
'verbose|v+' => \$verbose_p,
'help' => \&display_help_and_exit,
) || exit(1);
MIDI::ALSA::client($appName, 1, 1, 0);
if ($from =~ /^\d+:\d+$/) {
MIDI::ALSA::connectfrom(0, $from) or die "$appName: $from: Failed to connect\n";
$get_data = sub {
my $s = [ MIDI::ALSA::input ];
log_input Dumper $s if $verbose_p > 1;
$s;
};
log_debug "connected via ALSA to input $from\n" if $verbose_p;
} elsif ($from =~ /^(\d+\.\d+\.\d+\.\d+)(?::(\d+))?$/) {
my $socket = new IO::Socket::INET(
LocalAddr => '0.0.0.0',
LocalPort => $port,
Proto => 'udp'
) or die "$appName: $from: $!\n";
$get_data = sub {
my $s;
my $st = $socket->recv($s, 1024);
log_input Dumper $s if $verbose_p > 1;
if (defined $st) {
log_debug "recv returned $st" if $verbose_p > 2;
} else {
log_debug "recv failed: $!";
}
if (defined $s) {
$s = decode_json $s;
}
$s;
};
$remote_input_p = 1;
log_debug "connected via UDP to input $from\n" if $verbose_p;
} else {
die "$appName: $from: Not numeric ALSA client:port or IPv4 address:port\n";
}
if ($to =~ /^(\d+):(\d+)$/) {
my($to_client, $to_port) = ($1 + 0, $2 + 0);
my $from_client = MIDI::ALSA::id;
MIDI::ALSA::connectto(0, $to) or die "$appName: $to: Failed to connect\n";
$send_data = sub {
my($s) = @_;
my($type, $flags, $tag, $queue, $time, $source, $destination, $data) = @$s;
if ($remote_input_p) {
$source = [$from_client, 0];
$destination = [$to_client, $to_port];
}
log_output Dumper [$type, $flags, $tag, $queue, $time, $source, $destination, $data] if $verbose_p > 1;
MIDI::ALSA::output($type, $flags, $tag, $queue, $time, $source, $destination, $data);
};
log_debug "connected via ALSA to output $to\n" if $verbose_p;
} elsif ($to =~ /^(\d+\.\d+\.\d+\.\d+)(?::(\d+))?$/) {
my $socket = new IO::Socket::INET(
LocalPort => $port,
PeerAddr => $to,
Proto => 'udp'
) or die "$appName: $to: $!\n";
$send_data = sub {
my($s) = @_;
$s = encode_json $s;
my $st = $socket->send($s);
log_output Dumper $s if $verbose_p > 1;
if (defined $st) {
log_debug "send returned $st" if $verbose_p > 2;
} else {
log_debug "send failed: $!";
}
$st;
};
log_debug "connected via UDP to output $to\n" if $verbose_p;
} else {
die "$appName: $from: Not numeric ALSA client:port or IPv4 address:port\n";
}
for (;;) {
my $s = &$get_data;
&$send_data($s);
}