Skip to content
Snippets Groups Projects
Commit 125e130f authored by Matthew Hodgson's avatar Matthew Hodgson
Browse files

lost stuff from the MIDI hackathon

parent 7779ecc1
No related branches found
No related tags found
No related merge requests found
#!/opt/local/bin/perl
use strict;
use warnings;
use Data::Dumper;
use IO::Async::Loop;
use Net::Async::Matrix;
use Net::Pcap;
use Data::HexDump;
use JSON;
use Music::Chord::Namer qw/chordname/;
$| = 1;
our $notes = {};
our $notenames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];
our $room;
my $loop = IO::Async::Loop->new;
my $matrix = Net::Async::Matrix->new(
server => "echo-matrix:8008",
on_log => sub { warn "log: @_\n" },
on_room_new => sub {
my ($matrix, $new_room) = @_;
warn "[Matrix] have a room ID: " . $new_room->room_id . "\n";
$room = $new_room if ($new_room->room_id eq '!GaUcuyvZyXfoqmQTNR:echo-matrix');
},
on_error => sub {
print STDERR "Matrix failure: @_\n";
},
);
$loop->add( $matrix );
$matrix->login(
# XXX: password is broke
user_id => 'matthew',
access_token => 'QG1hdHRoZXc6ZWNoby1tYXRyaXg..ZVZbCQuOmnhwakNnOt',
)->get;
$matrix->join_room( '#midi:echo-matrix' )->get;
# ->on_done(sub {
# print Dumper([@_]);
# ($room) = @_;
# warn "joined $room";
# } )->get;
$matrix->start();
my $err = '';
my $dev = "en1";
my $pcap = pcap_open_live($dev, 1024, 0, 100, \$err);
die $err if $err;
my ($net, $mask);
pcap_lookupnet($dev, \$net, \$mask, \$err);
die $err if $err;
my $filter_str = "src host 10.12.76.65 and udp and port 5005";
my $filter;
if (pcap_compile($pcap, \$filter, $filter_str, 1, $net) == -1) {
die "Unable to compile filter string '$filter_str'\n";
}
pcap_setfilter($pcap, $filter);
while (1) {
pcap_dispatch($pcap, -1, \&process_packet, "");
#print ".\n";
}
pcap_close($pcap);
sub handle_event {
my ($event) = @_;
print to_json($event, { pretty => 1 });
if ($event->{state} eq 'on') {
$notes->{$event->{note}} = 1;
}
else {
delete $notes->{$event->{note}};
}
if (scalar keys %$notes >= 3) {
my $chord = (chordname(map { $notenames->[$_ % 12] } sort keys %$notes))[0];
print "$chord\n";
$room->send_message( $chord )->get;
}
# HACK HACK HACK HACK
$room->_do_POST_json( "/send/org.matrix.midi", $event )->get;
}
sub process_packet {
my ($user_data, $header, $packet) = @_;
my ($ether, $ip, $udp, $rtp_byte, $payload, $seqnum, $ts, $ssrc, @midi)
= unpack("a14a20a8CCSNNC*", $packet);
return if ($rtp_byte == 0xff);
#print HexDump $packet;
my $midilen;
if ($midi[0] & 0x80) { # long header
$midilen = (($midi[0] & 0x0f) << 8) | $midi[1];
shift @midi;
shift @midi;
}
else { # short header
$midilen = ($midi[0] & 0x0f);
shift @midi;
}
my $midiparsed = 0;
my $state = ($midi[0] >> 4 == 0x9 ? "on" : "off");
my $channel = ($midi[0] & 0x0f) + 1;
shift (@midi); $midiparsed++;
while ($midiparsed < $midilen) {
my ($event) = {
midi_ts => $ts,
note => $midi[0],
channel => $channel,
state => ($midi[1] == 0 ? "off" : $state),
velocity => $midi[1],
};
handle_event($event);
shift (@midi); $midiparsed++;
shift (@midi); $midiparsed++;
if (scalar @midi) {
$ts += shift @midi; $midiparsed++;
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment