use MIDI::ALSA (':CONSTS');
use Term::ANSIColor qw(:constants);
use strict;

local $Term::ANSIColor::AUTORESET = 1;
#---- Variables --------------------------------------
my $programVersion = "2015-12-12_1.14";
my $debug = 0;
my $k = "";
my $v = "";
my %clientnumber2clientname;
my %clientnumber2howmanyports;
my $keyboardPort = 0;
my $synthiPort = 0;
my $tst = SND_SEQ_EVENT_NOTEON();
my $channel = 0;
my $midiByte1 = 0;
my $midiByte2 = 0;
my $midiByte3 = 0;
my $keyboardClientNo = 0;
my $synthiClientNo = 0;
my $noValidMidiClients = 1;
my $processMidiEvents = 1;
my $retVal = 0;
my @alsaevent;
#-----------------------------------------------------
sub wait_seconds($)
{
my ($wait_time) = @_;
my $start = 0;
my $stop  = 0;
    $start = time;
    $stop  = time;
    while (($stop - $start) < $wait_time)
    {
          $stop  = time;
    }
    return 0;
}
#---- Functions --------------------------------------

#-----------------------------------------------------

print BOLD YELLOW "midiRouter.pl : $programVersion\r\n";

MIDI::ALSA::client( 'Raspi MIDI::ALSA cient', 2, 2, 0);

while ($noValidMidiClients)
{
      %clientnumber2clientname = MIDI::ALSA::listclients();
      while ( ($k,$v) = each %clientnumber2clientname )
      {
            if ($debug)
            {
	       print BOLD GREEN "$k => $v\n";
            }	
            if ($v =~ /CASIO/)
            {
	       $keyboardPort = 1;
	       $keyboardClientNo = $k;
            }
            if ($v =~ /USB2.0/)
            {
	       $synthiPort = 1;
	       $synthiClientNo = $k;
            }
      }

      if (($keyboardPort+$synthiPort) < 2) 
      {
         print BOLD RED "\r\nNo matching MIDI-ports found!";
         print " (key:$keyboardPort|syn:$synthiPort)";
	 $retVal = wait_seconds(10);
      }
      else
      {
         $noValidMidiClients = 0;
	 print BOLD GREEN "\r\nMatching MIDI-ports found.\r\n";
      }
}      

#%clientnumber2howmanyports = MIDI::ALSA::listnumports();
#while ( ($k,$v) = each %clientnumber2howmanyports ) {
#    if ($debug)
#    {
#	print "$k => $v\n";
#    }
#}

MIDI::ALSA::connectfrom( 0, 'CASIO' );  # CASIO USB-MIDI-OUT
MIDI::ALSA::connectto( 1, 'USB2.0' );   # USB2.0-MIDI-IF-IN
MIDI::ALSA::connectfrom( 0, 'USB2.0' );  # USB2.0 USB-MIDI-OUT
MIDI::ALSA::connectto( 1, 'CASIO' );   # CASIO-MIDI-IF-IN

while ($processMidiEvents) {
    @alsaevent = MIDI::ALSA::input();
    if ($alsaevent[0] == SND_SEQ_EVENT_PORT_UNSUBSCRIBED()) { last; }
    if ($alsaevent[0] == SND_SEQ_EVENT_NOTEON() ||
        $alsaevent[0] == SND_SEQ_EVENT_NOTEOFF()) {
	if ($alsaevent[5][0] == $keyboardClientNo)
	{
	   print BOLD CYAN "CASIO ::";
	}
	elsif ($alsaevent[5][0] == $synthiClientNo)
	{
	   print BOLD MAGENTA "USB2.0::";
	}
	$channel   = $alsaevent[7][0];
	if ($alsaevent[0] == SND_SEQ_EVENT_NOTEOFF())
	{
	   $midiByte1 = $channel+0x80;
	}
	else
	{
	   $midiByte1 = $channel+0x90;
	}   
        $midiByte2 = $alsaevent[7][1];
        $midiByte3 = $alsaevent[7][2];
	print "mb1: $midiByte1 | mb2: $midiByte2 | mb3: $midiByte3\r\n";
    } elsif ($alsaevent[0] == SND_SEQ_EVENT_CONTROLLER()) {
        if ($alsaevent[5][0] == $keyboardClientNo)
	{
	   print BOLD CYAN "CASIO ::";
	}
	elsif ($alsaevent[5][0] == $synthiClientNo)
	{
	   print BOLD MAGENTA "USB2.0::";
	}
        $channel    = $alsaevent[7][0];
	$midiByte1  = $channel+0xB0;
        $midiByte2  = $alsaevent[7][4];
        $midiByte3  = $alsaevent[7][5];
	if (($midiByte1 >= 0xB0) && ($midiByte2 == 0) && ($midiByte3 == 0))
	{
	   $processMidiEvents = 0;
	}
	print "mb1: $midiByte1 | mb2: $midiByte2 | mb3: $midiByte3\r\n";	
    }
    MIDI::ALSA::output( @alsaevent );
}

MIDI::ALSA::disconnectfrom( 0, 'CASIO' );  # CASIO USB-MIDI
MIDI::ALSA::disconnectto( 1, 'USB2.0' );   # USB2.0-MIDI-IF    
MIDI::ALSA::disconnectfrom( 1, 'CASIO' );  # CASIO USB-MIDI
MIDI::ALSA::disconnectto( 0, 'USB2.0' );   # USB2.0-MIDI-IF

