Skip to content

Instantly share code, notes, and snippets.

@jbarrett
Created February 8, 2023 16:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jbarrett/8f741784fffc12743b24a92fcc2b6910 to your computer and use it in GitHub Desktop.
Save jbarrett/8f741784fffc12743b24a92fcc2b6910 to your computer and use it in GitHub Desktop.
Exploring async event loop integration with RtMidi
#!/usr/bin/env perl
use strict;
use warnings;
use v5.32; # Perl on Windows is still hard...
use experimental 'signatures';
use IO::Async::Timer::Periodic;
use IO::Async::Routine;
use IO::Async::Channel;
use IO::Async::Loop;
use Future::AsyncAwait;
use MIDI::RtMidi::FFI::Device;
use Time::HiRes qw/ gettimeofday tv_interval /;
my $loop = IO::Async::Loop->new;
my $midi_ch = IO::Async::Channel->new;
my $midi_rtn = IO::Async::Routine->new(
channels_out => [ $midi_ch ],
code => sub {
my $midi_in = MIDI::RtMidi::FFI::Device->new( type => 'in' );
$midi_in->open_port_by_name( qr/LKMK3/i ); # LaunchKey Mk 3
$midi_in->set_callback(
sub( $ts, $msg, $data ) {
my $t0 = [ gettimeofday ];
$midi_ch->send( [ $t0, $ts, $msg ] );
}
);
sleep;
}
);
$loop->add( $midi_rtn );
$SIG{TERM} = sub { $midi_rtn->kill('TERM') };
async sub process_midi_events {
while ( my $event = await $midi_ch->recv ) {
say "recv took " . tv_interval( $event->[0] ) . "s";
say unpack 'H*', $event->[2];
}
}
my $tick = 0;
$loop->add( IO::Async::Timer::Periodic->new(
interval => 1,
on_tick => sub { say "Tick " . $tick++; },
)->start );
$loop->await( process_midi_events );
$ ./callback.pl
Tick 0
recv took 0.000653s
903c29
recv took 0.00056s
903c
Tick 1
Tick 2
recv took 0.000302s
903e2c
recv took 0.000324s
903e
Tick 3
recv took 0.000271s
904012
recv took 0.000288s
9040
Tick 4
...
@jbarrett
Copy link
Author

jbarrett commented Feb 8, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment